1 /* 2 * Copyright (c) 1980, 1986 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms are permitted 6 * provided that the above copyright notice and this paragraph are 7 * duplicated in all such forms and that any documentation, 8 * advertising materials, and other materials related to such 9 * distribution and use acknowledge that the software was developed 10 * by the University of California, Berkeley. The name of the 11 * University may not be used to endorse or promote products derived 12 * from this software without specific prior written permission. 13 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 14 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 16 */ 17 18 #ifndef lint 19 char copyright[] = 20 "@(#) Copyright (c) 1980, 1986 The Regents of the University of California.\n\ 21 All rights reserved.\n"; 22 #endif /* not lint */ 23 24 #ifndef lint 25 static char sccsid[] = "@(#)main.c 5.21 (Berkeley) 04/26/90"; 26 #endif /* not lint */ 27 28 #include <sys/param.h> 29 #include <ufs/dinode.h> 30 #include <ufs/fs.h> 31 #include <fstab.h> 32 #include <strings.h> 33 #include <ctype.h> 34 #include "fsck.h" 35 36 void catch(), catchquit(), voidquit(); 37 int returntosingle; 38 39 main(argc, argv) 40 int argc; 41 char *argv[]; 42 { 43 int ret, maxrun = 0; 44 extern int (docheck)(), (checkfilesys)(); 45 46 sync(); 47 while (--argc > 0 && **++argv == '-') { 48 switch (*++*argv) { 49 50 case 'p': 51 preen++; 52 break; 53 54 case 'b': 55 if (argv[0][1] != '\0') { 56 bflag = atoi(argv[0]+1); 57 } else { 58 bflag = atoi(*++argv); 59 argc--; 60 } 61 printf("Alternate super block location: %d\n", bflag); 62 break; 63 64 case 'c': 65 cvtflag++; 66 break; 67 68 case 'd': 69 debug++; 70 break; 71 72 case 'l': 73 if (!isdigit(argv[1][0])) 74 errexit("-l flag requires a number\n"); 75 maxrun = atoi(*++argv); 76 argc--; 77 break; 78 79 case 'm': 80 if (!isdigit(argv[1][0])) 81 errexit("-m flag requires a mode\n"); 82 sscanf(*++argv, "%o", &lfmode); 83 if (lfmode &~ 07777) 84 errexit("bad mode to -m: %o\n", lfmode); 85 argc--; 86 printf("** lost+found creation mode %o\n", lfmode); 87 break; 88 89 case 'n': 90 case 'N': 91 nflag++; 92 yflag = 0; 93 break; 94 95 case 'y': 96 case 'Y': 97 yflag++; 98 nflag = 0; 99 break; 100 101 default: 102 errexit("%c option?\n", **argv); 103 } 104 } 105 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 106 (void)signal(SIGINT, catch); 107 if (preen) 108 (void)signal(SIGQUIT, catchquit); 109 if (argc) { 110 while (argc-- > 0) { 111 hotroot = 0; 112 checkfilesys(*argv++); 113 } 114 exit(0); 115 } 116 ret = checkfstab(preen, maxrun, docheck, checkfilesys); 117 if (returntosingle) 118 exit(2); 119 exit(ret); 120 } 121 122 /* 123 * Determine whether a filesystem should be checked. 124 */ 125 docheck(fsp) 126 register struct fstab *fsp; 127 { 128 129 if (strcmp(fsp->fs_vfstype, "ufs") || 130 (strcmp(fsp->fs_type, FSTAB_RW) && 131 strcmp(fsp->fs_type, FSTAB_RO)) || 132 fsp->fs_passno == 0) 133 return (0); 134 return (1); 135 } 136 137 /* 138 * Check the specified filesystem. 139 */ 140 /* ARGSUSED */ 141 checkfilesys(filesys, mntpt, auxdata) 142 char *filesys, *mntpt; 143 long auxdata; 144 { 145 daddr_t n_ffree, n_bfree; 146 struct dups *dp; 147 struct zlncnt *zlnp; 148 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("%d files, %d used, %d free ", 213 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 214 printf("(%d frags, %d blocks, %.1f%% fragmentation)\n", 215 n_ffree, n_bfree, (float)(n_ffree * 100) / sblock.fs_dsize); 216 if (debug && 217 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 218 printf("%d files missing\n", n_files); 219 if (debug) { 220 n_blks += sblock.fs_ncg * 221 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 222 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 223 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 224 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 225 printf("%d blocks missing\n", n_blks); 226 if (duplist != NULL) { 227 printf("The following duplicate blocks remain:"); 228 for (dp = duplist; dp; dp = dp->next) 229 printf(" %d,", dp->dup); 230 printf("\n"); 231 } 232 if (zlnhead != NULL) { 233 printf("The following zero link count inodes remain:"); 234 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 235 printf(" %d,", zlnp->zlncnt); 236 printf("\n"); 237 } 238 } 239 zlnhead = (struct zlncnt *)0; 240 duplist = (struct dups *)0; 241 inocleanup(); 242 if (fsmodified) { 243 (void)time(&sblock.fs_time); 244 sbdirty(); 245 } 246 ckfini(); 247 free(blockmap); 248 free(statemap); 249 free((char *)lncntp); 250 if (!fsmodified) 251 return (0); 252 if (!preen) { 253 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 254 if (hotroot) 255 printf("\n***** REBOOT UNIX *****\n"); 256 } 257 if (hotroot) { 258 sync(); 259 return (4); 260 } 261 return (0); 262 } 263