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