[BACK]Return to main.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / fsck_lfs

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>