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