Annotation of 43BSDReno/sbin/fsck/setup.c, revision 1.1.1.1

1.1       root        1: /*
                      2:  * Copyright (c) 1980, 1986 The Regents of the University of California.
                      3:  * All rights reserved.
                      4:  *
                      5:  * Redistribution and use in source and binary forms are permitted provided
                      6:  * that: (1) source distributions retain this entire copyright notice and
                      7:  * comment, and (2) distributions including binaries display the following
                      8:  * acknowledgement:  ``This product includes software developed by the
                      9:  * University of California, Berkeley and its contributors'' in the
                     10:  * documentation or other materials provided with the distribution and in
                     11:  * all advertising materials mentioning features or use of this software.
                     12:  * Neither the name of the University nor the names of its contributors may
                     13:  * be used to endorse or promote products derived from this software without
                     14:  * specific prior written permission.
                     15:  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
                     16:  * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
                     17:  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
                     18:  */
                     19: 
                     20: #ifndef lint
                     21: static char sccsid[] = "@(#)setup.c    5.32 (Berkeley) 7/22/90";
                     22: #endif /* not lint */
                     23: 
                     24: #define DKTYPENAMES
                     25: #include <sys/param.h>
                     26: #include <ufs/dinode.h>
                     27: #include <ufs/fs.h>
                     28: #include <sys/stat.h>
                     29: #include <sys/ioctl.h>
                     30: #include <sys/disklabel.h>
                     31: #include <sys/file.h>
                     32: #include <errno.h>
                     33: #include <stdlib.h>
                     34: #include <string.h>
                     35: #include <ctype.h>
                     36: #include "fsck.h"
                     37: 
                     38: struct bufarea asblk;
                     39: #define altsblock (*asblk.b_un.b_fs)
                     40: #define POWEROF2(num)  (((num) & ((num) - 1)) == 0)
                     41: 
                     42: /*
                     43:  * The size of a cylinder group is calculated by CGSIZE. The maximum size
                     44:  * is limited by the fact that cylinder groups are at most one block.
                     45:  * Its size is derived from the size of the maps maintained in the 
                     46:  * cylinder group and the (struct cg) size.
                     47:  */
                     48: #define CGSIZE(fs) \
                     49:     /* base cg */      (sizeof(struct cg) + \
                     50:     /* blktot size */  (fs)->fs_cpg * sizeof(long) + \
                     51:     /* blks size */    (fs)->fs_cpg * (fs)->fs_nrpos * sizeof(short) + \
                     52:     /* inode map */    howmany((fs)->fs_ipg, NBBY) + \
                     53:     /* block map */    howmany((fs)->fs_cpg * (fs)->fs_spc / NSPF(fs), NBBY))
                     54: 
                     55: char   *index();
                     56: struct disklabel *getdisklabel();
                     57: 
                     58: setup(dev)
                     59:        char *dev;
                     60: {
                     61:        long cg, size, asked, i, j;
                     62:        long bmapsize;
                     63:        struct disklabel *lp;
                     64:        struct stat statb;
                     65:        struct fs proto;
                     66: 
                     67:        havesb = 0;
                     68:        if (stat(dev, &statb) < 0) {
                     69:                printf("Can't stat %s: %s\n", dev, strerror(errno));
                     70:                return (0);
                     71:        }
                     72:        if ((statb.st_mode & S_IFMT) != S_IFCHR) {
                     73:                pfatal("%s is not a character device", dev);
                     74:                if (reply("CONTINUE") == 0)
                     75:                        return (0);
                     76:        }
                     77:        if ((fsreadfd = open(dev, O_RDONLY)) < 0) {
                     78:                printf("Can't open %s: %s\n", dev, strerror(errno));
                     79:                return (0);
                     80:        }
                     81:        if (preen == 0)
                     82:                printf("** %s", dev);
                     83:        if (nflag || (fswritefd = open(dev, O_WRONLY)) < 0) {
                     84:                fswritefd = -1;
                     85:                if (preen)
                     86:                        pfatal("NO WRITE ACCESS");
                     87:                printf(" (NO WRITE)");
                     88:        }
                     89:        if (preen == 0)
                     90:                printf("\n");
                     91:        fsmodified = 0;
                     92:        lfdir = 0;
                     93:        initbarea(&sblk);
                     94:        initbarea(&asblk);
                     95:        sblk.b_un.b_buf = malloc(SBSIZE);
                     96:        asblk.b_un.b_buf = malloc(SBSIZE);
                     97:        if (sblk.b_un.b_buf == NULL || asblk.b_un.b_buf == NULL)
                     98:                errexit("cannot allocate space for superblock\n");
                     99:        if (lp = getdisklabel((char *)NULL, fsreadfd))
                    100:                dev_bsize = secsize = lp->d_secsize;
                    101:        else
                    102:                dev_bsize = secsize = DEV_BSIZE;
                    103:        /*
                    104:         * Read in the superblock, looking for alternates if necessary
                    105:         */
                    106:        if (readsb(1) == 0) {
                    107:                if (bflag || preen || calcsb(dev, fsreadfd, &proto) == 0)
                    108:                        return(0);
                    109:                if (reply("LOOK FOR ALTERNATE SUPERBLOCKS") == 0)
                    110:                        return (0);
                    111:                for (cg = 0; cg < proto.fs_ncg; cg++) {
                    112:                        bflag = fsbtodb(&proto, cgsblock(&proto, cg));
                    113:                        if (readsb(0) != 0)
                    114:                                break;
                    115:                }
                    116:                if (cg >= proto.fs_ncg) {
                    117:                        printf("%s %s\n%s %s\n%s %s\n",
                    118:                                "SEARCH FOR ALTERNATE SUPER-BLOCK",
                    119:                                "FAILED. YOU MUST USE THE",
                    120:                                "-b OPTION TO FSCK TO SPECIFY THE",
                    121:                                "LOCATION OF AN ALTERNATE",
                    122:                                "SUPER-BLOCK TO SUPPLY NEEDED",
                    123:                                "INFORMATION; SEE fsck(8).");
                    124:                        return(0);
                    125:                }
                    126:                pwarn("USING ALTERNATE SUPERBLOCK AT %d\n", bflag);
                    127:        }
                    128:        maxfsblock = sblock.fs_size;
                    129:        maxino = sblock.fs_ncg * sblock.fs_ipg;
                    130:        /*
                    131:         * Check and potentially fix certain fields in the super block.
                    132:         */
                    133:        if (sblock.fs_optim != FS_OPTTIME && sblock.fs_optim != FS_OPTSPACE) {
                    134:                pfatal("UNDEFINED OPTIMIZATION IN SUPERBLOCK");
                    135:                if (reply("SET TO DEFAULT") == 1) {
                    136:                        sblock.fs_optim = FS_OPTTIME;
                    137:                        sbdirty();
                    138:                }
                    139:        }
                    140:        if ((sblock.fs_minfree < 0 || sblock.fs_minfree > 99)) {
                    141:                pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
                    142:                        sblock.fs_minfree);
                    143:                if (reply("SET TO DEFAULT") == 1) {
                    144:                        sblock.fs_minfree = 10;
                    145:                        sbdirty();
                    146:                }
                    147:        }
                    148:        if (sblock.fs_interleave < 1 || 
                    149:            sblock.fs_interleave > sblock.fs_nsect) {
                    150:                pwarn("IMPOSSIBLE INTERLEAVE=%d IN SUPERBLOCK",
                    151:                        sblock.fs_interleave);
                    152:                sblock.fs_interleave = 1;
                    153:                if (preen)
                    154:                        printf(" (FIXED)\n");
                    155:                if (preen || reply("SET TO DEFAULT") == 1) {
                    156:                        sbdirty();
                    157:                        dirty(&asblk);
                    158:                }
                    159:        }
                    160:        if (sblock.fs_npsect < sblock.fs_nsect || 
                    161:            sblock.fs_npsect > sblock.fs_nsect*2) {
                    162:                pwarn("IMPOSSIBLE NPSECT=%d IN SUPERBLOCK",
                    163:                        sblock.fs_npsect);
                    164:                sblock.fs_npsect = sblock.fs_nsect;
                    165:                if (preen)
                    166:                        printf(" (FIXED)\n");
                    167:                if (preen || reply("SET TO DEFAULT") == 1) {
                    168:                        sbdirty();
                    169:                        dirty(&asblk);
                    170:                }
                    171:        }
                    172:        if (cvtflag) {
                    173:                if (sblock.fs_postblformat == FS_42POSTBLFMT) {
                    174:                        /*
                    175:                         * Requested to convert from old format to new format
                    176:                         */
                    177:                        if (preen)
                    178:                                pwarn("CONVERTING TO NEW FILE SYSTEM FORMAT\n");
                    179:                        else if (!reply("CONVERT TO NEW FILE SYSTEM FORMAT"))
                    180:                                return(0);
                    181:                        sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
                    182:                        sblock.fs_nrpos = 8;
                    183:                        sblock.fs_postbloff =
                    184:                            (char *)(&sblock.fs_opostbl[0][0]) -
                    185:                            (char *)(&sblock.fs_link);
                    186:                        sblock.fs_rotbloff = &sblock.fs_space[0] -
                    187:                            (u_char *)(&sblock.fs_link);
                    188:                        sblock.fs_cgsize =
                    189:                                fragroundup(&sblock, CGSIZE(&sblock));
                    190:                        /*
                    191:                         * Planning now for future expansion.
                    192:                         */
                    193: #                      if (BYTE_ORDER == BIG_ENDIAN)
                    194:                                sblock.fs_qbmask.val[0] = 0;
                    195:                                sblock.fs_qbmask.val[1] = ~sblock.fs_bmask;
                    196:                                sblock.fs_qfmask.val[0] = 0;
                    197:                                sblock.fs_qfmask.val[1] = ~sblock.fs_fmask;
                    198: #                      endif /* BIG_ENDIAN */
                    199: #                      if (BYTE_ORDER == LITTLE_ENDIAN)
                    200:                                sblock.fs_qbmask.val[0] = ~sblock.fs_bmask;
                    201:                                sblock.fs_qbmask.val[1] = 0;
                    202:                                sblock.fs_qfmask.val[0] = ~sblock.fs_fmask;
                    203:                                sblock.fs_qfmask.val[1] = 0;
                    204: #                      endif /* LITTLE_ENDIAN */
                    205:                        sbdirty();
                    206:                        dirty(&asblk);
                    207:                } else if (sblock.fs_postblformat == FS_DYNAMICPOSTBLFMT) {
                    208:                        /*
                    209:                         * Requested to convert from new format to old format
                    210:                         */
                    211:                        if (sblock.fs_nrpos != 8 || sblock.fs_ipg > 2048 ||
                    212:                            sblock.fs_cpg > 32 || sblock.fs_cpc > 16) {
                    213:                                printf(
                    214:                                "PARAMETERS OF CURRENT FILE SYSTEM DO NOT\n\t");
                    215:                                errexit(
                    216:                                "ALLOW CONVERSION TO OLD FILE SYSTEM FORMAT\n");
                    217:                        }
                    218:                        if (preen)
                    219:                                pwarn("CONVERTING TO OLD FILE SYSTEM FORMAT\n");
                    220:                        else if (!reply("CONVERT TO OLD FILE SYSTEM FORMAT"))
                    221:                                return(0);
                    222:                        sblock.fs_postblformat = FS_42POSTBLFMT;
                    223:                        sblock.fs_cgsize = fragroundup(&sblock,
                    224:                            sizeof(struct ocg) + howmany(sblock.fs_fpg, NBBY));
                    225:                        sbdirty();
                    226:                        dirty(&asblk);
                    227:                } else {
                    228:                        errexit("UNKNOWN FILE SYSTEM FORMAT\n");
                    229:                }
                    230:        }
                    231:        if (asblk.b_dirty) {
                    232:                bcopy((char *)&sblock, (char *)&altsblock,
                    233:                        (size_t)sblock.fs_sbsize);
                    234:                flush(fswritefd, &asblk);
                    235:        }
                    236:        /*
                    237:         * read in the summary info.
                    238:         */
                    239:        asked = 0;
                    240:        for (i = 0, j = 0; i < sblock.fs_cssize; i += sblock.fs_bsize, j++) {
                    241:                size = sblock.fs_cssize - i < sblock.fs_bsize ?
                    242:                    sblock.fs_cssize - i : sblock.fs_bsize;
                    243:                sblock.fs_csp[j] = (struct csum *)calloc(1, (unsigned)size);
                    244:                if (bread(fsreadfd, (char *)sblock.fs_csp[j],
                    245:                    fsbtodb(&sblock, sblock.fs_csaddr + j * sblock.fs_frag),
                    246:                    size) != 0 && !asked) {
                    247:                        pfatal("BAD SUMMARY INFORMATION");
                    248:                        if (reply("CONTINUE") == 0)
                    249:                                errexit("");
                    250:                        asked++;
                    251:                }
                    252:        }
                    253:        /*
                    254:         * allocate and initialize the necessary maps
                    255:         */
                    256:        bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(short));
                    257:        blockmap = calloc((unsigned)bmapsize, sizeof (char));
                    258:        if (blockmap == NULL) {
                    259:                printf("cannot alloc %u bytes for blockmap\n",
                    260:                    (unsigned)bmapsize);
                    261:                goto badsb;
                    262:        }
                    263:        statemap = calloc((unsigned)(maxino + 1), sizeof(char));
                    264:        if (statemap == NULL) {
                    265:                printf("cannot alloc %u bytes for statemap\n",
                    266:                    (unsigned)(maxino + 1));
                    267:                goto badsb;
                    268:        }
                    269:        lncntp = (short *)calloc((unsigned)(maxino + 1), sizeof(short));
                    270:        if (lncntp == NULL) {
                    271:                printf("cannot alloc %u bytes for lncntp\n", 
                    272:                    (unsigned)(maxino + 1) * sizeof(short));
                    273:                goto badsb;
                    274:        }
                    275:        numdirs = sblock.fs_cstotal.cs_ndir;
                    276:        inplast = 0;
                    277:        listmax = numdirs + 10;
                    278:        inpsort = (struct inoinfo **)calloc((unsigned)listmax,
                    279:            sizeof(struct inoinfo *));
                    280:        inphead = (struct inoinfo **)calloc((unsigned)numdirs,
                    281:            sizeof(struct inoinfo *));
                    282:        if (inpsort == NULL || inphead == NULL) {
                    283:                printf("cannot alloc %u bytes for inphead\n", 
                    284:                    (unsigned)numdirs * sizeof(struct inoinfo *));
                    285:                goto badsb;
                    286:        }
                    287:        bufinit();
                    288:        return (1);
                    289: 
                    290: badsb:
                    291:        ckfini();
                    292:        return (0);
                    293: }
                    294: 
                    295: /*
                    296:  * Read in the super block and its summary info.
                    297:  */
                    298: readsb(listerr)
                    299:        int listerr;
                    300: {
                    301:        daddr_t super = bflag ? bflag : SBOFF / dev_bsize;
                    302: 
                    303:        if (bread(fsreadfd, (char *)&sblock, super, (long)SBSIZE) != 0)
                    304:                return (0);
                    305:        sblk.b_bno = super;
                    306:        sblk.b_size = SBSIZE;
                    307:        /*
                    308:         * run a few consistency checks of the super block
                    309:         */
                    310:        if (sblock.fs_magic != FS_MAGIC)
                    311:                { badsb(listerr, "MAGIC NUMBER WRONG"); return (0); }
                    312:        if (sblock.fs_ncg < 1)
                    313:                { badsb(listerr, "NCG OUT OF RANGE"); return (0); }
                    314:        if (sblock.fs_cpg < 1)
                    315:                { badsb(listerr, "CPG OUT OF RANGE"); return (0); }
                    316:        if (sblock.fs_ncg * sblock.fs_cpg < sblock.fs_ncyl ||
                    317:            (sblock.fs_ncg - 1) * sblock.fs_cpg >= sblock.fs_ncyl)
                    318:                { badsb(listerr, "NCYL LESS THAN NCG*CPG"); return (0); }
                    319:        if (sblock.fs_sbsize > SBSIZE)
                    320:                { badsb(listerr, "SIZE PREPOSTEROUSLY LARGE"); return (0); }
                    321:        /*
                    322:         * Compute block size that the filesystem is based on,
                    323:         * according to fsbtodb, and adjust superblock block number
                    324:         * so we can tell if this is an alternate later.
                    325:         */
                    326:        super *= dev_bsize;
                    327:        dev_bsize = sblock.fs_fsize / fsbtodb(&sblock, 1);
                    328:        sblk.b_bno = super / dev_bsize;
                    329:        /*
                    330:         * Set all possible fields that could differ, then do check
                    331:         * of whole super block against an alternate super block.
                    332:         * When an alternate super-block is specified this check is skipped.
                    333:         */
                    334:        getblk(&asblk, cgsblock(&sblock, sblock.fs_ncg - 1), sblock.fs_sbsize);
                    335:        if (asblk.b_errs)
                    336:                return (0);
                    337:        if (bflag) {
                    338:                havesb = 1;
                    339:                return (1);
                    340:        }
                    341:        altsblock.fs_link = sblock.fs_link;
                    342:        altsblock.fs_rlink = sblock.fs_rlink;
                    343:        altsblock.fs_time = sblock.fs_time;
                    344:        altsblock.fs_cstotal = sblock.fs_cstotal;
                    345:        altsblock.fs_cgrotor = sblock.fs_cgrotor;
                    346:        altsblock.fs_fmod = sblock.fs_fmod;
                    347:        altsblock.fs_clean = sblock.fs_clean;
                    348:        altsblock.fs_ronly = sblock.fs_ronly;
                    349:        altsblock.fs_flags = sblock.fs_flags;
                    350:        altsblock.fs_maxcontig = sblock.fs_maxcontig;
                    351:        altsblock.fs_minfree = sblock.fs_minfree;
                    352:        altsblock.fs_optim = sblock.fs_optim;
                    353:        altsblock.fs_rotdelay = sblock.fs_rotdelay;
                    354:        altsblock.fs_maxbpg = sblock.fs_maxbpg;
                    355:        bcopy((char *)sblock.fs_csp, (char *)altsblock.fs_csp,
                    356:                sizeof sblock.fs_csp);
                    357:        bcopy((char *)sblock.fs_fsmnt, (char *)altsblock.fs_fsmnt,
                    358:                sizeof sblock.fs_fsmnt);
                    359:        bcopy((char *)sblock.fs_sparecon, (char *)altsblock.fs_sparecon,
                    360:                sizeof sblock.fs_sparecon);
                    361:        /*
                    362:         * The following should not have to be copied.
                    363:         */
                    364:        altsblock.fs_fsbtodb = sblock.fs_fsbtodb;
                    365:        altsblock.fs_interleave = sblock.fs_interleave;
                    366:        altsblock.fs_npsect = sblock.fs_npsect;
                    367:        altsblock.fs_nrpos = sblock.fs_nrpos;
                    368:        if (bcmp((char *)&sblock, (char *)&altsblock, (int)sblock.fs_sbsize)) {
                    369:                badsb(listerr,
                    370:                "VALUES IN SUPER BLOCK DISAGREE WITH THOSE IN FIRST ALTERNATE");
                    371:                return (0);
                    372:        }
                    373:        havesb = 1;
                    374:        return (1);
                    375: }
                    376: 
                    377: badsb(listerr, s)
                    378:        int listerr;
                    379:        char *s;
                    380: {
                    381: 
                    382:        if (!listerr)
                    383:                return;
                    384:        if (preen)
                    385:                printf("%s: ", devname);
                    386:        pfatal("BAD SUPER BLOCK: %s\n", s);
                    387: }
                    388: 
                    389: /*
                    390:  * Calculate a prototype superblock based on information in the disk label.
                    391:  * When done the cgsblock macro can be calculated and the fs_ncg field
                    392:  * can be used. Do NOT attempt to use other macros without verifying that
                    393:  * their needed information is available!
                    394:  */
                    395: calcsb(dev, devfd, fs)
                    396:        char *dev;
                    397:        int devfd;
                    398:        register struct fs *fs;
                    399: {
                    400:        register struct disklabel *lp;
                    401:        register struct partition *pp;
                    402:        register char *cp;
                    403:        int i;
                    404: 
                    405:        cp = index(dev, '\0') - 1;
                    406:        if (cp == (char *)-1 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp)) {
                    407:                pfatal("%s: CANNOT FIGURE OUT FILE SYSTEM PARTITION\n", dev);
                    408:                return (0);
                    409:        }
                    410:        lp = getdisklabel(dev, devfd);
                    411:        if (isdigit(*cp))
                    412:                pp = &lp->d_partitions[0];
                    413:        else
                    414:                pp = &lp->d_partitions[*cp - 'a'];
                    415:        if (pp->p_fstype != FS_BSDFFS) {
                    416:                pfatal("%s: NOT LABELED AS A BSD FILE SYSTEM (%s)\n",
                    417:                        dev, pp->p_fstype < FSMAXTYPES ?
                    418:                        fstypenames[pp->p_fstype] : "unknown");
                    419:                return (0);
                    420:        }
                    421:        bzero((char *)fs, sizeof(struct fs));
                    422:        fs->fs_fsize = pp->p_fsize;
                    423:        fs->fs_frag = pp->p_frag;
                    424:        fs->fs_cpg = pp->p_cpg;
                    425:        fs->fs_size = pp->p_size;
                    426:        fs->fs_ntrak = lp->d_ntracks;
                    427:        fs->fs_nsect = lp->d_nsectors;
                    428:        fs->fs_spc = lp->d_secpercyl;
                    429:        fs->fs_nspf = fs->fs_fsize / lp->d_secsize;
                    430:        fs->fs_sblkno = roundup(
                    431:                howmany(lp->d_bbsize + lp->d_sbsize, fs->fs_fsize),
                    432:                fs->fs_frag);
                    433:        fs->fs_cgmask = 0xffffffff;
                    434:        for (i = fs->fs_ntrak; i > 1; i >>= 1)
                    435:                fs->fs_cgmask <<= 1;
                    436:        if (!POWEROF2(fs->fs_ntrak))
                    437:                fs->fs_cgmask <<= 1;
                    438:        fs->fs_cgoffset = roundup(
                    439:                howmany(fs->fs_nsect, NSPF(fs)), fs->fs_frag);
                    440:        fs->fs_fpg = (fs->fs_cpg * fs->fs_spc) / NSPF(fs);
                    441:        fs->fs_ncg = howmany(fs->fs_size / fs->fs_spc, fs->fs_cpg);
                    442:        for (fs->fs_fsbtodb = 0, i = NSPF(fs); i > 1; i >>= 1)
                    443:                fs->fs_fsbtodb++;
                    444:        dev_bsize = lp->d_secsize;
                    445:        return (1);
                    446: }
                    447: 
                    448: struct disklabel *
                    449: getdisklabel(s, fd)
                    450:        char *s;
                    451:        int     fd;
                    452: {
                    453:        static struct disklabel lab;
                    454: 
                    455:        if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
                    456:                if (s == NULL)
                    457:                        return ((struct disklabel *)NULL);
                    458:                pwarn("ioctl (GCINFO): %s\n", strerror(errno));
                    459:                errexit("%s: can't read disk label\n", s);
                    460:        }
                    461:        return (&lab);
                    462: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.