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: char copyright[] = 9: "@(#) Copyright (c) 1980 Regents of the University of California.\n\ 10: All rights reserved.\n"; 11: 12: static char sccsid[] = "@(#)main.c 5.4.1 (2.11BSD) 1996/2/3"; 13: #endif not lint 14: 15: #include <sys/param.h> 16: #include <sys/inode.h> 17: #include <sys/fs.h> 18: #include <sys/stat.h> 19: #include <sys/wait.h> 20: #include <fstab.h> 21: #include <strings.h> 22: #include "fsck.h" 23: #include <stdio.h> 24: 25: char *rawname(), *unrawname(), *blockcheck(); 26: int catch(), catchquit(), voidquit(); 27: int returntosingle; 28: int (*signal())(); 29: 30: main(argc, argv) 31: int argc; 32: char *argv[]; 33: { 34: struct fstab *fsp; 35: int pid, passno, anygtr, sumstatus; 36: char *name, inbuf[128], outbuf[128]; 37: 38: setbuffer(stdin, inbuf, sizeof (inbuf)); 39: setbuffer(stdout, outbuf, sizeof (outbuf)); 40: setlinebuf(stdout); 41: sync(); 42: 43: while (--argc > 0 && **++argv == '-') { 44: switch (*++*argv) { 45: 46: case 's': 47: sflag++; 48: stype(++*argv); 49: argc--; 50: break; 51: 52: case 't': 53: case 'T': 54: if (**++argv == '-' || --argc <= 0) 55: errexit("Bad -t option"); 56: strcpy(scrfile, *argv); 57: break; 58: 59: case 'p': 60: preen++; 61: break; 62: 63: case 'd': 64: debug++; 65: break; 66: 67: case 'n': /* default no answer flag */ 68: case 'N': 69: nflag++; 70: yflag = 0; 71: break; 72: 73: case 'y': /* default yes answer flag */ 74: case 'Y': 75: yflag++; 76: nflag = 0; 77: break; 78: 79: default: 80: errexit("%c option?\n", **argv); 81: } 82: } 83: 84: /* 85: * fsck has a problem under a 4BSD C library in that if its done 86: * its sbrk's before it accesses FSTAB, there's no space left 87: * for stdio. There may be other problems like this. Enjoy. 88: */ 89: if (!getfsent()) 90: errexit("Can't open checklist file: %s\n",FSTAB); 91: setpassent(1); 92: 93: memsize = sbrk(0); 94: memsize = MAXDATA - memsize - sizeof(int); 95: while (memsize >= 2 * sizeof(BUFAREA) && 96: (membase = (char *)sbrk(memsize)) == (char *)-1) 97: memsize -= MEMUNIT; 98: if (memsize < 2 * sizeof(BUFAREA)) 99: errexit("Can't get memory\n"); 100: 101: if (signal(SIGINT, SIG_IGN) != SIG_IGN) 102: (void)signal(SIGINT, catch); 103: if (preen) 104: (void)signal(SIGQUIT, catchquit); 105: if (argc) { 106: while (argc-- > 0) { 107: hotroot = 0; 108: checkfilesys(*argv++); 109: } 110: exit(0); 111: } 112: sumstatus = 0; 113: passno = 1; 114: do { 115: anygtr = 0; 116: if (setfsent() == 0) 117: errexit("Can't open %s\n", FSTAB); 118: while ((fsp = getfsent()) != 0) { 119: if (strcmp(fsp->fs_vfstype, "ufs") || 120: (strcmp(fsp->fs_type, FSTAB_RW) && 121: strcmp(fsp->fs_type, FSTAB_RO) && 122: strcmp(fsp->fs_type, FSTAB_RQ)) || 123: fsp->fs_passno == 0) 124: continue; 125: if (preen == 0 || 126: passno == 1 && fsp->fs_passno == passno) { 127: name = blockcheck(fsp->fs_spec); 128: if (name != NULL) 129: checkfilesys(name); 130: else if (preen) 131: exit(8); 132: } else if (fsp->fs_passno > passno) { 133: anygtr = 1; 134: } else if (fsp->fs_passno == passno) { 135: pid = fork(); 136: if (pid < 0) { 137: perror("fork"); 138: exit(8); 139: } 140: if (pid == 0) { 141: (void)signal(SIGQUIT, voidquit); 142: name = blockcheck(fsp->fs_spec); 143: if (name == NULL) 144: exit(8); 145: checkfilesys(name); 146: exit(0); 147: } 148: } 149: } 150: if (preen) { 151: union wait status; 152: while (wait(&status) != -1) 153: sumstatus |= status.w_retcode; 154: } 155: passno++; 156: } while (anygtr); 157: 158: if (sumstatus) 159: exit(8); 160: (void)endfsent(); 161: if (returntosingle) 162: exit(2); 163: exit(0); 164: } 165: 166: checkfilesys(filesys) 167: char *filesys; 168: { 169: daddr_t n_ffree, n_bfree; 170: register ino_t *zp; 171: 172: devname = filesys; 173: if (setup(filesys) == 0) { 174: if (preen) 175: pfatal("CAN'T CHECK FILE SYSTEM."); 176: return; 177: } 178: /* 179: * 1: scan inodes tallying blocks used 180: */ 181: if (preen == 0) { 182: printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 183: if (hotroot) 184: printf("** Root file system\n"); 185: printf("** Phase 1 - Check Blocks and Sizes\n"); 186: } 187: pass1(); 188: 189: /* 190: * 1b: locate first references to duplicates, if any 191: */ 192: if (enddup != duplist) { 193: if (preen) 194: pfatal("INTERNAL ERROR: dups with -p"); 195: printf("** Phase 1b - Rescan For More DUPS\n"); 196: pass1b(); 197: } 198: 199: /* 200: * 2: traverse directories from root to mark all connected directories 201: */ 202: if (preen == 0) 203: printf("** Phase 2 - Check Pathnames\n"); 204: pass2(); 205: 206: /* 207: * 3: scan inodes looking for disconnected directories 208: */ 209: if (preen == 0) 210: printf("** Phase 3 - Check Connectivity\n"); 211: pass3(); 212: 213: /* 214: * 4: scan inodes looking for disconnected files; check reference counts 215: */ 216: if (preen == 0) 217: printf("** Phase 4 - Check Reference Counts\n"); 218: pass4(); 219: 220: flush(&dfile, &fileblk); 221: 222: /* 223: * 5: check and repair resource counts in cylinder groups 224: */ 225: if (preen == 0) 226: printf("** Phase 5 - Check Free List\n"); 227: pass5(); 228: 229: /* 230: * print out summary statistics 231: */ 232: pwarn("%ld files, %ld used, %ld free\n", 233: n_files, n_blks, sblock.fs_tfree); 234: if (debug && (n_files -= imax - ROOTINO - sblock.fs_tinode)) 235: printf("%ld files missing, imax: %u tinode: %u\n", n_files, 236: imax,sblock.fs_tinode); 237: if (debug) { 238: if (enddup != duplist) { 239: printf("The following duplicate blocks remain:"); 240: for (; enddup > duplist; enddup--) 241: printf(" %ld,", *enddup); 242: printf("\n"); 243: } 244: for (zp = zlnlist; zp < zlnp; zp++) 245: if (*zp) break; 246: if (zp < zlnp) { 247: printf("The following zero link count inodes remain:"); 248: for (zp = zlnlist; zp < zlnp; zp++) 249: if (*zp) printf(" %ld,", *zp); 250: printf("\n"); 251: } 252: } 253: bzero(zlnlist, sizeof zlnlist); 254: bzero(duplist, sizeof duplist); 255: if (dfile.mod) { 256: (void)time(&sblock.fs_time); 257: sbdirty(); 258: } 259: ckfini(); 260: if (!dfile.mod) 261: return; 262: if (!preen) { 263: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 264: if (hotroot) 265: printf("\n***** REBOOT UNIX *****\n"); 266: } 267: if (hotroot) { 268: sync(); 269: exit(4); 270: } 271: } 272: 273: char * 274: blockcheck(name) 275: char *name; 276: { 277: struct stat stslash, stblock, stchar; 278: char *raw; 279: int looped = 0; 280: 281: hotroot = 0; 282: if (stat("/", &stslash) < 0){ 283: printf("Can't stat root\n"); 284: return (0); 285: } 286: retry: 287: if (stat(name, &stblock) < 0){ 288: printf("Can't stat %s\n", name); 289: return (0); 290: } 291: if (stblock.st_mode & S_IFBLK) { 292: raw = rawname(name); 293: if (stat(raw, &stchar) < 0){ 294: printf("Can't stat %s\n", raw); 295: return (0); 296: } 297: if (stchar.st_mode & S_IFCHR) { 298: if (stslash.st_dev == stblock.st_rdev) { 299: hotroot++; 300: raw = unrawname(name); 301: } 302: return (raw); 303: } else { 304: printf("%s is not a character device\n", raw); 305: return (0); 306: } 307: } else if (stblock.st_mode & S_IFCHR) { 308: if (looped) { 309: printf("Can't make sense out of name %s\n", name); 310: return (0); 311: } 312: name = unrawname(name); 313: looped++; 314: goto retry; 315: } 316: printf("Can't make sense out of name %s\n", name); 317: return (0); 318: } 319: 320: char * 321: unrawname(cp) 322: char *cp; 323: { 324: char *dp = rindex(cp, '/'); 325: struct stat stb; 326: 327: if (dp == 0) 328: return (cp); 329: if (stat(cp, &stb) < 0) 330: return (cp); 331: if ((stb.st_mode&S_IFMT) != S_IFCHR) 332: return (cp); 333: if (*(dp+1) != 'r') 334: return (cp); 335: (void)strcpy(dp+1, dp+2); 336: return (cp); 337: } 338: 339: char * 340: rawname(cp) 341: char *cp; 342: { 343: static char rawbuf[32]; 344: char *dp = rindex(cp, '/'); 345: 346: if (dp == 0) 347: return (0); 348: *dp = 0; 349: (void)strcpy(rawbuf, cp); 350: *dp = '/'; 351: (void)strcat(rawbuf, "/r"); 352: (void)strcat(rawbuf, dp+1); 353: return (rawbuf); 354: }