Annotation of src/sbin/fsck_lfs/main.c, Revision 1.28
1.28 ! perseant 1: /* $NetBSD: main.c,v 1.27 2005/09/23 12:10:34 jmmv 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/ufs/dinode.h>
36: #include <sys/mount.h>
37: #include <ufs/ufs/ufsmount.h>
38: #include <ufs/lfs/lfs.h>
1.13 perseant 39:
1.1 perseant 40: #include <fstab.h>
1.13 perseant 41: #include <stdarg.h>
1.1 perseant 42: #include <stdlib.h>
43: #include <string.h>
44: #include <ctype.h>
45: #include <stdio.h>
46: #include <unistd.h>
47: #include <err.h>
48:
49: #include "fsck.h"
50: #include "extern.h"
51: #include "fsutil.h"
52:
1.13 perseant 53: int returntosingle;
1.1 perseant 54:
1.25 christos 55: static int argtoi(int, const char *, const char *, int);
1.13 perseant 56: static int checkfilesys(const char *, char *, long, int);
57: static void usage(void);
58: extern void (*panic_func)(int, const char *, va_list);
1.1 perseant 59:
60: int
1.5 perseant 61: main(int argc, char **argv)
1.1 perseant 62: {
1.13 perseant 63: int ch;
64: int ret = 0;
1.25 christos 65: const char *optstring = "b:dfi:m:npPqy";
1.1 perseant 66:
67: skipclean = 1;
1.5 perseant 68: exitonfail = 0;
1.6 perseant 69: idaddr = 0x0;
1.13 perseant 70: panic_func = vmsg;
1.10 ad 71: while ((ch = getopt(argc, argv, optstring)) != -1) {
1.1 perseant 72: switch (ch) {
73: case 'b':
74: skipclean = 0;
1.13 perseant 75: bflag = argtoi('b', "number", optarg, 0);
1.1 perseant 76: printf("Alternate super block location: %d\n", bflag);
77: break;
78: case 'd':
79: debug++;
80: break;
1.5 perseant 81: case 'e':
82: exitonfail++;
1.7 perseant 83: break;
84: case 'f':
85: skipclean = 0;
1.5 perseant 86: break;
1.6 perseant 87: case 'i':
88: idaddr = strtol(optarg, NULL, 0);
89: break;
1.1 perseant 90: case 'm':
91: lfmode = argtoi('m', "mode", optarg, 8);
1.5 perseant 92: if (lfmode & ~07777)
1.13 perseant 93: err(1, "bad mode to -m: %o\n", lfmode);
1.1 perseant 94: printf("** lost+found creation mode %o\n", lfmode);
95: break;
96:
97: case 'n':
98: nflag++;
99: yflag = 0;
100: break;
101:
102: case 'p':
103: preen++;
1.16 dsl 104: break;
105:
1.19 christos 106: case 'P': /* Progress meter not implemented. */
107: break;
108:
1.22 perseant 109: case 'q':
110: quiet++;
1.1 perseant 111: break;
112:
113: case 'y':
114: yflag++;
115: nflag = 0;
116: break;
117:
118: default:
119: usage();
120: }
121: }
122:
123: argc -= optind;
124: argv += optind;
125:
126: if (!argc)
127: usage();
128:
129: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
1.13 perseant 130: (void) signal(SIGINT, catch);
1.1 perseant 131: if (preen)
1.13 perseant 132: (void) signal(SIGQUIT, catchquit);
1.1 perseant 133:
134: while (argc-- > 0)
1.13 perseant 135: (void) checkfilesys(blockcheck(*argv++), 0, 0L, 0);
1.1 perseant 136:
137: if (returntosingle)
138: ret = 2;
139:
140: exit(ret);
141: }
142:
143: static int
1.25 christos 144: argtoi(int flag, const char *req, const char *str, int base)
1.1 perseant 145: {
1.13 perseant 146: char *cp;
147: int ret;
1.1 perseant 148:
1.13 perseant 149: ret = (int) strtol(str, &cp, base);
1.1 perseant 150: if (cp == str || *cp)
1.13 perseant 151: err(1, "-%c flag requires a %s\n", flag, req);
1.1 perseant 152: return (ret);
153: }
154:
155: /*
1.13 perseant 156: * Check the specified filesystem.
1.1 perseant 157: */
158:
159: /* ARGSUSED */
160: static int
1.5 perseant 161: checkfilesys(const char *filesys, char *mntpt, long auxdata, int child)
1.1 perseant 162: {
1.13 perseant 163: struct dups *dp;
164: struct zlncnt *zlnp;
1.1 perseant 165:
166: if (preen && child)
1.13 perseant 167: (void) signal(SIGQUIT, voidquit);
1.1 perseant 168: setcdevname(filesys, preen);
169: if (debug && preen)
170: pwarn("starting\n");
171: switch (setup(filesys)) {
172: case 0:
173: if (preen)
174: pfatal("CAN'T CHECK FILE SYSTEM.");
175: case -1:
176: return (0);
177: }
178:
1.13 perseant 179: /*
180: * For LFS, "preen" means "roll forward". We don't check anything
181: * else.
182: */
1.5 perseant 183: if (preen == 0) {
1.13 perseant 184: printf("** Last Mounted on %s\n", fs->lfs_fsmnt);
1.1 perseant 185: if (hotroot())
186: printf("** Root file system\n");
1.13 perseant 187: /*
188: * 0: check segment checksums, inode ranges
189: */
1.21 perseant 190: printf("** Phase 0 - Check Inode Free List\n");
1.14 perseant 191: }
192: if (idaddr)
193: pwarn("-i given, skipping free list check\n");
194: else
195: pass0();
1.4 perseant 196:
1.14 perseant 197: if (preen == 0) {
1.4 perseant 198: /*
199: * 1: scan inodes tallying blocks used
200: */
1.13 perseant 201: printf("** Phase 1 - Check Blocks and Sizes\n");
1.4 perseant 202: pass1();
1.5 perseant 203:
1.4 perseant 204: /*
205: * 2: traverse directories from root to mark all connected directories
206: */
1.13 perseant 207: printf("** Phase 2 - Check Pathnames\n");
1.4 perseant 208: pass2();
1.5 perseant 209:
1.4 perseant 210: /*
211: * 3: scan inodes looking for disconnected directories
212: */
1.13 perseant 213: printf("** Phase 3 - Check Connectivity\n");
1.4 perseant 214: pass3();
1.5 perseant 215:
1.4 perseant 216: /*
217: * 4: scan inodes looking for disconnected files; check reference counts
218: */
1.13 perseant 219: printf("** Phase 4 - Check Reference Counts\n");
1.4 perseant 220: pass4();
1.24 perseant 221: }
1.4 perseant 222:
1.24 perseant 223: /*
224: * 5: check segment byte totals and dirty flags, and cleanerinfo
225: */
226: if (!preen)
1.13 perseant 227: printf("** Phase 5 - Check Segment Block Accounting\n");
1.24 perseant 228: pass5();
1.4 perseant 229:
1.24 perseant 230: if (debug && !preen) {
231: if (duplist != NULL) {
232: printf("The following duplicate blocks remain:");
233: for (dp = duplist; dp; dp = dp->next)
234: printf(" %lld,", (long long) dp->dup);
235: printf("\n");
236: }
237: if (zlnhead != NULL) {
238: printf("The following zero link count inodes remain:");
239: for (zlnp = zlnhead; zlnp; zlnp = zlnp->next)
1.26 christos 240: printf(" %llu,",
241: (unsigned long long)zlnp->zlncnt);
1.24 perseant 242: printf("\n");
1.13 perseant 243: }
1.1 perseant 244: }
1.24 perseant 245:
1.13 perseant 246: if (!rerun) {
247: if (!preen)
248: printf("** Phase 6 - Roll Forward\n");
249: pass6();
1.1 perseant 250: }
1.13 perseant 251: zlnhead = (struct zlncnt *) 0;
252: duplist = (struct dups *) 0;
253: muldup = (struct dups *) 0;
1.1 perseant 254: inocleanup();
1.4 perseant 255:
1.13 perseant 256: /*
257: * print out summary statistics
258: */
1.26 christos 259: pwarn("%llu files, %lld used, %lld free\n",
260: (unsigned long long)n_files, (long long) n_blks,
1.13 perseant 261: (long long) fs->lfs_bfree);
262:
1.1 perseant 263: ckfini(1);
1.13 perseant 264:
1.1 perseant 265: free(blockmap);
266: free(statemap);
267: free((char *)lncntp);
1.13 perseant 268: if (!fsmodified) {
1.1 perseant 269: return (0);
1.13 perseant 270: }
1.1 perseant 271: if (!preen)
272: printf("\n***** FILE SYSTEM WAS MODIFIED *****\n");
273: if (rerun)
274: printf("\n***** PLEASE RERUN FSCK *****\n");
275: if (hotroot()) {
1.18 christos 276: struct statvfs stfs_buf;
1.1 perseant 277: /*
278: * We modified the root. Do a mount update on
279: * it, unless it is read-write, so we can continue.
280: */
1.18 christos 281: if (statvfs("/", &stfs_buf) == 0) {
282: long flags = stfs_buf.f_flag;
1.1 perseant 283: struct ufs_args args;
1.13 perseant 284: int ret;
1.1 perseant 285:
286: if (flags & MNT_RDONLY) {
287: args.fspec = 0;
288: flags |= MNT_UPDATE | MNT_RELOAD;
289: ret = mount(MOUNT_LFS, "/", flags, &args);
290: if (ret == 0)
1.5 perseant 291: return (0);
1.1 perseant 292: }
293: }
294: if (!preen)
295: printf("\n***** REBOOT NOW *****\n");
296: sync();
297: return (4);
298: }
299: return (0);
300: }
301:
302: static void
1.20 xtraeme 303: usage(void)
1.1 perseant 304: {
1.9 cgd 305:
1.13 perseant 306: (void) fprintf(stderr,
1.23 wiz 307: "usage: %s [-dfpq] [-b block] [-m mode] [-y | -n] filesystem ...\n",
1.13 perseant 308: getprogname());
1.1 perseant 309: exit(1);
310: }
CVSweb <webmaster@jp.NetBSD.org>