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