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.4 (Berkeley) 04/27/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 if (setup(filesys) == 0) { 167 if (preen) 168 pfatal("CAN'T CHECK FILE SYSTEM."); 169 return (0); 170 } 171 /* 172 * 1: scan inodes tallying blocks used 173 */ 174 if (preen == 0) { 175 printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 176 if (hotroot) 177 printf("** Root file system\n"); 178 printf("** Phase 1 - Check Blocks and Sizes\n"); 179 } 180 pass1(); 181 182 /* 183 * 1b: locate first references to duplicates, if any 184 */ 185 if (duplist) { 186 if (preen) 187 pfatal("INTERNAL ERROR: dups with -p"); 188 printf("** Phase 1b - Rescan For More DUPS\n"); 189 pass1b(); 190 } 191 192 /* 193 * 2: traverse directories from root to mark all connected directories 194 */ 195 if (preen == 0) 196 printf("** Phase 2 - Check Pathnames\n"); 197 pass2(); 198 199 /* 200 * 3: scan inodes looking for disconnected directories 201 */ 202 if (preen == 0) 203 printf("** Phase 3 - Check Connectivity\n"); 204 pass3(); 205 206 /* 207 * 4: scan inodes looking for disconnected files; check reference counts 208 */ 209 if (preen == 0) 210 printf("** Phase 4 - Check Reference Counts\n"); 211 pass4(); 212 213 /* 214 * 5: check and repair resource counts in cylinder groups 215 */ 216 if (preen == 0) 217 printf("** Phase 5 - Check Cyl groups\n"); 218 pass5(); 219 220 /* 221 * print out summary statistics 222 */ 223 n_ffree = sblock.fs_cstotal.cs_nffree; 224 n_bfree = sblock.fs_cstotal.cs_nbfree; 225 pwarn("%ld files, %ld used, %ld free ", 226 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 227 printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 228 n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 229 ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 230 if (debug && 231 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 232 printf("%ld files missing\n", n_files); 233 if (debug) { 234 n_blks += sblock.fs_ncg * 235 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 236 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 237 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 238 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 239 printf("%ld blocks missing\n", n_blks); 240 if (duplist != NULL) { 241 printf("The following duplicate blocks remain:"); 242 for (dp = duplist; dp; dp = dp->next) 243 printf(" %ld,", dp->dup); 244 printf("\n"); 245 } 246 if (zlnhead != NULL) { 247 printf("The following zero link count inodes remain:"); 248 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 249 printf(" %lu,", zlnp->zlncnt); 250 printf("\n"); 251 } 252 } 253 zlnhead = (struct zlncnt *)0; 254 duplist = (struct dups *)0; 255 muldup = (struct dups *)0; 256 inocleanup(); 257 if (fsmodified) { 258 (void)time(&sblock.fs_time); 259 sbdirty(); 260 } 261 if (cvtlevel && sblk.b_dirty) { 262 /* 263 * Write out the duplicate super blocks 264 */ 265 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 266 bwrite(fswritefd, (char *)&sblock, 267 fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 268 } 269 ckfini(); 270 free(blockmap); 271 free(statemap); 272 free((char *)lncntp); 273 if (!fsmodified) 274 return (0); 275 if (!preen) 276 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 277 if (hotroot) { 278 struct statfs stfs_buf; 279 /* 280 * We modified the root. Do a mount update on 281 * it, unless it is read-write, so we can continue. 282 */ 283 if (statfs("/", &stfs_buf) == 0) { 284 long flags = stfs_buf.f_flags; 285 struct ufs_args args; 286 int ret; 287 288 if (flags & MNT_RDONLY) { 289 args.fspec = 0; 290 args.export.ex_flags = 0; 291 args.export.ex_root = 0; 292 flags |= MNT_UPDATE | MNT_RELOAD; 293 ret = mount("ufs", "/", flags, &args); 294 if (ret == 0) 295 return(0); 296 } 297 } 298 if (!preen) 299 printf("\n***** REBOOT NOW *****\n"); 300 sync(); 301 return (4); 302 } 303 return (0); 304 } 305