|
|
1.1 ! root 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
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.