1 /* 2 * Copyright (c) 1980, 1986, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the following acknowledgement: 15 * This product includes software developed by the University of 16 * California, Berkeley and its contributors. 17 * 4. Neither the name of the University nor the names of its contributors 18 * may be used to endorse or promote products derived from this software 19 * without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 */ 33 34 #ifndef lint 35 static const char copyright[] = 36 "@(#) Copyright (c) 1980, 1986, 1993\n\ 37 The Regents of the University of California. All rights reserved.\n"; 38 #endif /* not lint */ 39 40 #ifndef lint 41 static const char sccsid[] = "@(#)main.c 8.2 (Berkeley) 1/23/94"; 42 #endif /* not lint */ 43 44 #include <sys/param.h> 45 #include <sys/time.h> 46 #include <sys/proc.h> 47 #include <sys/mount.h> 48 #include <ufs/ufs/dinode.h> 49 #include <ufs/ffs/fs.h> 50 #include <fstab.h> 51 #include <stdlib.h> 52 #include <unistd.h> 53 #include <string.h> 54 #include <ctype.h> 55 #include <stdio.h> 56 #include "fsck.h" 57 static int argtoi __P((int flag, char *req, char *str, int base)); 58 static int docheck __P((struct fstab *fsp)); 59 static int checkfilesys __P((char *filesys, char *mntpt, long auxdata, 60 int child)); 61 62 int 63 main(argc, argv) 64 int argc; 65 char *argv[]; 66 { 67 int ch; 68 int ret, maxrun = 0; 69 extern char *optarg; 70 extern int optind; 71 72 sync(); 73 while ((ch = getopt(argc, argv, "dfpnNyYb:c:l:m:")) != EOF) { 74 switch (ch) { 75 case 'p': 76 preen++; 77 break; 78 79 case 'b': 80 bflag = argtoi('b', "number", optarg, 10); 81 printf("Alternate super block location: %d\n", bflag); 82 break; 83 84 case 'c': 85 cvtlevel = argtoi('c', "conversion level", optarg, 10); 86 break; 87 88 case 'd': 89 debug++; 90 break; 91 92 case 'f': 93 fflag++; 94 break; 95 96 case 'l': 97 maxrun = argtoi('l', "number", optarg, 10); 98 break; 99 100 case 'm': 101 lfmode = argtoi('m', "mode", optarg, 8); 102 if (lfmode &~ 07777) 103 errexit("bad mode to -m: %o\n", lfmode); 104 printf("** lost+found creation mode %o\n", lfmode); 105 break; 106 107 case 'n': 108 case 'N': 109 nflag++; 110 yflag = 0; 111 break; 112 113 case 'y': 114 case 'Y': 115 yflag++; 116 nflag = 0; 117 break; 118 119 default: 120 errexit("%c option?\n", ch); 121 } 122 } 123 argc -= optind; 124 argv += optind; 125 if (signal(SIGINT, SIG_IGN) != SIG_IGN) 126 (void)signal(SIGINT, catch); 127 if (preen) 128 (void)signal(SIGQUIT, catchquit); 129 if (argc) { 130 while (argc-- > 0) 131 (void)checkfilesys(blockcheck(*argv++), 0, 0L, 0); 132 exit(0); 133 } 134 ret = checkfstab(preen, maxrun, docheck, checkfilesys); 135 if (returntosingle) 136 exit(2); 137 exit(ret); 138 } 139 140 int 141 argtoi(flag, req, str, base) 142 int flag; 143 char *req, *str; 144 int base; 145 { 146 char *cp; 147 int ret; 148 149 ret = (int)strtol(str, &cp, base); 150 if (cp == str || *cp) 151 errexit("-%c flag requires a %s\n", flag, req); 152 return (ret); 153 } 154 155 /* 156 * Determine whether a filesystem should be checked. 157 */ 158 int 159 docheck(fsp) 160 register struct fstab *fsp; 161 { 162 163 if (strcmp(fsp->fs_vfstype, "ufs") || 164 (strcmp(fsp->fs_type, FSTAB_RW) && 165 strcmp(fsp->fs_type, FSTAB_RO)) || 166 fsp->fs_passno == 0) 167 return (0); 168 return (1); 169 } 170 171 /* 172 * Check the specified filesystem. 173 */ 174 /* ARGSUSED */ 175 int 176 checkfilesys(filesys, mntpt, auxdata, child) 177 char *filesys, *mntpt; 178 long auxdata; 179 int child; 180 { 181 daddr_t n_ffree, n_bfree; 182 struct dups *dp; 183 struct zlncnt *zlnp; 184 int cylno; 185 186 if (preen && child) 187 (void)signal(SIGQUIT, voidquit); 188 cdevname = filesys; 189 if (debug && preen) 190 pwarn("starting\n"); 191 if (setup(filesys) == 0) { 192 if (preen) 193 pfatal("CAN'T CHECK FILE SYSTEM."); 194 return (0); 195 } 196 197 if (preen && sblock.fs_clean && !fflag) { 198 pwarn("clean, %ld free ", sblock.fs_cstotal.cs_nffree + 199 sblock.fs_frag * sblock.fs_cstotal.cs_nbfree); 200 printf("(%ld frags, %ld blocks, %.1f%% fragmentation)\n", 201 sblock.fs_cstotal.cs_nffree, 202 sblock.fs_cstotal.cs_nbfree, 203 (float)(sblock.fs_cstotal.cs_nffree * 100) / 204 sblock.fs_dsize); 205 return(0); 206 } 207 208 /* 209 * 1: scan inodes tallying blocks used 210 */ 211 if (preen == 0) { 212 printf("** Last Mounted on %s\n", sblock.fs_fsmnt); 213 if (hotroot) 214 printf("** Root file system\n"); 215 printf("** Phase 1 - Check Blocks and Sizes\n"); 216 } 217 pass1(); 218 219 /* 220 * 1b: locate first references to duplicates, if any 221 */ 222 if (duplist) { 223 if (preen) 224 pfatal("INTERNAL ERROR: dups with -p"); 225 printf("** Phase 1b - Rescan For More DUPS\n"); 226 pass1b(); 227 } 228 229 /* 230 * 2: traverse directories from root to mark all connected directories 231 */ 232 if (preen == 0) 233 printf("** Phase 2 - Check Pathnames\n"); 234 pass2(); 235 236 /* 237 * 3: scan inodes looking for disconnected directories 238 */ 239 if (preen == 0) 240 printf("** Phase 3 - Check Connectivity\n"); 241 pass3(); 242 243 /* 244 * 4: scan inodes looking for disconnected files; check reference counts 245 */ 246 if (preen == 0) 247 printf("** Phase 4 - Check Reference Counts\n"); 248 pass4(); 249 250 /* 251 * 5: check and repair resource counts in cylinder groups 252 */ 253 if (preen == 0) 254 printf("** Phase 5 - Check Cyl groups\n"); 255 pass5(); 256 257 /* 258 * print out summary statistics 259 */ 260 n_ffree = sblock.fs_cstotal.cs_nffree; 261 n_bfree = sblock.fs_cstotal.cs_nbfree; 262 pwarn("%ld files, %ld used, %ld free ", 263 n_files, n_blks, n_ffree + sblock.fs_frag * n_bfree); 264 printf("(%ld frags, %ld blocks, %ld.%ld%% fragmentation)\n", 265 n_ffree, n_bfree, (n_ffree * 100) / sblock.fs_dsize, 266 ((n_ffree * 1000 + sblock.fs_dsize / 2) / sblock.fs_dsize) % 10); 267 if (debug && 268 (n_files -= maxino - ROOTINO - sblock.fs_cstotal.cs_nifree)) 269 printf("%ld files missing\n", n_files); 270 if (debug) { 271 n_blks += sblock.fs_ncg * 272 (cgdmin(&sblock, 0) - cgsblock(&sblock, 0)); 273 n_blks += cgsblock(&sblock, 0) - cgbase(&sblock, 0); 274 n_blks += howmany(sblock.fs_cssize, sblock.fs_fsize); 275 if (n_blks -= maxfsblock - (n_ffree + sblock.fs_frag * n_bfree)) 276 printf("%ld blocks missing\n", n_blks); 277 if (duplist != NULL) { 278 printf("The following duplicate blocks remain:"); 279 for (dp = duplist; dp; dp = dp->next) 280 printf(" %ld,", dp->dup); 281 printf("\n"); 282 } 283 if (zlnhead != NULL) { 284 printf("The following zero link count inodes remain:"); 285 for (zlnp = zlnhead; zlnp; zlnp = zlnp->next) 286 printf(" %lu,", zlnp->zlncnt); 287 printf("\n"); 288 } 289 } 290 zlnhead = (struct zlncnt *)0; 291 duplist = (struct dups *)0; 292 muldup = (struct dups *)0; 293 inocleanup(); 294 if (fsmodified) { 295 (void)time(&sblock.fs_time); 296 sbdirty(); 297 } 298 if (cvtlevel && sblk.b_dirty) { 299 /* 300 * Write out the duplicate super blocks 301 */ 302 for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 303 bwrite(fswritefd, (char *)&sblock, 304 fsbtodb(&sblock, cgsblock(&sblock, cylno)), SBSIZE); 305 } 306 ckfini(); 307 free(blockmap); 308 free(statemap); 309 free((char *)lncntp); 310 if (!fsmodified) 311 return (0); 312 if (!preen) 313 printf("\n***** FILE SYSTEM WAS MODIFIED *****\n"); 314 if (hotroot) { 315 struct statfs stfs_buf; 316 /* 317 * We modified the root. Do a mount update on 318 * it, unless it is read-write, so we can continue. 319 */ 320 if (statfs("/", &stfs_buf) == 0) { 321 long flags = stfs_buf.f_flags; 322 struct ufs_args args; 323 int ret; 324 325 if (flags & MNT_RDONLY) { 326 args.fspec = 0; 327 args.export.ex_flags = 0; 328 args.export.ex_root = 0; 329 flags |= MNT_UPDATE | MNT_RELOAD; 330 ret = mount(MOUNT_UFS, "/", flags, &args); 331 if (ret == 0) 332 return(0); 333 } 334 } 335 if (!preen) 336 printf("\n***** REBOOT NOW *****\n"); 337 sync(); 338 return (4); 339 } 340 return (0); 341 } 342