1 /* 2 * Copyright (c) 1980, 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * %sccs.include.redist.c% 6 */ 7 8 #ifndef lint 9 char copyright[] = 10 "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\ 11 All rights reserved.\n"; 12 #endif /* not lint */ 13 14 #ifndef lint 15 static char sccsid[] = "@(#)main.c 5.31 (Berkeley) 05/27/92"; 16 #endif /* not lint */ 17 18 #include <sys/param.h> 19 #include <sys/time.h> 20 #include <ufs/ufs/dinode.h> 21 #include <ufs/ffs/fs.h> 22 #include <fstab.h> 23 #include <stdlib.h> 24 #include <string.h> 25 #include <ctype.h> 26 #include <stdio.h> 27 #include "fsck.h" 28 29 void catch(), catchquit(), voidquit(); 30 int returntosingle; 31 32 main(argc, argv) 33 int argc; 34 char *argv[]; 35 { 36 int ch; 37 int ret, maxrun = 0; 38 extern int docheck(), checkfilesys(); 39 extern char *optarg; 40 extern int optind; 41 42 sync(); 43 while ((ch = getopt(argc, argv, "cdpnNyYb:l:m:")) != EOF) { 44 switch (ch) { 45 case 'p': 46 preen++; 47 break; 48 49 case 'b': 50 bflag = argtoi('b', "number", optarg, 10); 51 printf("Alternate super block location: %d\n", bflag); 52 break; 53 54 case 'c': 55 cvtflag++; 56 break; 57 58 case 'd': 59 debug++; 60 break; 61 62 case 'l': 63 maxrun = argtoi('l', "number", optarg, 10); 64 break; 65 66 case 'm': 67 lfmode = argtoi('m', "mode", optarg, 8); 68 if (lfmode &~ 07777) 69 errexit("bad mode to -m: %o\n", lfmode); 70 printf("** lost+found creation mode %o\n", lfmode); 71 break; 72 73 case 'n': 74 case 'N': 75 nflag++; 76 yflag = 0; 77 break; 78 79 case 'y': 80 case 'Y': 81 yflag++; 82 nflag = 0; 83 break; 84 85 default: 86 errexit("%c option?\n", ch); 87 } 88 } 89 argc -= optind; 90 argv += optind; 91 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 92 (void)signal(SIGINT, catch); 93 if (preen) 94 (void)signal(SIGQUIT, catchquit); 95 if (argc) { 96 while (argc-- > 0) 97 (void)checkfilesys(*argv++, (char *)0, 0L, 0); 98 exit(0); 99 } 100 ret = checkfstab(preen, maxrun, docheck, checkfilesys); 101 if (returntosingle) 102 exit(2); 103 exit(ret); 104 } 105 106 argtoi(flag, req, str, base) 107 int flag; 108 char *req, *str; 109 int base; 110 { 111 char *cp; 112 int ret; 113 114 ret = (int)strtol(str, &cp, base); 115 if (cp == str || *cp) 116 errexit("-%c flag requires a %s\n", flag, req); 117 return (ret); 118 } 119 120 /* 121 * Determine whether a filesystem should be checked. 122 */ 123 docheck(fsp) 124 register struct fstab *fsp; 125 { 126 127 if (strcmp(fsp->fs_vfstype, "ufs") || 128 (strcmp(fsp->fs_type, FSTAB_RW) && 129 strcmp(fsp->fs_type, FSTAB_RO)) || 130 fsp->fs_passno == 0) 131 return (0); 132 return (1); 133 } 134 135 /* 136 * Check the specified filesystem. 137 */ 138 /* ARGSUSED */ 139 checkfilesys(filesys, mntpt, auxdata, child) 140 char *filesys, *mntpt; 141 long auxdata; 142 { 143 daddr_t n_ffree, n_bfree; 144 struct dups *dp; 145 struct zlncnt *zlnp; 146 147 if (preen && child) 148 (void)signal(SIGQUIT, voidquit); 149 devname = filesys; 150 if (debug && preen) 151 pwarn("starting\n"); 152 if (setup(filesys) == 0) { 153 if (preen) 154 pfatal("CAN'T CHECK FILE SYSTEM."); 155 return (0); 156 } 157 /* 158 * 1: scan inodes tallying blocks used 159 */ 160 if (preen == 0) { 161 printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 162 if (hotroot) 163 printf("** Root file system\n"); 164 printf("** Phase 1 - Check Blocks and Sizes\n"); 165 } 166 pass1(); 167 168 /* 169 * 1b: locate first references to duplicates, if any 170 */ 171 if (duplist) { 172 if (preen) 173 pfatal("INTERNAL ERROR: dups with -p"); 174 printf("** Phase 1b - Rescan For More DUPS\n"); 175 pass1b(); 176 } 177 178 /* 179 * 2: traverse directories from root to mark all connected directories 180 */ 181 if (preen == 0) 182 printf("** Phase 2 - Check Pathnames\n"); 183 pass2(); 184 185 /* 186 * 3: scan inodes looking for disconnected directories 187 */ 188 if (preen == 0) 189 printf("** Phase 3 - Check Connectivity\n"); 190 pass3(); 191 192 /* 193 * 4: scan inodes looking for disconnected files; check reference counts 194 */ 195 if (preen == 0) 196 printf("** Phase 4 - Check Reference Counts\n"); 197 pass4(); 198 199 /* 200 * 5: check and repair resource counts in cylinder groups 201 */ 202 if (preen == 0) 203 printf("** Phase 5 - Check Cyl groups\n"); 204 pass5(); 205 206 /* 207 * print out summary statistics 208 */ 209 n_ffree = sblock.fs_cstotal.cs_nffree; 210 n_bfree = sblock.fs_cstotal.cs_nbfree; 211 pwarn("%ld files, %ld used, %ld free ", 212 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 213 printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 214 n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 215 ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 216 if (debug && 217 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 218 printf("%ld files missing\n", n_files); 219 if (debug) { 220 n_blks += sblock.fs_ncg * 221 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 222 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 223 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 224 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 225 printf("%ld blocks missing\n", n_blks); 226 if (duplist != NULL) { 227 printf("The following duplicate blocks remain:"); 228 for (dp = duplist; dp; dp = dp->next) 229 printf(" %ld,", dp->dup); 230 printf("\n"); 231 } 232 if (zlnhead != NULL) { 233 printf("The following zero link count inodes remain:"); 234 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 235 printf(" %lu,", zlnp->zlncnt); 236 printf("\n"); 237 } 238 } 239 zlnhead = (struct zlncnt *)0; 240 duplist = (struct dups *)0; 241 muldup = (struct dups *)0; 242 inocleanup(); 243 if (fsmodified) { 244 (void)time(&sblock.fs_time); 245 sbdirty(); 246 } 247 ckfini(); 248 free(blockmap); 249 free(statemap); 250 free((char *)lncntp); 251 if (!fsmodified) 252 return (0); 253 if (!preen) { 254 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 255 if (hotroot) 256 printf("\n***** REBOOT UNIX *****\n"); 257 } 258 if (hotroot) { 259 sync(); 260 return (4); 261 } 262 return (0); 263 } 264