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: #ifndef lint
   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, size)
  87:     register BUFAREA *bp;
  88:     daddr_t blk;
  89:     long size;
  90: {
  91:     register struct filecntl *fcp;
  92:     daddr_t dblk;
  93: 
  94:     fcp = &dfile;
  95:     dblk = fsbtodb(&sblock, blk);
  96:     if (bp->b_bno == dblk)
  97:         return (bp);
  98:     flush(fcp, bp);
  99:     bp->b_errs = bread(fcp, bp->b_un.b_buf, dblk, size);
 100:     bp->b_bno = dblk;
 101:     bp->b_size = size;
 102:     return (bp);
 103: }
 104: 
 105: flush(fcp, bp)
 106:     struct filecntl *fcp;
 107:     register BUFAREA *bp;
 108: {
 109:     register int i, j;
 110: 
 111:     if (!bp->b_dirty)
 112:         return;
 113:     if (bp->b_errs != 0)
 114:         pfatal("WRITING ZERO'ED BLOCK %d TO DISK\n", bp->b_bno);
 115:     bp->b_dirty = 0;
 116:     bp->b_errs = 0;
 117:     bwrite(fcp, bp->b_un.b_buf, bp->b_bno, (long)bp->b_size);
 118:     if (bp != &sblk)
 119:         return;
 120:     for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
 121:         bwrite(&dfile, (char *)sblock.fs_csp[j],
 122:             fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
 123:             sblock.fs_cssize - i < sblock.fs_bsize ?
 124:             sblock.fs_cssize - i : sblock.fs_bsize);
 125:     }
 126: }
 127: 
 128: rwerr(s, blk)
 129:     char *s;
 130:     daddr_t blk;
 131: {
 132: 
 133:     if (preen == 0)
 134:         printf("\n");
 135:     pfatal("CANNOT %s: BLK %ld", s, blk);
 136:     if (reply("CONTINUE") == 0)
 137:         errexit("Program terminated\n");
 138: }
 139: 
 140: ckfini()
 141: {
 142: 
 143:     flush(&dfile, &fileblk);
 144:     flush(&dfile, &sblk);
 145:     if (sblk.b_bno != SBLOCK) {
 146:         sblk.b_bno = SBLOCK;
 147:         sbdirty();
 148:         flush(&dfile, &sblk);
 149:     }
 150:     flush(&dfile, &inoblk);
 151:     flush(&dfile, &cgblk);
 152:     (void)close(dfile.rfdes);
 153:     (void)close(dfile.wfdes);
 154: }
 155: 
 156: bread(fcp, buf, blk, size)
 157:     register struct filecntl *fcp;
 158:     char *buf;
 159:     daddr_t blk;
 160:     long size;
 161: {
 162:     char *cp;
 163:     int i, errs;
 164: 
 165:     if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
 166:         rwerr("SEEK", blk);
 167:     else if (read(fcp->rfdes, buf, (int)size) == size)
 168:         return (0);
 169:     rwerr("READ", blk);
 170:     if (lseek(fcp->rfdes, (long)dbtob(blk), 0) < 0)
 171:         rwerr("SEEK", blk);
 172:     errs = 0;
 173:     pfatal("THE FOLLOWING SECTORS COULD NOT BE READ:");
 174:     for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE) {
 175:         if (read(fcp->rfdes, cp, DEV_BSIZE) < 0) {
 176:             printf(" %d,", blk + i / DEV_BSIZE);
 177:             bzero(cp, DEV_BSIZE);
 178:             errs++;
 179:         }
 180:     }
 181:     printf("\n");
 182:     return (errs);
 183: }
 184: 
 185: bwrite(fcp, buf, blk, size)
 186:     register struct filecntl *fcp;
 187:     char *buf;
 188:     daddr_t blk;
 189:     long size;
 190: {
 191:     int i;
 192:     char *cp;
 193: 
 194:     if (fcp->wfdes < 0)
 195:         return;
 196:     if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
 197:         rwerr("SEEK", blk);
 198:     else if (write(fcp->wfdes, buf, (int)size) == size) {
 199:         fcp->mod = 1;
 200:         return;
 201:     }
 202:     rwerr("WRITE", blk);
 203:     if (lseek(fcp->wfdes, (long)dbtob(blk), 0) < 0)
 204:         rwerr("SEEK", blk);
 205:     pfatal("THE FOLLOWING SECTORS COULD NOT BE WRITTEN:");
 206:     for (cp = buf, i = 0; i < size; i += DEV_BSIZE, cp += DEV_BSIZE)
 207:         if (write(fcp->wfdes, cp, DEV_BSIZE) < 0)
 208:             printf(" %d,", blk + i / DEV_BSIZE);
 209:     printf("\n");
 210:     return;
 211: }
 212: 
 213: /*
 214:  * allocate a data block with the specified number of fragments
 215:  */
 216: allocblk(frags)
 217:     int frags;
 218: {
 219:     register int i, j, k;
 220: 
 221:     if (frags <= 0 || frags > sblock.fs_frag)
 222:         return (0);
 223:     for (i = 0; i < fmax - sblock.fs_frag; i += sblock.fs_frag) {
 224:         for (j = 0; j <= sblock.fs_frag - frags; j++) {
 225:             if (getbmap(i + j))
 226:                 continue;
 227:             for (k = 1; k < frags; k++)
 228:                 if (getbmap(i + j + k))
 229:                     break;
 230:             if (k < frags) {
 231:                 j += k;
 232:                 continue;
 233:             }
 234:             for (k = 0; k < frags; k++)
 235:                 setbmap(i + j + k);
 236:             n_blks += frags;
 237:             return (i + j);
 238:         }
 239:     }
 240:     return (0);
 241: }
 242: 
 243: /*
 244:  * Free a previously allocated block
 245:  */
 246: freeblk(blkno, frags)
 247:     daddr_t blkno;
 248:     int frags;
 249: {
 250:     struct inodesc idesc;
 251: 
 252:     idesc.id_blkno = blkno;
 253:     idesc.id_numfrags = frags;
 254:     pass4check(&idesc);
 255: }
 256: 
 257: /*
 258:  * Find a pathname
 259:  */
 260: getpathname(namebuf, curdir, ino)
 261:     char *namebuf;
 262:     ino_t curdir, ino;
 263: {
 264:     int len;
 265:     register char *cp;
 266:     struct inodesc idesc;
 267:     extern int findname();
 268: 
 269:     if (statemap[ino] != DSTATE && statemap[ino] != DFOUND) {
 270:         strcpy(namebuf, "?");
 271:         return;
 272:     }
 273:     bzero(&idesc, sizeof(struct inodesc));
 274:     idesc.id_type = DATA;
 275:     cp = &namebuf[BUFSIZ - 1];
 276:     *cp-- = '\0';
 277:     if (curdir != ino) {
 278:         idesc.id_parent = curdir;
 279:         goto namelookup;
 280:     }
 281:     while (ino != ROOTINO) {
 282:         idesc.id_number = ino;
 283:         idesc.id_func = findino;
 284:         idesc.id_name = "..";
 285:         if ((ckinode(ginode(ino), &idesc) & STOP) == 0)
 286:             break;
 287:     namelookup:
 288:         idesc.id_number = idesc.id_parent;
 289:         idesc.id_parent = ino;
 290:         idesc.id_func = findname;
 291:         idesc.id_name = namebuf;
 292:         if ((ckinode(ginode(idesc.id_number), &idesc) & STOP) == 0)
 293:             break;
 294:         len = strlen(namebuf);
 295:         cp -= len;
 296:         if (cp < &namebuf[MAXNAMLEN])
 297:             break;
 298:         bcopy(namebuf, cp, len);
 299:         *--cp = '/';
 300:         ino = idesc.id_number;
 301:     }
 302:     if (ino != ROOTINO) {
 303:         strcpy(namebuf, "?");
 304:         return;
 305:     }
 306:     bcopy(cp, namebuf, &namebuf[BUFSIZ] - cp);
 307: }
 308: 
 309: catch()
 310: {
 311: 
 312:     ckfini();
 313:     exit(12);
 314: }
 315: 
 316: /*
 317:  * When preening, allow a single quit to signal
 318:  * a special exit after filesystem checks complete
 319:  * so that reboot sequence may be interrupted.
 320:  */
 321: catchquit()
 322: {
 323:     extern returntosingle;
 324: 
 325:     printf("returning to single-user after filesystem check\n");
 326:     returntosingle = 1;
 327:     (void)signal(SIGQUIT, SIG_DFL);
 328: }
 329: 
 330: /*
 331:  * Ignore a single quit signal; wait and flush just in case.
 332:  * Used by child processes in preen.
 333:  */
 334: voidquit()
 335: {
 336: 
 337:     sleep(1);
 338:     (void)signal(SIGQUIT, SIG_IGN);
 339:     (void)signal(SIGQUIT, SIG_DFL);
 340: }
 341: 
 342: /*
 343:  * determine whether an inode should be fixed.
 344:  */
 345: dofix(idesc, msg)
 346:     register struct inodesc *idesc;
 347:     char *msg;
 348: {
 349: 
 350:     switch (idesc->id_fix) {
 351: 
 352:     case DONTKNOW:
 353:         if (idesc->id_type == DATA)
 354:             direrr(idesc->id_number, msg);
 355:         else
 356:             pwarn(msg);
 357:         if (preen) {
 358:             printf(" (SALVAGED)\n");
 359:             idesc->id_fix = FIX;
 360:             return (ALTERED);
 361:         }
 362:         if (reply("SALVAGE") == 0) {
 363:             idesc->id_fix = NOFIX;
 364:             return (0);
 365:         }
 366:         idesc->id_fix = FIX;
 367:         return (ALTERED);
 368: 
 369:     case FIX:
 370:         return (ALTERED);
 371: 
 372:     case NOFIX:
 373:         return (0);
 374: 
 375:     default:
 376:         errexit("UNKNOWN INODESC FIX MODE %d\n", idesc->id_fix);
 377:     }
 378:     /* NOTREACHED */
 379: }
 380: 
 381: /* VARARGS1 */
 382: errexit(s1, s2, s3, s4)
 383:     char *s1;
 384: {
 385:     printf(s1, s2, s3, s4);
 386:     exit(8);
 387: }
 388: 
 389: /*
 390:  * An inconsistency occured which shouldn't during normal operations.
 391:  * Die if preening, otherwise just printf.
 392:  */
 393: /* VARARGS1 */
 394: pfatal(s, a1, a2, a3)
 395:     char *s;
 396: {
 397: 
 398:     if (preen) {
 399:         printf("%s: ", devname);
 400:         printf(s, a1, a2, a3);
 401:         printf("\n");
 402:         printf("%s: UNEXPECTED INCONSISTENCY; RUN fsck MANUALLY.\n",
 403:             devname);
 404:         exit(8);
 405:     }
 406:     printf(s, a1, a2, a3);
 407: }
 408: 
 409: /*
 410:  * Pwarn is like printf when not preening,
 411:  * or a warning (preceded by filename) when preening.
 412:  */
 413: /* VARARGS1 */
 414: pwarn(s, a1, a2, a3, a4, a5, a6)
 415:     char *s;
 416: {
 417: 
 418:     if (preen)
 419:         printf("%s: ", devname);
 420:     printf(s, a1, a2, a3, a4, a5, a6);
 421: }
 422: 
 423: #ifndef lint
 424: /*
 425:  * Stub for routines from kernel.
 426:  */
 427: panic(s)
 428:     char *s;
 429: {
 430: 
 431:     pfatal("INTERNAL INCONSISTENCY:");
 432:     errexit(s);
 433: }
 434: #endif

Defined functions

allocblk defined in line 216; used 2 times
bread defined in line 156; used 3 times
bwrite defined in line 185; used 2 times
catch defined in line 309; used 2 times
catchquit defined in line 321; used 2 times
ckfini defined in line 140; used 3 times
dofix defined in line 345; used 7 times
flush defined in line 105; used 8 times
freeblk defined in line 246; used 1 times
ftypeok defined in line 21; used 2 times
getline defined in line 66; used 1 times
  • in line 57
getpathname defined in line 260; used 1 times
panic defined in line 427; never used
reply defined in line 41; used 38 times
rwerr defined in line 128; used 6 times
voidquit defined in line 334; used 2 times

Defined variables

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