1: /*
   2:  * Copyright (c) 1980 Regents of the University of California.
   3:  * All rights reserved.  The Berkeley software License Agreement
   4:  * specifies the terms and conditions for redistribution.
   5:  */
   6: 
   7: #if !defined(lint) && defined(DOSCCS)
   8: static char sccsid[] = "@(#)utilities.c	5.2 (Berkeley) 9/10/85";
   9: #endif not lint
  10: 
  11: #include <stdio.h>
  12: #include <ctype.h>
  13: #include <sys/param.h>
  14: #include <sys/inode.h>
  15: #include <sys/fs.h>
  16: #include <sys/dir.h>
  17: #include "fsck.h"
  18: 
  19: long    lseek();
  20: 
  21: ftypeok(dp)
  22:     DINODE *dp;
  23: {
  24:     switch (dp->di_mode & IFMT) {
  25: 
  26:     case IFDIR:
  27:     case IFREG:
  28:     case IFBLK:
  29:     case IFCHR:
  30:     case IFLNK:
  31:     case IFSOCK:
  32:         return (1);
  33: 
  34:     default:
  35:         if (debug)
  36:             printf("bad file type 0%o\n", dp->di_mode);
  37:         return (0);
  38:     }
  39: }
  40: 
  41: reply(s)
  42:     char *s;
  43: {
  44:     char line[80];
  45: 
  46:     if (preen)
  47:         pfatal("INTERNAL ERROR: GOT TO reply()");
  48:     printf("\n%s? ", s);
  49:     if (nflag || dfile.wfdes < 0) {
  50:         printf(" no\n\n");
  51:         return (0);
  52:     }
  53:     if (yflag) {
  54:         printf(" yes\n\n");
  55:         return (1);
  56:     }
  57:     if (getline(stdin, line, sizeof(line)) == EOF)
  58:         errexit("\n");
  59:     printf("\n");
  60:     if (line[0] == 'y' || line[0] == 'Y')
  61:         return (1);
  62:     else
  63:         return (0);
  64: }
  65: 
  66: getline(fp, loc, maxlen)
  67:     FILE *fp;
  68:     char *loc;
  69: {
  70:     register n;
  71:     register char *p, *lastloc;
  72: 
  73:     p = loc;
  74:     lastloc = &p[maxlen-1];
  75:     while ((n = getc(fp)) != '\n') {
  76:         if (n == EOF)
  77:             return (EOF);
  78:         if (!isspace(n) && p < lastloc)
  79:             *p++ = n;
  80:     }
  81:     *p = 0;
  82:     return (p - loc);
  83: }
  84: 
  85: BUFAREA *
  86: getblk(bp, blk)
  87:     register BUFAREA *bp;
  88:     daddr_t blk;
  89: {
  90:     register struct filecntl *fcp;
  91:     extern BUFAREA *search();
  92: 
  93:     if(bp == NULL) {
  94:         bp = search(blk);
  95:         fcp = &sfile;
  96:     }
  97:     else
  98:         fcp = &dfile;
  99:     if(bp->b_bno == blk)
 100:         return(bp);
 101:     flush(fcp,bp);
 102:     bp->b_errs = bread(fcp,bp->b_un.b_buf,blk,DEV_BSIZE);
 103:     bp->b_bno = blk;
 104:     bp->b_size = DEV_BSIZE;
 105:     return(bp);
 106: }
 107: 
 108: flush(fcp, bp)
 109:     struct filecntl *fcp;
 110:     register BUFAREA *bp;
 111: {
 112: 
 113:     if (!bp->b_dirty)
 114:         return;
 115:     if (bp->b_errs != 0)
 116:         pfatal("WRITING ZERO'ED BLOCK %ld TO DISK\n", bp->b_bno);
 117:     bp->b_dirty = 0;
 118:     bp->b_errs = 0;
 119:     if (bp == &inoblk)
 120:         bwrite(fcp, inobuf, startib, NINOBLK * DEV_BSIZE);
 121:     else
 122:         bwrite(fcp, bp->b_un.b_buf, bp->b_bno, DEV_BSIZE);
 123: }
 124: 
 125: rwerr(s, blk)
 126:     char *s;
 127:     daddr_t blk;
 128: {
 129: 
 130:     if (preen == 0)
 131:         printf("\n");
 132:     pfatal("CANNOT %s: BLK %ld", s, blk);
 133:     if (reply("CONTINUE") == 0)
 134:         errexit("Program terminated\n");
 135: }
 136: 
 137: ckfini()
 138: {
 139: 
 140:     flush(&dfile, &fileblk);
 141:     flush(&dfile, &sblk);
 142:     if (sblk.b_bno != SBLOCK) {
 143:         sblk.b_bno = SBLOCK;
 144:         sbdirty();
 145:         flush(&dfile, &sblk);
 146:     }
 147:     flush(&dfile, &inoblk);
 148:     if (dfile.rfdes)
 149:         (void)close(dfile.rfdes);
 150:     if (dfile.wfdes)
 151:         (void)close(dfile.wfdes);
 152:     if (sfile.rfdes)
 153:         (void)close(sfile.rfdes);
 154:     if (sfile.wfdes)
 155:         (void)close(sfile.wfdes);
 156: }
 157: 
 158: bread(fcp, buf, blk, size)
 159:     register struct filecntl *fcp;
 160:     char *buf;
 161:     daddr_t blk;
 162:     int size;
 163: {
 164:     char *cp;
 165:     register int i, errs;
 166: 
 167:     if (lseek(fcp->rfdes, blk << DEV_BSHIFT, 0) < 0)
 168:         rwerr("SEEK", blk);
 169:     else if (read(fcp->rfdes, buf, size) == size)
 170:         return (0);
 171:     rwerr("READ", blk);
 172:     if (lseek(fcp->rfdes, blk << DEV_BSHIFT, 0) < 0)
 173:         rwerr("SEEK", blk);
 174:     errs = 0;
 175:     pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:");
 176:     for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) {
 177:         if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) {
 178:             printf(" %ld,", blk + i / DEV_BSIZE);
 179:             bzero(cp, DEV_BSIZE);
 180:             errs++;
 181:         }
 182:     }
 183:     printf("\n");
 184:     return (errs);
 185: }
 186: 
 187: bwrite(fcp, buf, blk, size)
 188:     register struct filecntl *fcp;
 189:     char *buf;
 190:     daddr_t blk;
 191:     int size;
 192: {
 193:     int i;
 194:     char *cp;
 195: 
 196:     if (fcp->wfdes < 0)
 197:         return;
 198:     if (lseek(fcp->wfdes, blk << DEV_BSHIFT, 0) < 0)
 199:         rwerr("SEEK", blk);
 200:     else if (write(fcp->wfdes, buf, size) == size) {
 201:         fcp->mod = 1;
 202:         return;
 203:     }
 204:     rwerr("WRITE", blk);
 205:     if (lseek(fcp->wfdes, blk << DEV_BSHIFT, 0) < 0)
 206:         rwerr("SEEK", blk);
 207:     pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
 208:     for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE)
 209:         if (write(fcp->wfdes, cp, DEV_BSIZE) < 0)
 210:             printf(" %ld,", blk + i / DEV_BSIZE);
 211:     printf("\n");
 212:     return;
 213: }
 214: 
 215: /*
 216:  * allocate a data block
 217:  */
 218: daddr_t
 219: allocblk()
 220: {
 221:     daddr_t i;
 222: 
 223:     for (i = 0; i < fmax; i++) {
 224:         if (getbmap(i))
 225:             continue;
 226:         setbmap(i);
 227:         n_blks++;
 228:         return (i);
 229:     }
 230:     return (0);
 231: }
 232: 
 233: /*
 234:  * Free a previously allocated block
 235:  */
 236: fr_blk(blkno)
 237:     daddr_t blkno;
 238: {
 239:     struct inodesc idesc;
 240: 
 241:     idesc.id_blkno = blkno;
 242:     pass4check(&idesc);
 243: }
 244: 
 245: /*
 246:  * Find a pathname
 247:  */
 248: getpathname(namebuf, curdir, ino)
 249:     char *namebuf;
 250:     ino_t curdir, ino;
 251: {
 252:     int len, st;
 253:     register char *cp;
 254:     struct inodesc idesc;
 255:     extern int findname();
 256: 
 257:     st = getstate(ino);
 258:     if (st != DSTATE && st != DFOUND) {
 259:         strcpy(namebuf, "?");
 260:         return;
 261:     }
 262:     bzero(&idesc, sizeof(struct inodesc));
 263:     idesc.id_type = DATA;
 264:     cp = &namebuf[MAXPATHLEN - 1];
 265:     *cp-- = '\0';
 266:     if (curdir != ino) {
 267:         idesc.id_parent = curdir;
 268:         goto namelookup;
 269:     }
 270:     while (ino != ROOTINO) {
 271:         idesc.id_number = ino;
 272:         idesc.id_func = findino;
 273:         idesc.id_name = "..";
 274:         if ((ckinode(ginode(ino), &idesc) & STOP) == 0)
 275:             break;
 276:     namelookup:
 277:         idesc.id_number = idesc.id_parent;
 278:         idesc.id_parent = ino;
 279:         idesc.id_func = findname;
 280:         idesc.id_name = namebuf;
 281:         if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0)
 282:             break;
 283:         len = strlen(namebuf);
 284:         cp -= len;
 285:         if (cp < &namebuf[MAXNAMLEN])
 286:             break;
 287:         bcopy(namebuf, cp, len);
 288:         *--cp = '/';
 289:         ino = idesc.id_number;
 290:     }
 291:     if (ino != ROOTINO) {
 292:         strcpy(namebuf, "?");
 293:         return;
 294:     }
 295:     bcopy(cp, namebuf, &namebuf[MAXPATHLEN] - cp);
 296: }
 297: 
 298: catch()
 299: {
 300: 
 301:     ckfini();
 302:     exit(12);
 303: }
 304: 
 305: /*
 306:  * When preening, allow a single quit to signal
 307:  * a special exit after filesystem checks complete
 308:  * so that reboot sequence may be interrupted.
 309:  */
 310: catchquit()
 311: {
 312:     extern returntosingle;
 313: 
 314:     printf("returning to single-user after filesystem check\n");
 315:     returntosingle = 1;
 316:     (void)signal(SIGQUIT, SIG_DFL);
 317: }
 318: 
 319: /*
 320:  * Ignore a single quit signal; wait and flush just in case.
 321:  * Used by child processes in preen.
 322:  */
 323: voidquit()
 324: {
 325: 
 326:     sleep(1);
 327:     (void)signal(SIGQUIT, SIG_IGN);
 328:     (void)signal(SIGQUIT, SIG_DFL);
 329: }
 330: 
 331: /*
 332:  * determine whether an inode should be fixed.
 333:  */
 334: dofix(idesc, msg)
 335:     register struct inodesc *idesc;
 336:     char *msg;
 337: {
 338: 
 339:     switch (idesc->id_fix) {
 340: 
 341:     case DONTKNOW:
 342:         if (idesc->id_type == DATA)
 343:             direrr(idesc->id_number, msg);
 344:         else
 345:             pwarn(msg);
 346:         if (preen) {
 347:             printf(" (SALVAGED)\n");
 348:             idesc->id_fix = FIX;
 349:             return (ALTERED);
 350:         }
 351:         if (reply("SALVAGE") == 0) {
 352:             idesc->id_fix = NOFIX;
 353:             return (0);
 354:         }
 355:         idesc->id_fix = FIX;
 356:         return (ALTERED);
 357: 
 358:     case FIX:
 359:         return (ALTERED);
 360: 
 361:     case NOFIX:
 362:         return (0);
 363: 
 364:     default:
 365:         errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
 366:     }
 367:     /* NOTREACHED */
 368: }
 369: 
 370: /* VARARGS1 */
 371: errexit(s1, s2, s3, s4)
 372:     char *s1;
 373: {
 374:     printf(s1, s2, s3, s4);
 375:     exit(8);
 376: }
 377: 
 378: /*
 379:  * An inconsistency occured which shouldn't during normal operations.
 380:  * Die if preening, otherwise just printf.
 381:  */
 382: /* VARARGS1 */
 383: pfatal(s, a1, a2, a3, a4)
 384:     char *s;
 385: {
 386: 
 387:     if (preen) {
 388:         printf("%s: ", devname);
 389:         printf(s, a1, a2, a3, a4);
 390:         printf("\n");
 391:         printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
 392:             devname);
 393:         exit(8);
 394:     }
 395:     printf(s, a1, a2, a3, a4);
 396: }
 397: 
 398: /*
 399:  * Pwarn is like printf when not preening,
 400:  * or a warning (preceded by filename) when preening.
 401:  */
 402: /* VARARGS1 */
 403: pwarn(s, a1, a2, a3, a4, a5, a6)
 404:     char *s;
 405: {
 406: 
 407:     if (preen)
 408:         printf("%s: ", devname);
 409:     printf(s, a1, a2, a3, a4, a5, a6);
 410: }
 411: 
 412: stype(p)
 413: register char *p;
 414: {
 415:     if(*p == 0)
 416:         return;
 417:     if (*(p+1) == 0) {
 418:         if (*p == '3') {
 419:             cylsize = 200;
 420:             stepsize = 5;
 421:             return;
 422:         }
 423:         if (*p == '4') {
 424:             cylsize = 418;
 425:             stepsize = 9;
 426:             return;
 427:         }
 428:     }
 429:     cylsize = atoi(p);
 430:     while(*p && *p != ':')
 431:         p++;
 432:     if(*p)
 433:         p++;
 434:     stepsize = atoi(p);
 435:     if(stepsize <= 0 || stepsize > cylsize ||
 436:     cylsize <= 0 || cylsize > MAXCYL) {
 437:         printf("Invalid -s argument, defaults assumed\n");
 438:         cylsize = stepsize = 0;
 439:     }
 440: }
 441: 
 442: dostate(ino, s,flg)
 443:     ino_t ino;
 444:     int s, flg;
 445: {
 446:     register char *p;
 447:     register unsigned byte, shift;
 448:     BUFAREA *bp;
 449: 
 450:     byte = ino / STATEPB;
 451:     shift = LSTATE * (ino % STATEPB);
 452:     if(statemap != NULL) {
 453:         bp = NULL;
 454:         p = &statemap[byte];
 455:     }
 456:     else {
 457:         bp = getblk(NULL,(daddr_t)(smapblk+(byte/DEV_BSIZE)));
 458:         if (bp->b_errs)
 459:             errexit("Fatal I/O error\n");
 460:         else
 461:             p = &bp->b_un.b_buf[byte%DEV_BSIZE];
 462:     }
 463:     switch(flg) {
 464:         case 0:
 465:             *p &= ~(SMASK<<(shift));
 466:             *p |= s << shift;
 467:             if(bp != NULL)
 468:                 dirty(bp);
 469:             return(s);
 470:         case 1:
 471:             return((*p >> shift) & SMASK);
 472:     }
 473:     return(USTATE);
 474: }
 475: 
 476: domap(blk,flg)
 477: daddr_t blk;
 478: int flg;
 479: {
 480:     register char *p;
 481:     register unsigned n;
 482:     register BUFAREA *bp;
 483:     off_t byte;
 484: 
 485:     byte = blk >> BITSHIFT;
 486:     n = 1<<((unsigned)(blk & BITMASK));
 487:     if(flg & 04) {
 488:         p = freemap;
 489:         blk = fmapblk;
 490:     }
 491:     else {
 492:         p = blockmap;
 493:         blk = bmapblk;
 494:     }
 495:     if(p != NULL) {
 496:         bp = NULL;
 497:         p += (unsigned)byte;
 498:     }
 499:     else {
 500:         bp = getblk((BUFAREA *)NULL,blk+(byte>>DEV_BSHIFT));
 501:         if (bp->b_errs)
 502:             errexit("Fatal I/O error\n");
 503:         else
 504:             p = &bp->b_un.b_buf[(unsigned)(byte&DEV_BMASK)];
 505:     }
 506:     switch(flg&03) {
 507:         case 0:
 508:             *p |= n;
 509:             break;
 510:         case 1:
 511:             n &= *p;
 512:             bp = NULL;
 513:             break;
 514:         case 2:
 515:             *p &= ~n;
 516:     }
 517:     if(bp != NULL)
 518:         dirty(bp);
 519:     return(n);
 520: }
 521: 
 522: dolncnt(ino, flg, val)
 523: ino_t ino;
 524: short val, flg;
 525: {
 526:     register short *sp;
 527:     register BUFAREA *bp;
 528: 
 529:     if(lncntp != NULL) {
 530:         bp = NULL;
 531:         sp = &lncntp[ino];
 532:     }
 533:     else {
 534:         bp = getblk((BUFAREA *)NULL,(daddr_t)(lncntblk+(ino/SPERB)));
 535:         if (bp->b_errs)
 536:             errexit("Fatal I/O error\n");
 537:         else
 538:             sp = &bp->b_un.b_lnks[ino%SPERB];
 539:     }
 540:     switch(flg) {
 541:         case 0:
 542:             *sp = val;
 543:             break;
 544:         case 1:
 545:             bp = NULL;
 546:             break;
 547:         case 2:
 548:             (*sp)--;
 549:             break;
 550:         case 3:
 551:             (*sp)++;
 552:             break;
 553:         default:
 554:             abort();
 555:     }
 556:     if(bp != NULL)
 557:         dirty(bp);
 558:     return(*sp);
 559: }
 560: 
 561: BUFAREA *
 562: search(blk)
 563: daddr_t blk;
 564: {
 565:     register BUFAREA *pbp, *bp;
 566: 
 567:     for(bp = (BUFAREA *) &poolhead; bp->b_next; ) {
 568:         pbp = bp;
 569:         bp = pbp->b_next;
 570:         if(bp->b_bno == blk)
 571:             break;
 572:     }
 573:     pbp->b_next = bp->b_next;
 574:     bp->b_next = poolhead;
 575:     poolhead = bp;
 576:     return(bp);
 577: }

Defined functions

bread defined in line 158; used 3 times
bwrite defined in line 187; used 3 times
catch defined in line 298; used 2 times
catchquit defined in line 310; used 2 times
ckfini defined in line 137; used 4 times
dofix defined in line 334; used 6 times
dolncnt defined in line 522; used 4 times
domap defined in line 476; used 6 times
dostate defined in line 442; used 2 times
fr_blk defined in line 236; used 1 times
ftypeok defined in line 21; used 2 times
getblk defined in line 85; used 14 times
getline defined in line 66; used 2 times
getpathname defined in line 248; used 1 times
rwerr defined in line 125; used 6 times
search defined in line 561; used 2 times
stype defined in line 412; used 1 times
voidquit defined in line 323; used 2 times

Defined variables

sccsid defined in line 8; never used
Last modified: 1990-09-16
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4007
Valid CSS Valid XHTML 1.0 Strict