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