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