Annotation of src/sbin/fsck_lfs/main.c, Revision 1.48
1.47 dholland 1: /* $NetBSD: main.c,v 1.46 2014/07/12 16:11:27 dholland Exp $ */
1.1 perseant 2:
3: /*
4: * Copyright (c) 1980, 1986, 1993
5: * The Regents of the University of California. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
1.15 agc 15: * 3. Neither the name of the University nor the names of its contributors
1.1 perseant 16: * may be used to endorse or promote products derived from this software
17: * without specific prior written permission.
18: *
19: * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22: * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29: * SUCH DAMAGE.
30: */
31:
32: #include <sys/param.h>
33: #include <sys/time.h>
34: #include <sys/mount.h>
35: #include <ufs/lfs/lfs.h>
1.13 perseant 36:
1.1 perseant 37: #include <fstab.h>
1.46 dholland 38: #include <stdbool.h>
1.13 perseant 39: #include <stdarg.h>
1.1 perseant 40: #include <stdlib.h>
41: #include <string.h>
42: #include <ctype.h>
43: #include <stdio.h>
44: #include <unistd.h>
45: #include <err.h>
1.31 christos 46: #include <util.h>
1.34 drochner 47: #include <signal.h>
1.1 perseant 48:
49: #include "fsck.h"
50: #include "extern.h"
51: #include "fsutil.h"
1.37 christos 52: #include "exitvalues.h"
1.1 perseant 53:
1.42 christos 54: volatile sig_atomic_t returntosingle = 0;
1.1 perseant 55:
1.25 christos 56: static int argtoi(int, const char *, const char *, int);
1.13 perseant 57: static int checkfilesys(const char *, char *, long, int);
58: static void usage(void);
1.31 christos 59: static void efun(int, const char *, ...);
1.48 ! dholland 60: extern void (*panic_func)(int, const char *, va_list);
1.1 perseant 61:
1.31 christos 62: static void
63: efun(int eval, const char *fmt, ...)
64: {
65: va_list ap;
66: va_start(ap, fmt);
67: verr(EEXIT, fmt, ap);
68: va_end(ap);
69: }
70:
1.1 perseant 71: int
1.5 perseant 72: main(int argc, char **argv)
1.1 perseant 73: {
1.13 perseant 74: int ch;
1.37 christos 75: int ret = FSCK_EXIT_OK;
1.38 christos 76: const char *optstring = "b:dfi:m:npPqUy";
1.46 dholland 77: bool reallypreen;
1.1 perseant 78:
1.46 dholland 79: reallypreen = false;
1.43 christos 80: ckfinish = ckfini;
1.1 perseant 81: skipclean = 1;
1.5 perseant 82: exitonfail = 0;
1.6 perseant 83: idaddr = 0x0;
1.48 ! dholland 84: panic_func = vmsg;
1.31 christos 85: esetfunc(efun);
1.10 ad 86: while ((ch = getopt(argc, argv, optstring)) != -1) {
1.1 perseant 87: switch (ch) {
88: case 'b':
89: skipclean = 0;
1.13 perseant 90: bflag = argtoi('b', "number", optarg, 0);
1.1 perseant 91: printf("Alternate super block location: %d\n", bflag);
92: break;
93: case 'd':
94: debug++;
95: break;
1.5 perseant 96: case 'e':
97: exitonfail++;
1.7 perseant 98: break;
99: case 'f':
100: skipclean = 0;
1.46 dholland 101: reallypreen = true;
1.5 perseant 102: break;
1.6 perseant 103: case 'i':
104: idaddr = strtol(optarg, NULL, 0);
105: break;
1.1 perseant 106: case 'm':
107: lfmode = argtoi('m', "mode", optarg, 8);
1.5 perseant 108: if (lfmode & ~07777)
1.13 perseant 109: err(1, "bad mode to -m: %o\n", lfmode);
1.1 perseant 110: printf("** lost+found creation mode %o\n", lfmode);
111: break;
112:
113: case 'n':
114: nflag++;
115: yflag = 0;
116: break;
117:
118: case 'p':
119: preen++;
1.16 dsl 120: break;
121:
1.19 christos 122: case 'P': /* Progress meter not implemented. */
123: break;
124:
1.22 perseant 125: case 'q':
126: quiet++;
1.1 perseant 127: break;
1.38 christos 128: #ifndef SMALL
129: case 'U':
130: Uflag++;
131: break;
132: #endif
1.1 perseant 133: case 'y':
134: yflag++;
135: nflag = 0;
136: break;
137:
138: default:
139: usage();
140: }
141: }
142:
143: argc -= optind;
144: argv += optind;
145:
146: if (!argc)
147: usage();
148:
1.46 dholland 149: /*
150: * Don't do anything in preen mode. This is a replacement for
151: * version 1.111 of src/distrib/utils/sysinst/disks.c, which
152: * disabled fsck on installer-generated lfs partitions. That
153: * isn't the right way to do it; better to run fsck but have
154: * it not do anything, so that when the issues in fsck get
155: * resolved it can be turned back on.
156: *
157: * If you really want to run fsck in preen mode you can do:
158: * fsck_lfs -p -f image
159: *
160: * This was prompted by
161: * http://mail-index.netbsd.org/tech-kern/2010/02/09/msg007306.html.
162: *
163: * It would be nice if someone prepared a more detailed report
164: * of the problems.
165: *
166: * XXX.
167: */
168: if (preen && !reallypreen) {
169: return ret;
170: }
171:
1.1 perseant 172: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1.13 perseant 173: (void) signal(SIGINT, catch);
1.1 perseant 174: if (preen)
1.13 perseant 175: (void) signal(SIGQUIT, catchquit);
1.1 perseant 176:
1.37 christos 177: while (argc-- > 0) {
178: int nret = checkfilesys(blockcheck(*argv++), 0, 0L, 0);
179: if (ret < nret)
180: ret = nret;
181: }
1.1 perseant 182:
1.37 christos 183: return returntosingle ? FSCK_EXIT_UNRESOLVED : ret;
1.1 perseant 184: }
185:
186: static int
1.25 christos 187: argtoi(int flag, const char *req, const char *str, int base)
1.1 perseant 188: {
1.13 perseant 189: char *cp;
190: int ret;
1.1 perseant 191:
1.13 perseant 192: ret = (int) strtol(str, &cp, base);
1.1 perseant 193: if (cp == str || *cp)
1.37 christos 194: err(FSCK_EXIT_USAGE, "-%c flag requires a %s\n", flag, req);
1.1 perseant 195: return (ret);
196: }
197:
198: /*
1.13 perseant 199: * Check the specified filesystem.
1.1 perseant 200: */
201:
202: /* ARGSUSED */
203: static int
1.5 perseant 204: checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
1.1 perseant 205: {
1.13 perseant 206: struct dups *dp;
207: struct zlncnt *zlnp;
1.1 perseant 208:
209: if (preen && child)
1.13 perseant 210: (void) signal(SIGQUIT, voidquit);
1.1 perseant 211: setcdevname(filesys, preen);
212: if (debug && preen)
213: pwarn("starting\n");
214: switch (setup(filesys)) {
215: case 0:
216: if (preen)
217: pfatal("CAN'T CHECK FILE SYSTEM.");
218: case -1:
1.37 christos 219: return FSCK_EXIT_OK;
1.1 perseant 220: }
221:
1.13 perseant 222: /*
223: * For LFS, "preen" means "roll forward". We don't check anything
224: * else.
225: */
1.5 perseant 226: if (preen == 0) {
1.13 perseant 227: printf("** Last Mounted on %s\n", fs->lfs_fsmnt);
1.1 perseant 228: if (hotroot())
229: printf("** Root file system\n");
1.13 perseant 230: /*
231: * 0: check segment checksums, inode ranges
232: */
1.21 perseant 233: printf("** Phase 0 - Check Inode Free List\n");
1.14 perseant 234: }
1.29 perseant 235:
236: /*
237: * Check inode free list - we do this even if idaddr is set,
238: * since if we're writing we don't want to write a bad list.
239: */
240: pass0();
1.4 perseant 241:
1.14 perseant 242: if (preen == 0) {
1.4 perseant 243: /*
244: * 1: scan inodes tallying blocks used
245: */
1.13 perseant 246: printf("** Phase 1 - Check Blocks and Sizes\n");
1.4 perseant 247: pass1();
1.5 perseant 248:
1.4 perseant 249: /*
250: * 2: traverse directories from root to mark all connected directories
251: */
1.13 perseant 252: printf("** Phase 2 - Check Pathnames\n");
1.4 perseant 253: pass2();
1.5 perseant 254:
1.4 perseant 255: /*
256: * 3: scan inodes looking for disconnected directories
257: */
1.13 perseant 258: printf("** Phase 3 - Check Connectivity\n");
1.4 perseant 259: pass3();
1.5 perseant 260:
1.4 perseant 261: /*
262: * 4: scan inodes looking for disconnected files; check reference counts
263: */
1.13 perseant 264: printf("** Phase 4 - Check Reference Counts\n");
1.4 perseant 265: pass4();
1.24 perseant 266: }
1.4 perseant 267:
1.24 perseant 268: /*
269: * 5: check segment byte totals and dirty flags, and cleanerinfo
270: */
271: if (!preen)
1.13 perseant 272: printf("** Phase 5 - Check Segment Block Accounting\n");
1.24 perseant 273: pass5();
1.4 perseant 274:
1.24 perseant 275: if (debug && !preen) {
276: if (duplist != NULL) {
277: printf("The following duplicate blocks remain:");
278: for (dp = duplist; dp; dp = dp->next)
279: printf(" %lld,", (long long) dp->dup);
280: printf("\n");
281: }
282: if (zlnhead != NULL) {
283: printf("The following zero link count inodes remain:");
284: for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
1.26 christos 285: printf(" %llu,",
286: (unsigned long long)zlnp->zlncnt);
1.24 perseant 287: printf("\n");
1.13 perseant 288: }
1.1 perseant 289: }
1.24 perseant 290:
1.13 perseant 291: if (!rerun) {
1.32 tls 292: if (!preen) {
293: if (reply("ROLL FILESYSTEM FORWARD") == 1) {
294: printf("** Phase 6 - Roll Forward\n");
295: pass6();
296: }
297: }
298: else {
299: pass6();
300: }
1.1 perseant 301: }
1.13 perseant 302: zlnhead = (struct zlncnt *) 0;
1.30 perseant 303: orphead = (struct zlncnt *) 0;
1.13 perseant 304: duplist = (struct dups *) 0;
305: muldup = (struct dups *) 0;
1.1 perseant 306: inocleanup();
1.4 perseant 307:
1.13 perseant 308: /*
309: * print out summary statistics
310: */
1.26 christos 311: pwarn("%llu files, %lld used, %lld free\n",
312: (unsigned long long)n_files, (long long) n_blks,
1.13 perseant 313: (long long) fs->lfs_bfree);
314:
1.1 perseant 315: ckfini(1);
1.13 perseant 316:
1.1 perseant 317: free(blockmap);
318: free(statemap);
319: free((char *)lncntp);
1.13 perseant 320: if (!fsmodified) {
1.37 christos 321: return FSCK_EXIT_OK;
1.13 perseant 322: }
1.1 perseant 323: if (!preen)
324: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
325: if (rerun)
326: printf("\n***** PLEASE RERUN FSCK *****\n");
327: if (hotroot()) {
1.18 christos 328: struct statvfs stfs_buf;
1.1 perseant 329: /*
330: * We modified the root. Do a mount update on
331: * it, unless it is read-write, so we can continue.
332: */
1.18 christos 333: if (statvfs("/", &stfs_buf) == 0) {
334: long flags = stfs_buf.f_flag;
1.44 dholland 335: struct ulfs_args args;
1.1 perseant 336:
337: if (flags & MNT_RDONLY) {
338: args.fspec = 0;
339: flags |= MNT_UPDATE | MNT_RELOAD;
1.37 christos 340: if (mount(MOUNT_LFS, "/", flags,
341: &args, sizeof args) == 0)
342: return FSCK_EXIT_OK;
1.1 perseant 343: }
344: }
345: if (!preen)
346: printf("\n***** REBOOT NOW *****\n");
347: sync();
1.37 christos 348: return FSCK_EXIT_ROOT_CHANGED;
1.1 perseant 349: }
1.37 christos 350: return FSCK_EXIT_OK;
1.1 perseant 351: }
352:
353: static void
1.20 xtraeme 354: usage(void)
1.1 perseant 355: {
1.9 cgd 356:
1.13 perseant 357: (void) fprintf(stderr,
1.40 wiz 358: "Usage: %s [-dfpqU] [-b block] [-m mode] [-y | -n] filesystem ...\n",
1.13 perseant 359: getprogname());
1.37 christos 360: exit(FSCK_EXIT_USAGE);
1.1 perseant 361: }
CVSweb <webmaster@jp.NetBSD.org>