[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.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>