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