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.32 (Berkeley) 07/02/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, "dpnNyYb:c: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 cvtlevel = argtoi('c', "conversion level", optarg, 10); 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 int cylno; 147 148 if (preen && child) 149 (void)signal(SIGQUIT, voidquit); 150 devname = filesys; 151 if (debug && preen) 152 pwarn("starting\n"); 153 if (setup(filesys) == 0) { 154 if (preen) 155 pfatal("CAN'T CHECK FILE SYSTEM."); 156 return (0); 157 } 158 /* 159 * 1: scan inodes tallying blocks used 160 */ 161 if (preen == 0) { 162 printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 163 if (hotroot) 164 printf("** Root file system\n"); 165 printf("** Phase 1 - Check Blocks and Sizes\n"); 166 } 167 pass1(); 168 169 /* 170 * 1b: locate first references to duplicates, if any 171 */ 172 if (duplist) { 173 if (preen) 174 pfatal("INTERNAL ERROR: dups with -p"); 175 printf("** Phase 1b - Rescan For More DUPS\n"); 176 pass1b(); 177 } 178 179 /* 180 * 2: traverse directories from root to mark all connected directories 181 */ 182 if (preen == 0) 183 printf("** Phase 2 - Check Pathnames\n"); 184 pass2(); 185 186 /* 187 * 3: scan inodes looking for disconnected directories 188 */ 189 if (preen == 0) 190 printf("** Phase 3 - Check Connectivity\n"); 191 pass3(); 192 193 /* 194 * 4: scan inodes looking for disconnected files; check reference counts 195 */ 196 if (preen == 0) 197 printf("** Phase 4 - Check Reference Counts\n"); 198 pass4(); 199 200 /* 201 * 5: check and repair resource counts in cylinder groups 202 */ 203 if (preen == 0) 204 printf("** Phase 5 - Check Cyl groups\n"); 205 pass5(); 206 207 /* 208 * print out summary statistics 209 */ 210 n_ffree = sblock.fs_cstotal.cs_nffree; 211 n_bfree = sblock.fs_cstotal.cs_nbfree; 212 pwarn("%ld files, %ld used, %ld free ", 213 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 214 printf("(%ld frags, %ld blocks, %d.%d%% fragmentation)\n", 215 n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 216 ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 217 if (debug && 218 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 219 printf("%ld files missing\n", n_files); 220 if (debug) { 221 n_blks += sblock.fs_ncg * 222 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 223 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 224 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 225 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 226 printf("%ld blocks missing\n", n_blks); 227 if (duplist != NULL) { 228 printf("The following duplicate blocks remain:"); 229 for (dp = duplist; dp; dp = dp->next) 230 printf(" %ld,", dp->dup); 231 printf("\n"); 232 } 233 if (zlnhead != NULL) { 234 printf("The following zero link count inodes remain:"); 235 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 236 printf(" %lu,", zlnp->zlncnt); 237 printf("\n"); 238 } 239 } 240 zlnhead = (struct zlncnt *)0; 241 duplist = (struct dups *)0; 242 muldup = (struct dups *)0; 243 inocleanup(); 244 if (fsmodified) { 245 (void)time(&sblock.fs_time); 246 sbdirty(); 247 } 248 if (cvtlevel && sblk.b_dirty) { 249 /* 250 * Write out the duplicate super blocks 251 */ 252 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 253 bwrite(fswritefd, (char *)&sblock, 254 fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 255 } 256 ckfini(); 257 free(blockmap); 258 free(statemap); 259 free((char *)lncntp); 260 if (!fsmodified) 261 return (0); 262 if (!preen) { 263 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 264 if (hotroot) 265 printf("\n***** REBOOT UNIX *****\n"); 266 } 267 if (hotroot) { 268 sync(); 269 return (4); 270 } 271 return (0); 272 } 273