|
|
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: char copyright[] = ! 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ ! 10: All rights reserved.\n"; ! 11: #endif not lint ! 12: ! 13: #ifndef lint ! 14: static char sccsid[] = "@(#)main.c 5.8 (Berkeley) 5/3/88"; ! 15: #endif not lint ! 16: ! 17: #include <sys/param.h> ! 18: #include <sys/inode.h> ! 19: #include <sys/fs.h> ! 20: #include <sys/stat.h> ! 21: #include <sys/wait.h> ! 22: #include <fstab.h> ! 23: #include <strings.h> ! 24: #include "fsck.h" ! 25: ! 26: char *rawname(), *unrawname(), *blockcheck(); ! 27: int catch(), catchquit(), voidquit(); ! 28: int returntosingle; ! 29: int (*signal())(); ! 30: ! 31: main(argc, argv) ! 32: int argc; ! 33: char *argv[]; ! 34: { ! 35: struct fstab *fsp; ! 36: int pid, passno, anygtr, sumstatus; ! 37: char *name; ! 38: struct worklist { ! 39: int pid; /* pid of child doing the check */ ! 40: struct worklist *next; /* next in list */ ! 41: char name[MAXMNTLEN];/* name of file system */ ! 42: } *listhead = 0, *freelist = 0, *badlist = 0; ! 43: register struct worklist *wp, *pwp; ! 44: ! 45: sync(); ! 46: while (--argc > 0 && **++argv == '-') { ! 47: switch (*++*argv) { ! 48: ! 49: case 'p': ! 50: preen++; ! 51: break; ! 52: ! 53: case 'b': ! 54: if (argv[0][1] != '\0') { ! 55: bflag = atoi(argv[0]+1); ! 56: } else { ! 57: bflag = atoi(*++argv); ! 58: argc--; ! 59: } ! 60: printf("Alternate super block location: %d\n", bflag); ! 61: break; ! 62: ! 63: case 'c': ! 64: cvtflag++; ! 65: break; ! 66: ! 67: case 'd': ! 68: debug++; ! 69: break; ! 70: ! 71: case 'n': /* default no answer flag */ ! 72: case 'N': ! 73: nflag++; ! 74: yflag = 0; ! 75: break; ! 76: ! 77: case 'y': /* default yes answer flag */ ! 78: case 'Y': ! 79: yflag++; ! 80: nflag = 0; ! 81: break; ! 82: ! 83: default: ! 84: errexit("%c option?\n", **argv); ! 85: } ! 86: } ! 87: if (signal(SIGINT, SIG_IGN) != SIG_IGN) ! 88: (void)signal(SIGINT, catch); ! 89: if (preen) ! 90: (void)signal(SIGQUIT, catchquit); ! 91: if (argc) { ! 92: while (argc-- > 0) { ! 93: hotroot = 0; ! 94: checkfilesys(*argv++); ! 95: } ! 96: exit(0); ! 97: } ! 98: sumstatus = 0; ! 99: passno = 1; ! 100: do { ! 101: anygtr = 0; ! 102: if (setfsent() == 0) ! 103: errexit("Can't open checklist file: %s\n", FSTAB); ! 104: while ((fsp = getfsent()) != 0) { ! 105: if (strcmp(fsp->fs_type, FSTAB_RW) && ! 106: strcmp(fsp->fs_type, FSTAB_RO) && ! 107: strcmp(fsp->fs_type, FSTAB_RQ)) ! 108: continue; ! 109: if (preen == 0 || ! 110: passno == 1 && fsp->fs_passno == passno) { ! 111: name = blockcheck(fsp->fs_spec); ! 112: if (name != NULL) ! 113: checkfilesys(name); ! 114: else if (preen) ! 115: exit(8); ! 116: } else if (fsp->fs_passno > passno) { ! 117: anygtr = 1; ! 118: } else if (fsp->fs_passno == passno) { ! 119: name = blockcheck(fsp->fs_spec); ! 120: if (name == NULL) { ! 121: pwarn("BAD DISK NAME %s\n", ! 122: fsp->fs_spec); ! 123: sumstatus |= 8; ! 124: continue; ! 125: } ! 126: pid = fork(); ! 127: if (pid < 0) { ! 128: perror("fork"); ! 129: exit(8); ! 130: } ! 131: if (pid == 0) { ! 132: (void)signal(SIGQUIT, voidquit); ! 133: checkfilesys(name); ! 134: exit(0); ! 135: } else { ! 136: if (freelist == 0) { ! 137: wp = (struct worklist *) malloc ! 138: (sizeof(struct worklist)); ! 139: } else { ! 140: wp = freelist; ! 141: freelist = wp->next; ! 142: } ! 143: wp->next = listhead; ! 144: listhead = wp; ! 145: wp->pid = pid; ! 146: sprintf(wp->name, "%s (%s)", name, ! 147: fsp->fs_file); ! 148: } ! 149: } ! 150: } ! 151: if (preen) { ! 152: union wait status; ! 153: while ((pid = wait(&status)) != -1) { ! 154: sumstatus |= status.w_retcode; ! 155: pwp = 0; ! 156: for (wp = listhead; wp; pwp = wp, wp = wp->next) ! 157: if (wp->pid == pid) ! 158: break; ! 159: if (wp == 0) { ! 160: printf("Unknown pid %d\n", pid); ! 161: continue; ! 162: } ! 163: if (pwp == 0) ! 164: listhead = wp->next; ! 165: else ! 166: pwp->next = wp->next; ! 167: if (status.w_retcode != 0) { ! 168: wp->next = badlist; ! 169: badlist = wp; ! 170: } else { ! 171: wp->next = freelist; ! 172: freelist = wp; ! 173: } ! 174: } ! 175: } ! 176: passno++; ! 177: } while (anygtr); ! 178: if (sumstatus) { ! 179: if (badlist == 0) ! 180: exit(8); ! 181: printf("THE FOLLOWING FILE SYSTEM%s HAD AN %s\n\t", ! 182: badlist->next ? "S" : "", "UNEXPECTED INCONSISTENCY:"); ! 183: for (wp = badlist; wp; wp = wp->next) ! 184: printf("%s%s", wp->name, wp->next ? ", " : "\n"); ! 185: exit(8); ! 186: } ! 187: (void)endfsent(); ! 188: if (returntosingle) ! 189: exit(2); ! 190: exit(0); ! 191: } ! 192: ! 193: checkfilesys(filesys) ! 194: char *filesys; ! 195: { ! 196: daddr_t n_ffree, n_bfree; ! 197: struct dups *dp; ! 198: struct zlncnt *zlnp; ! 199: ! 200: devname = filesys; ! 201: if (setup(filesys) == 0) { ! 202: if (preen) ! 203: pfatal("CAN'T CHECK FILE SYSTEM."); ! 204: return; ! 205: } ! 206: /* ! 207: * 1: scan inodes tallying blocks used ! 208: */ ! 209: if (preen == 0) { ! 210: printf("** Last Mounted on %s\n", sblock.fs_fsmnt); ! 211: if (hotroot) ! 212: printf("** Root file system\n"); ! 213: printf("** Phase 1 - Check Blocks and Sizes\n"); ! 214: } ! 215: pass1(); ! 216: ! 217: /* ! 218: * 1b: locate first references to duplicates, if any ! 219: */ ! 220: if (duplist) { ! 221: if (preen) ! 222: pfatal("INTERNAL ERROR: dups with -p"); ! 223: printf("** Phase 1b - Rescan For More DUPS\n"); ! 224: pass1b(); ! 225: } ! 226: ! 227: /* ! 228: * 2: traverse directories from root to mark all connected directories ! 229: */ ! 230: if (preen == 0) ! 231: printf("** Phase 2 - Check Pathnames\n"); ! 232: pass2(); ! 233: ! 234: /* ! 235: * 3: scan inodes looking for disconnected directories ! 236: */ ! 237: if (preen == 0) ! 238: printf("** Phase 3 - Check Connectivity\n"); ! 239: pass3(); ! 240: ! 241: /* ! 242: * 4: scan inodes looking for disconnected files; check reference counts ! 243: */ ! 244: if (preen == 0) ! 245: printf("** Phase 4 - Check Reference Counts\n"); ! 246: pass4(); ! 247: ! 248: /* ! 249: * 5: check and repair resource counts in cylinder groups ! 250: */ ! 251: if (preen == 0) ! 252: printf("** Phase 5 - Check Cyl groups\n"); ! 253: pass5(); ! 254: ! 255: /* ! 256: * print out summary statistics ! 257: */ ! 258: n_ffree = sblock.fs_cstotal.cs_nffree; ! 259: n_bfree = sblock.fs_cstotal.cs_nbfree; ! 260: pwarn("%d files, %d used, %d free ", ! 261: n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); ! 262: printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", ! 263: n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize); ! 264: if (debug && (n_files -= imax - ROOTINO - sblock.fs_cstotal.cs_nifree)) ! 265: printf("%d files missing\n", n_files); ! 266: if (debug) { ! 267: n_blks += sblock.fs_ncg * ! 268: (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); ! 269: n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); ! 270: n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); ! 271: if (n_blks -= fmax - (n_ffree + sblock.fs_frag * n_bfree)) ! 272: printf("%d blocks missing\n", n_blks); ! 273: if (duplist != NULL) { ! 274: printf("The following duplicate blocks remain:"); ! 275: for (dp = duplist; dp; dp = dp->next) ! 276: printf(" %d,", dp->dup); ! 277: printf("\n"); ! 278: } ! 279: if (zlnhead != NULL) { ! 280: printf("The following zero link count inodes remain:"); ! 281: for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) ! 282: printf(" %d,", zlnp->zlncnt); ! 283: printf("\n"); ! 284: } ! 285: } ! 286: zlnhead = (struct zlncnt *)0; ! 287: duplist = (struct dups *)0; ! 288: if (dfile.mod) { ! 289: (void)time(&sblock.fs_time); ! 290: sbdirty(); ! 291: } ! 292: ckfini(); ! 293: free(blockmap); ! 294: free(statemap); ! 295: free((char *)lncntp); ! 296: if (!dfile.mod) ! 297: return; ! 298: if (!preen) { ! 299: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); ! 300: if (hotroot) ! 301: printf("\n***** REBOOT UNIX *****\n"); ! 302: } ! 303: if (hotroot) { ! 304: sync(); ! 305: exit(4); ! 306: } ! 307: } ! 308: ! 309: char * ! 310: blockcheck(name) ! 311: char *name; ! 312: { ! 313: struct stat stslash, stblock, stchar; ! 314: char *raw; ! 315: int looped = 0; ! 316: ! 317: hotroot = 0; ! 318: if (stat("/", &stslash) < 0){ ! 319: perror("/"); ! 320: printf("Can't stat root\n"); ! 321: return (0); ! 322: } ! 323: retry: ! 324: if (stat(name, &stblock) < 0){ ! 325: perror(name); ! 326: printf("Can't stat %s\n", name); ! 327: return (0); ! 328: } ! 329: if ((stblock.st_mode & S_IFMT) == S_IFBLK) { ! 330: if (stslash.st_dev == stblock.st_rdev) { ! 331: hotroot++; ! 332: return (name); ! 333: } ! 334: raw = rawname(name); ! 335: if (stat(raw, &stchar) < 0){ ! 336: perror(raw); ! 337: printf("Can't stat %s\n", raw); ! 338: return (name); ! 339: } ! 340: if ((stchar.st_mode & S_IFMT) == S_IFCHR) ! 341: return (raw); ! 342: else { ! 343: printf("%s is not a character device\n", raw); ! 344: return (name); ! 345: } ! 346: } else if ((stblock.st_mode & S_IFMT) == S_IFCHR) { ! 347: if (looped) { ! 348: printf("Can't make sense out of name %s\n", name); ! 349: return (0); ! 350: } ! 351: name = unrawname(name); ! 352: looped++; ! 353: goto retry; ! 354: } ! 355: printf("Can't make sense out of name %s\n", name); ! 356: return (0); ! 357: } ! 358: ! 359: char * ! 360: unrawname(cp) ! 361: char *cp; ! 362: { ! 363: char *dp = rindex(cp, '/'); ! 364: struct stat stb; ! 365: ! 366: if (dp == 0) ! 367: return (cp); ! 368: if (stat(cp, &stb) < 0) ! 369: return (cp); ! 370: if ((stb.st_mode&S_IFMT) != S_IFCHR) ! 371: return (cp); ! 372: if (*(dp+1) != 'r') ! 373: return (cp); ! 374: (void)strcpy(dp+1, dp+2); ! 375: return (cp); ! 376: } ! 377: ! 378: char * ! 379: rawname(cp) ! 380: char *cp; ! 381: { ! 382: static char rawbuf[32]; ! 383: char *dp = rindex(cp, '/'); ! 384: ! 385: if (dp == 0) ! 386: return (0); ! 387: *dp = 0; ! 388: (void)strcpy(rawbuf, cp); ! 389: *dp = '/'; ! 390: (void)strcat(rawbuf, "/r"); ! 391: (void)strcat(rawbuf, dp+1); ! 392: return (rawbuf); ! 393: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.