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

Annotation of src/sbin/newfs/newfs.c, Revision 1.47

1.47    ! lukem       1: /*     $NetBSD: newfs.c,v 1.46 2001/08/30 14:37:26 lukem Exp $ */
1.18      cgd         2:
1.1       cgd         3: /*
1.10      mycroft     4:  * Copyright (c) 1983, 1989, 1993, 1994
                      5:  *     The Regents of the University of California.  All rights reserved.
1.1       cgd         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.
                     15:  * 3. All advertising materials mentioning features or use of this software
                     16:  *    must display the following acknowledgement:
                     17:  *     This product includes software developed by the University of
                     18:  *     California, Berkeley and its contributors.
                     19:  * 4. Neither the name of the University nor the names of its contributors
                     20:  *    may be used to endorse or promote products derived from this software
                     21:  *    without specific prior written permission.
                     22:  *
                     23:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     24:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     25:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     26:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     27:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     28:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     29:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     30:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     31:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     32:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     33:  * SUCH DAMAGE.
                     34:  */
                     35:
1.25      christos   36: #include <sys/cdefs.h>
1.1       cgd        37: #ifndef lint
1.25      christos   38: __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
                     39:        The Regents of the University of California.  All rights reserved.\n");
1.1       cgd        40: #endif /* not lint */
                     41:
                     42: #ifndef lint
1.18      cgd        43: #if 0
1.27      lukem      44: static char sccsid[] = "@(#)newfs.c    8.13 (Berkeley) 5/1/95";
1.18      cgd        45: #else
1.47    ! lukem      46: __RCSID("$NetBSD: newfs.c,v 1.46 2001/08/30 14:37:26 lukem Exp $");
1.18      cgd        47: #endif
1.1       cgd        48: #endif /* not lint */
                     49:
                     50: /*
                     51:  * newfs: friendly front end to mkfs
                     52:  */
                     53: #include <sys/param.h>
                     54: #include <sys/stat.h>
                     55: #include <sys/ioctl.h>
                     56: #include <sys/disklabel.h>
                     57: #include <sys/file.h>
                     58: #include <sys/mount.h>
1.19      thorpej    59: #include <sys/sysctl.h>
1.30      drochner   60: #include <sys/wait.h>
1.1       cgd        61:
1.10      mycroft    62: #include <ufs/ufs/dir.h>
1.27      lukem      63: #include <ufs/ufs/dinode.h>
1.32      fvdl       64: #include <ufs/ufs/ufsmount.h>
1.10      mycroft    65: #include <ufs/ffs/fs.h>
                     66:
                     67: #include <ctype.h>
1.37      tron       68: #include <disktab.h>
1.1       cgd        69: #include <errno.h>
1.10      mycroft    70: #include <paths.h>
1.1       cgd        71: #include <stdio.h>
1.10      mycroft    72: #include <stdlib.h>
1.1       cgd        73: #include <string.h>
1.10      mycroft    74: #include <syslog.h>
                     75: #include <unistd.h>
1.30      drochner   76: #include <signal.h>
1.25      christos   77: #include <err.h>
1.20      thorpej    78: #include <util.h>
1.10      mycroft    79:
                     80: #include "mntopts.h"
1.25      christos   81: #include "dkcksum.h"
                     82: #include "extern.h"
1.10      mycroft    83:
                     84: struct mntopt mopts[] = {
                     85:        MOPT_STDOPTS,
                     86:        MOPT_ASYNC,
1.22      cgd        87:        MOPT_UPDATE,
1.23      tls        88:        MOPT_NOATIME,
1.10      mycroft    89:        { NULL },
                     90: };
                     91:
1.40      simonb     92: static struct disklabel *getdisklabel(char *, int);
                     93: static void rewritelabel(char *, int, struct disklabel *);
1.43      lukem      94: static int strsuftoi(const char *, const char *, int, int);
1.40      simonb     95: static void usage(void);
                     96: int main(int, char *[]);
1.1       cgd        97:
                     98: #define        COMPAT                  /* allow non-labeled disks */
                     99:
                    100: /*
                    101:  * The following two constants set the default block and fragment sizes.
                    102:  * Both constants must be a power of 2 and meet the following constraints:
                    103:  *     MINBSIZE <= DESBLKSIZE <= MAXBSIZE
                    104:  *     sectorsize <= DESFRAGSIZE <= DESBLKSIZE
                    105:  *     DESBLKSIZE / DESFRAGSIZE <= 8
                    106:  */
                    107: #define        DFL_FRAGSIZE    1024
                    108: #define        DFL_BLKSIZE     8192
                    109:
                    110: /*
1.43      lukem     111:  * Default sector size.
                    112:  */
                    113: #define DFL_SECSIZE    512
                    114:
                    115: /*
1.1       cgd       116:  * Cylinder groups may have up to many cylinders. The actual
                    117:  * number used depends upon how much information can be stored
                    118:  * on a single cylinder. The default is to use 16 cylinders
                    119:  * per group.
                    120:  */
                    121: #define        DESCPG          16      /* desired fs_cpg */
                    122:
                    123: /*
                    124:  * ROTDELAY gives the minimum number of milliseconds to initiate
                    125:  * another disk transfer on the same cylinder. It is used in
                    126:  * determining the rotationally optimal layout for disk blocks
1.13      mycroft   127:  * within a file; the default of fs_rotdelay is 0ms.
1.1       cgd       128:  */
1.13      mycroft   129: #define ROTDELAY       0
1.1       cgd       130:
                    131: /*
                    132:  * MAXBLKPG determines the maximum number of data blocks which are
                    133:  * placed in a single cylinder group. The default is one indirect
                    134:  * block worth of data blocks.
                    135:  */
                    136: #define MAXBLKPG(bsize)        ((bsize) / sizeof(daddr_t))
                    137:
                    138: /*
                    139:  * Each file system has a number of inodes statically allocated.
                    140:  * We allocate one inode slot per NFPI fragments, expecting this
                    141:  * to be far more than we will ever need.
                    142:  */
                    143: #define        NFPI            4
                    144:
                    145: /*
                    146:  * For each cylinder we keep track of the availability of blocks at different
                    147:  * rotational positions, so that we can lay out the data to be picked
                    148:  * up with minimum rotational latency.  NRPOS is the default number of
                    149:  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
1.13      mycroft   150:  * of our summary information is 2ms for a typical 3600 rpm drive.  Caching
                    151:  * and zoning pretty much defeats rotational optimization, so we now use a
                    152:  * default of 1.
1.1       cgd       153:  */
1.13      mycroft   154: #define        NRPOS           1       /* number distinct rotational positions */
1.1       cgd       155:
                    156:
                    157: int    mfs;                    /* run as the memory based filesystem */
                    158: int    Nflag;                  /* run without writing file system */
1.10      mycroft   159: int    Oflag;                  /* format as an 4.3BSD file system */
1.1       cgd       160: int    fssize;                 /* file system size */
                    161: int    ntracks;                /* # tracks/cylinder */
                    162: int    nsectors;               /* # sectors/track */
                    163: int    nphyssectors;           /* # sectors/track including spares */
                    164: int    secpercyl;              /* sectors per cylinder */
                    165: int    trackspares = -1;       /* spare sectors per track */
                    166: int    cylspares = -1;         /* spare sectors per cylinder */
                    167: int    sectorsize;             /* bytes/sector */
                    168: int    rpm;                    /* revolutions/minute of drive */
                    169: int    interleave;             /* hardware sector interleave */
                    170: int    trackskew = -1;         /* sector 0 skew, per track */
                    171: int    fsize = 0;              /* fragment size */
                    172: int    bsize = 0;              /* block size */
                    173: int    cpg = DESCPG;           /* cylinders/cylinder group */
                    174: int    cpgflg;                 /* cylinders/cylinder group flag was given */
                    175: int    minfree = MINFREE;      /* free space threshold */
                    176: int    opt = DEFAULTOPT;       /* optimization preference (space or time) */
                    177: int    density;                /* number of bytes per inode */
1.36      mycroft   178: int    maxcontig = 0;          /* max contiguous blocks to allocate */
1.1       cgd       179: int    rotdelay = ROTDELAY;    /* rotational delay between blocks */
                    180: int    maxbpg;                 /* maximum blocks per file in a cyl group */
                    181: int    nrpos = NRPOS;          /* # of distinguished rotational positions */
1.47    ! lukem     182: int    avgfilesize = AVFILESIZ;/* expected average file size */
        !           183: int    avgfpdir = AFPDIR;      /* expected number of files per directory */
1.1       cgd       184: int    bbsize = BBSIZE;        /* boot block size */
                    185: int    sbsize = SBSIZE;        /* superblock size */
1.10      mycroft   186: int    mntflags = MNT_ASYNC;   /* flags to be passed to mount */
1.1       cgd       187: u_long memleft;                /* virtual memory available */
                    188: caddr_t        membase;                /* start address of memory based filesystem */
1.43      lukem     189: int    needswap;               /* Filesystem not in native byte order */
1.1       cgd       190: #ifdef COMPAT
                    191: char   *disktype;
                    192: int    unlabeled;
                    193: #endif
                    194:
                    195: char   device[MAXPATHLEN];
                    196:
1.10      mycroft   197: int
1.40      simonb    198: main(int argc, char *argv[])
1.1       cgd       199: {
1.25      christos  200:        struct partition *pp;
                    201:        struct disklabel *lp;
1.14      cgd       202:        struct disklabel mfsfakelabel;
1.1       cgd       203:        struct partition oldpartition;
                    204:        struct stat st;
1.10      mycroft   205:        struct statfs *mp;
1.43      lukem     206:        int ch, fsi, fso, len, maxpartitions, n, Fflag, Zflag;
                    207:        char *cp, *endp, *s1, *s2, *special;
                    208:        const char *opstring;
                    209:        long long llsize;
1.30      drochner  210: #ifdef MFS
                    211:        char mountfromname[100];
                    212:        pid_t pid, res;
                    213:        struct statfs sf;
                    214:        int status;
                    215: #endif
1.1       cgd       216:
1.43      lukem     217:        cp = NULL;
                    218:        fsi = fso = -1;
                    219:        Fflag = Zflag = 0;
1.42      cgd       220:        if (strstr(getprogname(), "mfs")) {
1.1       cgd       221:                mfs = 1;
                    222:                Nflag++;
                    223:        }
                    224:
1.19      thorpej   225:        maxpartitions = getmaxpartitions();
                    226:        if (maxpartitions > 26)
1.25      christos  227:                errx(1, "insane maxpartitions value %d", maxpartitions);
1.19      thorpej   228:
1.10      mycroft   229:        opstring = mfs ?
1.47    ! lukem     230:            "NT:a:b:c:d:e:f:g:h:i:m:o:s:" :
        !           231:            "B:FNOS:T:Za:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:x:";
1.26      lukem     232:        while ((ch = getopt(argc, argv, opstring)) != -1)
1.10      mycroft   233:                switch (ch) {
1.33      bouyer    234:                case 'B':
                    235:                        if (strcmp(optarg, "be") == 0) {
                    236: #if BYTE_ORDER == LITTLE_ENDIAN
                    237:                                needswap = 1;
                    238: #endif
                    239:                        } else if (strcmp(optarg, "le") == 0) {
                    240: #if BYTE_ORDER == BIG_ENDIAN
                    241:                                needswap = 1;
                    242: #endif
                    243:                        } else
                    244:                                usage();
                    245:                        break;
1.43      lukem     246:                case 'F':
                    247:                        Fflag = 1;
                    248:                        break;
1.10      mycroft   249:                case 'N':
                    250:                        Nflag = 1;
1.1       cgd       251:                        break;
1.10      mycroft   252:                case 'O':
                    253:                        Oflag = 1;
1.1       cgd       254:                        break;
                    255:                case 'S':
1.43      lukem     256:                        sectorsize = strsuftoi("sector size",
                    257:                            optarg, 1, INT_MAX);
1.1       cgd       258:                        break;
                    259: #ifdef COMPAT
                    260:                case 'T':
                    261:                        disktype = optarg;
                    262:                        break;
                    263: #endif
1.43      lukem     264:                case 'Z':
                    265:                        Zflag = 1;
                    266:                        break;
1.1       cgd       267:                case 'a':
1.43      lukem     268:                        maxcontig = strsuftoi("maximum contiguous blocks",
                    269:                            optarg, 1, INT_MAX);
1.1       cgd       270:                        break;
                    271:                case 'b':
1.43      lukem     272:                        bsize = strsuftoi("block size",
                    273:                            optarg, MINBSIZE, INT_MAX);
1.1       cgd       274:                        break;
                    275:                case 'c':
1.43      lukem     276:                        cpg = strsuftoi("cylinders per group",
                    277:                            optarg, 1, INT_MAX);
1.1       cgd       278:                        cpgflg++;
                    279:                        break;
                    280:                case 'd':
1.43      lukem     281:                        rotdelay = strsuftoi("rotational delay",
                    282:                            optarg, 0, INT_MAX);
1.1       cgd       283:                        break;
                    284:                case 'e':
1.43      lukem     285:                        maxbpg = strsuftoi(
                    286:                            "blocks per file in a cylinder group",
                    287:                            optarg, 1, INT_MAX);
1.1       cgd       288:                        break;
                    289:                case 'f':
1.43      lukem     290:                        fsize = strsuftoi("fragment size",
                    291:                            optarg, 1, INT_MAX);
1.1       cgd       292:                        break;
1.47    ! lukem     293:                case 'g':
        !           294:                        avgfilesize = strsuftoi("average file size",
        !           295:                            optarg, 1, INT_MAX);
        !           296:                        break;
        !           297:                case 'h':
        !           298:                        avgfpdir = strsuftoi("expected files per directory",
        !           299:                            optarg, 1, INT_MAX);
        !           300:                        break;
1.1       cgd       301:                case 'i':
1.43      lukem     302:                        density = strsuftoi("bytes per inode",
                    303:                            optarg, 1, INT_MAX);
1.1       cgd       304:                        break;
                    305:                case 'k':
1.43      lukem     306:                        trackskew = strsuftoi("track skew",
                    307:                            optarg, 0, INT_MAX);
1.1       cgd       308:                        break;
                    309:                case 'l':
1.43      lukem     310:                        interleave = strsuftoi("interleave",
                    311:                            optarg, 1, INT_MAX);
1.1       cgd       312:                        break;
                    313:                case 'm':
1.43      lukem     314:                        minfree = strsuftoi("free space %",
                    315:                            optarg, 0, 99);
1.1       cgd       316:                        break;
                    317:                case 'n':
1.43      lukem     318:                        nrpos = strsuftoi("rotational layout count",
                    319:                            optarg, 1, INT_MAX);
1.1       cgd       320:                        break;
                    321:                case 'o':
1.10      mycroft   322:                        if (mfs)
1.27      lukem     323:                                getmntopts(optarg, mopts, &mntflags, 0);
1.10      mycroft   324:                        else {
                    325:                                if (strcmp(optarg, "space") == 0)
                    326:                                        opt = FS_OPTSPACE;
                    327:                                else if (strcmp(optarg, "time") == 0)
                    328:                                        opt = FS_OPTTIME;
                    329:                                else
1.25      christos  330:                                    errx(1, "%s %s",
                    331:                                        "unknown optimization preference: ",
                    332:                                        "use `space' or `time'.");
1.10      mycroft   333:                        }
1.1       cgd       334:                        break;
                    335:                case 'p':
1.43      lukem     336:                        trackspares = strsuftoi("spare sectors per track",
                    337:                            optarg, 0, INT_MAX);
1.1       cgd       338:                        break;
                    339:                case 'r':
1.43      lukem     340:                        rpm = strsuftoi("revolutions per minute",
                    341:                            optarg, 1, INT_MAX);
1.1       cgd       342:                        break;
                    343:                case 's':
1.43      lukem     344:                        llsize = strtoll(optarg, &endp, 10);
                    345:                        if (endp[0] != '\0' && endp[1] != '\0')
                    346:                                llsize = -1;
                    347:                        else {
                    348:                                int     ssiz;
                    349:
                    350:                                ssiz = (sectorsize ? sectorsize : DFL_SECSIZE);
                    351:                                switch (tolower((unsigned char)endp[0])) {
                    352:                                case 'b':
                    353:                                        llsize /= ssiz;
                    354:                                        break;
                    355:                                case 'k':
                    356:                                        llsize *= 1024 / ssiz;
                    357:                                        break;
                    358:                                case 'm':
                    359:                                        llsize *= 1024 * 1024 / ssiz;
                    360:                                        break;
                    361:                                case 'g':
                    362:                                        llsize *= 1024 * 1024 * 1024 / ssiz;
                    363:                                        break;
                    364:                                case '\0':
                    365:                                case 's':
                    366:                                        break;
                    367:                                default:
                    368:                                        llsize = -1;
1.41      simonb    369:                                }
                    370:                        }
1.43      lukem     371:                        if (llsize > INT_MAX)
                    372:                                errx(1, "file system size `%s' is too large.",
                    373:                                    optarg);
                    374:                        if (llsize <= 0)
                    375:                                errx(1,
                    376:                            "`%s' is not a valid number for file system size.",
                    377:                                    optarg);
                    378:                        fssize = (int)llsize;
1.1       cgd       379:                        break;
                    380:                case 't':
1.43      lukem     381:                        ntracks = strsuftoi("total tracks",
                    382:                            optarg, 1, INT_MAX);
1.1       cgd       383:                        break;
                    384:                case 'u':
1.43      lukem     385:                        nsectors = strsuftoi("sectors per track",
                    386:                            optarg, 1, INT_MAX);
1.1       cgd       387:                        break;
                    388:                case 'x':
1.43      lukem     389:                        cylspares = strsuftoi("spare sectors per cylinder",
                    390:                            optarg, 0, INT_MAX);
1.1       cgd       391:                        break;
                    392:                case '?':
                    393:                default:
                    394:                        usage();
                    395:                }
                    396:        argc -= optind;
                    397:        argv += optind;
                    398:
                    399:        if (argc != 2 && (mfs || argc != 1))
                    400:                usage();
                    401:
                    402:        special = argv[0];
1.43      lukem     403:        if ((mfs && !strcmp(special, "swap")) || Fflag) {
1.14      cgd       404:                /*
1.43      lukem     405:                 * it's an MFS mounted on "swap" or a file system image;
                    406:                 * fake up a label.             XXX
1.14      cgd       407:                 */
1.43      lukem     408:                if (!sectorsize)
                    409:                        sectorsize = DFL_SECSIZE;
                    410:
                    411:                if (Fflag && (stat(special, &st) != -1 && !S_ISREG(st.st_mode)))
                    412:                        errx(1, "%s is not a regular file", special);
                    413:                if (Fflag && !Nflag) {  /* creating image in a regular file */
1.44      lukem     414:                        if (fssize == 0)
                    415:                                errx(1, "need to specify size when using -F");
1.43      lukem     416:                        fso = open(special, O_RDWR | O_CREAT | O_TRUNC, 0777);
                    417:                        if (fso == -1)
                    418:                                err(1, "can't open file %s", special);
1.44      lukem     419:                        if ((fsi = dup(fso)) == -1)
                    420:                                err(1, "can't dup(2) image fd");
1.43      lukem     421:                        if (ftruncate(fso, (off_t)fssize * sectorsize) == -1)
                    422:                                err(1, "can't resize %s to %d",
                    423:                                    special, fssize);
                    424:
                    425:                        if (Zflag) {    /* pre-zero the file */
                    426:                                char    *buf;
1.45      lukem     427:                                int     bufsize, i;
                    428:                                off_t   bufrem;
                    429:                                struct statfs sfs;
                    430:
                    431:                                if (fstatfs(fso, &sfs) == -1) {
                    432:                                        warn("can't fstatfs `%s'", special);
                    433:                                        bufsize = 8192;
                    434:                                } else
                    435:                                        bufsize = sfs.f_iosize;
1.43      lukem     436:
1.45      lukem     437:                                if ((buf = calloc(1, bufsize)) == NULL)
1.43      lukem     438:                                        err(1, "can't malloc buffer of %d",
1.45      lukem     439:                                        bufsize);
                    440:                                bufrem = fssize * sectorsize;
1.43      lukem     441:                                printf(
1.45      lukem     442:     "Creating file system image in `%s', size %lld bytes, in %d byte chunks.\n",
                    443:                                    special, (long long)bufrem, bufsize);
                    444:                                while (bufrem > 0) {
                    445:                                        i = write(fso, buf,
                    446:                                            MIN(bufsize, bufrem));
                    447:                                        if (i == -1)
                    448:                                                err(1, "writing image");
                    449:                                        bufrem -= i;
1.43      lukem     450:                                }
                    451:                        }
                    452:
                    453:                }
1.14      cgd       454:
                    455:                memset(&mfsfakelabel, 0, sizeof(mfsfakelabel));
1.43      lukem     456:                mfsfakelabel.d_secsize = sectorsize;
                    457:                mfsfakelabel.d_nsectors = 64;   /* these 3 add up to 16MB */
1.14      cgd       458:                mfsfakelabel.d_ntracks = 16;
                    459:                mfsfakelabel.d_ncylinders = 16;
1.43      lukem     460:                mfsfakelabel.d_secpercyl =
                    461:                    mfsfakelabel.d_nsectors * mfsfakelabel.d_ntracks;
                    462:                mfsfakelabel.d_secperunit =
                    463:                    mfsfakelabel.d_ncylinders * mfsfakelabel.d_secpercyl;
1.14      cgd       464:                mfsfakelabel.d_rpm = 3600;
                    465:                mfsfakelabel.d_interleave = 1;
                    466:                mfsfakelabel.d_npartitions = 1;
1.43      lukem     467:                mfsfakelabel.d_partitions[0].p_size = mfsfakelabel.d_secperunit;
1.14      cgd       468:                mfsfakelabel.d_partitions[0].p_fsize = 1024;
                    469:                mfsfakelabel.d_partitions[0].p_frag = 8;
                    470:                mfsfakelabel.d_partitions[0].p_cpg = 16;
                    471:
                    472:                lp = &mfsfakelabel;
                    473:                pp = &mfsfakelabel.d_partitions[0];
                    474:
                    475:                goto havelabel;
                    476:        }
1.11      mycroft   477:        cp = strrchr(special, '/');
1.43      lukem     478:        if (cp == NULL) {
1.1       cgd       479:                /*
                    480:                 * No path prefix; try /dev/r%s then /dev/%s.
                    481:                 */
1.43      lukem     482:                (void)snprintf(device, sizeof(device), "%sr%s",
                    483:                    _PATH_DEV, special);
1.1       cgd       484:                if (stat(device, &st) == -1)
1.34      mycroft   485:                        (void)snprintf(device, sizeof(device), "%s%s",
                    486:                            _PATH_DEV, special);
1.1       cgd       487:                special = device;
                    488:        }
1.10      mycroft   489:        if (Nflag) {
                    490:                fso = -1;
                    491:        } else {
1.1       cgd       492:                fso = open(special, O_WRONLY);
                    493:                if (fso < 0)
1.28      enami     494:                        err(1, "%s: open", special);
1.10      mycroft   495:
                    496:                /* Bail if target special is mounted */
                    497:                n = getmntinfo(&mp, MNT_NOWAIT);
                    498:                if (n == 0)
1.28      enami     499:                        err(1, "%s: getmntinfo", special);
1.10      mycroft   500:
                    501:                len = sizeof(_PATH_DEV) - 1;
                    502:                s1 = special;
                    503:                if (strncmp(_PATH_DEV, s1, len) == 0)
                    504:                        s1 += len;
                    505:
                    506:                while (--n >= 0) {
                    507:                        s2 = mp->f_mntfromname;
                    508:                        if (strncmp(_PATH_DEV, s2, len) == 0) {
                    509:                                s2 += len - 1;
                    510:                                *s2 = 'r';
                    511:                        }
                    512:                        if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
1.25      christos  513:                                errx(1, "%s is mounted on %s",
1.10      mycroft   514:                                    special, mp->f_mntonname);
                    515:                        ++mp;
                    516:                }
                    517:        }
                    518:        if (mfs && disktype != NULL) {
                    519:                lp = (struct disklabel *)getdiskbyname(disktype);
                    520:                if (lp == NULL)
1.25      christos  521:                        errx(1, "%s: unknown disk type", disktype);
1.10      mycroft   522:                pp = &lp->d_partitions[1];
                    523:        } else {
                    524:                fsi = open(special, O_RDONLY);
                    525:                if (fsi < 0)
1.28      enami     526:                        err(1, "%s: open", special);
1.10      mycroft   527:                if (fstat(fsi, &st) < 0)
1.28      enami     528:                        err(1, "%s: fstat", special);
1.15      mycroft   529:                if (!S_ISCHR(st.st_mode) && !mfs)
1.25      christos  530:                        warnx("%s: not a character-special device", special);
1.11      mycroft   531:                cp = strchr(argv[0], '\0') - 1;
1.25      christos  532:                if (cp == 0 || ((*cp < 'a' || *cp > ('a' + maxpartitions - 1))
                    533:                    && !isdigit(*cp)))
                    534:                        errx(1, "can't figure out file system partition");
1.1       cgd       535: #ifdef COMPAT
1.10      mycroft   536:                if (!mfs && disktype == NULL)
                    537:                        disktype = argv[1];
1.1       cgd       538: #endif
1.10      mycroft   539:                lp = getdisklabel(special, fsi);
                    540:                if (isdigit(*cp))
                    541:                        pp = &lp->d_partitions[0];
                    542:                else
                    543:                        pp = &lp->d_partitions[*cp - 'a'];
                    544:                if (pp->p_size == 0)
1.25      christos  545:                        errx(1, "`%c' partition is unavailable", *cp);
1.10      mycroft   546:                if (pp->p_fstype == FS_BOOT)
1.25      christos  547:                        errx(1, "`%c' partition overlaps boot program", *cp);
1.10      mycroft   548:        }
1.43      lukem     549:
                    550:  havelabel:
1.1       cgd       551:        if (fssize == 0)
                    552:                fssize = pp->p_size;
1.43      lukem     553:        if (fssize > pp->p_size && !mfs && !Fflag)
1.25      christos  554:                errx(1, "maximum file system size on the `%c' partition is %d",
                    555:                    *cp, pp->p_size);
1.1       cgd       556:        if (rpm == 0) {
                    557:                rpm = lp->d_rpm;
                    558:                if (rpm <= 0)
                    559:                        rpm = 3600;
                    560:        }
                    561:        if (ntracks == 0) {
                    562:                ntracks = lp->d_ntracks;
                    563:                if (ntracks <= 0)
1.25      christos  564:                        errx(1, "no default #tracks");
1.1       cgd       565:        }
                    566:        if (nsectors == 0) {
                    567:                nsectors = lp->d_nsectors;
                    568:                if (nsectors <= 0)
1.25      christos  569:                        errx(1, "no default #sectors/track");
1.1       cgd       570:        }
                    571:        if (sectorsize == 0) {
                    572:                sectorsize = lp->d_secsize;
                    573:                if (sectorsize <= 0)
1.25      christos  574:                        errx(1, "no default sector size");
1.1       cgd       575:        }
                    576:        if (trackskew == -1) {
                    577:                trackskew = lp->d_trackskew;
                    578:                if (trackskew < 0)
                    579:                        trackskew = 0;
                    580:        }
                    581:        if (interleave == 0) {
                    582:                interleave = lp->d_interleave;
                    583:                if (interleave <= 0)
                    584:                        interleave = 1;
                    585:        }
                    586:        if (fsize == 0) {
                    587:                fsize = pp->p_fsize;
                    588:                if (fsize <= 0)
                    589:                        fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
                    590:        }
                    591:        if (bsize == 0) {
                    592:                bsize = pp->p_frag * pp->p_fsize;
                    593:                if (bsize <= 0)
                    594:                        bsize = MIN(DFL_BLKSIZE, 8 * fsize);
1.38      wrstuden  595:        }
                    596:        if (cpgflg == 0) {
                    597:                if (pp->p_cpg != 0)
                    598:                        cpg = pp->p_cpg;
1.1       cgd       599:        }
1.10      mycroft   600:        /*
                    601:         * Maxcontig sets the default for the maximum number of blocks
                    602:         * that may be allocated sequentially. With filesystem clustering
                    603:         * it is possible to allocate contiguous blocks up to the maximum
                    604:         * transfer size permitted by the controller or buffering.
                    605:         */
                    606:        if (maxcontig == 0)
1.27      lukem     607:                maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize);
1.1       cgd       608:        if (density == 0)
                    609:                density = NFPI * fsize;
1.8       cgd       610:        if (minfree < MINFREE && opt != FS_OPTSPACE) {
1.25      christos  611:                warnx("%s %s %d%%", "Warning: changing optimization to space",
                    612:                    "because minfree is less than", MINFREE);
1.1       cgd       613:                opt = FS_OPTSPACE;
                    614:        }
                    615:        if (trackspares == -1) {
                    616:                trackspares = lp->d_sparespertrack;
                    617:                if (trackspares < 0)
                    618:                        trackspares = 0;
                    619:        }
                    620:        nphyssectors = nsectors + trackspares;
                    621:        if (cylspares == -1) {
                    622:                cylspares = lp->d_sparespercyl;
                    623:                if (cylspares < 0)
                    624:                        cylspares = 0;
                    625:        }
                    626:        secpercyl = nsectors * ntracks - cylspares;
                    627:        if (secpercyl != lp->d_secpercyl)
1.25      christos  628:                warnx("%s (%d) %s (%u)\n",
1.1       cgd       629:                        "Warning: calculated sectors per cylinder", secpercyl,
                    630:                        "disagrees with disk label", lp->d_secpercyl);
                    631:        if (maxbpg == 0)
                    632:                maxbpg = MAXBLKPG(bsize);
                    633: #ifdef notdef /* label may be 0 if faked up by kernel */
                    634:        bbsize = lp->d_bbsize;
                    635:        sbsize = lp->d_sbsize;
                    636: #endif
                    637:        oldpartition = *pp;
                    638:        mkfs(pp, special, fsi, fso);
1.43      lukem     639:        if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)) && !Fflag)
1.1       cgd       640:                rewritelabel(special, fso, lp);
                    641:        if (!Nflag)
                    642:                close(fso);
                    643:        close(fsi);
                    644: #ifdef MFS
                    645:        if (mfs) {
                    646:                struct mfs_args args;
                    647:
1.30      drochner  648:                switch (pid = fork()) {
                    649:                case -1:
                    650:                        perror("mfs");
                    651:                        exit(10);
                    652:                case 0:
1.34      mycroft   653:                        (void)snprintf(mountfromname, sizeof(mountfromname),
                    654:                            "mfs:%d", getpid());
1.30      drochner  655:                        break;
                    656:                default:
1.34      mycroft   657:                        (void)snprintf(mountfromname, sizeof(mountfromname),
                    658:                            "mfs:%d", pid);
1.30      drochner  659:                        for (;;) {
                    660:                                /*
                    661:                                 * spin until the mount succeeds
                    662:                                 * or the child exits
                    663:                                 */
                    664:                                usleep(1);
                    665:
                    666:                                /*
                    667:                                 * XXX Here is a race condition: another process
                    668:                                 * can mount a filesystem which hides our
                    669:                                 * ramdisk before we see the success.
                    670:                                 */
                    671:                                if (statfs(argv[1], &sf) < 0)
                    672:                                        err(88, "statfs %s", argv[1]);
                    673:                                if (!strcmp(sf.f_mntfromname, mountfromname) &&
                    674:                                    !strncmp(sf.f_mntonname, argv[1],
                    675:                                             MNAMELEN) &&
                    676:                                    !strcmp(sf.f_fstypename, "mfs"))
                    677:                                        exit(0);
                    678:
                    679:                                res = waitpid(pid, &status, WNOHANG);
                    680:                                if (res == -1)
                    681:                                        err(11, "waitpid");
                    682:                                if (res != pid)
                    683:                                        continue;
1.31      drochner  684:                                if (WIFEXITED(status)) {
                    685:                                        if (WEXITSTATUS(status) == 0)
                    686:                                                exit(0);
1.30      drochner  687:                                        errx(1, "%s: mount: %s", argv[1],
                    688:                                             strerror(WEXITSTATUS(status)));
1.31      drochner  689:                                } else
1.30      drochner  690:                                        errx(11, "abnormal termination");
                    691:                        }
                    692:                        /* NOTREACHED */
                    693:                }
                    694:
                    695:                (void) setsid();
                    696:                (void) close(0);
                    697:                (void) close(1);
                    698:                (void) close(2);
                    699:                (void) chdir("/");
                    700:
                    701:                args.fspec = mountfromname;
1.10      mycroft   702:                args.export.ex_root = -2;
                    703:                if (mntflags & MNT_RDONLY)
                    704:                        args.export.ex_flags = MNT_EXRDONLY;
                    705:                else
                    706:                        args.export.ex_flags = 0;
1.1       cgd       707:                args.base = membase;
                    708:                args.size = fssize * sectorsize;
                    709:                if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0)
1.30      drochner  710:                        exit(errno); /* parent prints message */
1.1       cgd       711:        }
                    712: #endif
                    713:        exit(0);
                    714: }
                    715:
                    716: #ifdef COMPAT
1.39      is        717: const char lmsg[] = "%s: can't read disk label; disk type must be specified";
1.1       cgd       718: #else
1.39      is        719: const char lmsg[] = "%s: can't read disk label";
1.1       cgd       720: #endif
                    721:
1.25      christos  722: static struct disklabel *
1.40      simonb    723: getdisklabel(char *s, volatile int fd)
                    724: /* XXX why is fs volatile?! */
1.1       cgd       725: {
                    726:        static struct disklabel lab;
                    727:
1.24      tls       728:        if (ioctl(fd, DIOCGDINFO, &lab) < 0) {
1.1       cgd       729: #ifdef COMPAT
                    730:                if (disktype) {
1.25      christos  731:                        struct disklabel *lp;
1.1       cgd       732:
                    733:                        unlabeled++;
                    734:                        lp = getdiskbyname(disktype);
                    735:                        if (lp == NULL)
1.25      christos  736:                                errx(1, "%s: unknown disk type", disktype);
1.1       cgd       737:                        return (lp);
                    738:                }
                    739: #endif
1.10      mycroft   740:                warn("ioctl (GDINFO)");
1.25      christos  741:                errx(1, lmsg, s);
1.1       cgd       742:        }
                    743:        return (&lab);
                    744: }
                    745:
1.25      christos  746: static void
1.40      simonb    747: rewritelabel(char *s, volatile int fd, struct disklabel *lp)
                    748: /* XXX why is fd volatile?! */
1.1       cgd       749: {
                    750: #ifdef COMPAT
                    751:        if (unlabeled)
                    752:                return;
                    753: #endif
                    754:        lp->d_checksum = 0;
                    755:        lp->d_checksum = dkcksum(lp);
                    756:        if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
1.10      mycroft   757:                warn("ioctl (WDINFO)");
1.25      christos  758:                errx(1, "%s: can't rewrite disk label", s);
1.1       cgd       759:        }
1.35      matt      760: #if __vax__
1.1       cgd       761:        if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
1.25      christos  762:                int i;
1.1       cgd       763:                int cfd;
                    764:                daddr_t alt;
                    765:                char specname[64];
                    766:                char blk[1024];
                    767:                char *cp;
                    768:
                    769:                /*
                    770:                 * Make name for 'c' partition.
                    771:                 */
                    772:                strcpy(specname, s);
                    773:                cp = specname + strlen(specname) - 1;
                    774:                if (!isdigit(*cp))
                    775:                        *cp = 'c';
                    776:                cfd = open(specname, O_WRONLY);
                    777:                if (cfd < 0)
1.28      enami     778:                        err(1, "%s: open", specname);
1.11      mycroft   779:                memset(blk, 0, sizeof(blk));
1.1       cgd       780:                *(struct disklabel *)(blk + LABELOFFSET) = *lp;
                    781:                alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
                    782:                for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
1.17      cgd       783:                        off_t offset;
                    784:
                    785:                        offset = alt + i;
                    786:                        offset *= lp->d_secsize;
                    787:                        if (lseek(cfd, offset, SEEK_SET) == -1)
1.25      christos  788:                                err(1, "lseek to badsector area: ");
1.1       cgd       789:                        if (write(cfd, blk, lp->d_secsize) < lp->d_secsize)
1.10      mycroft   790:                                warn("alternate label %d write", i/2);
1.1       cgd       791:                }
                    792:                close(cfd);
                    793:        }
                    794: #endif
                    795: }
                    796:
1.43      lukem     797: static int
                    798: strsuftoi(const char *desc, const char *arg, int min, int max)
                    799: {
                    800:        long long result;
                    801:        char    *ep;
                    802:
                    803:        errno = 0;
                    804:        result = strtoll(arg, &ep, 10);
                    805:        if (ep[0] != '\0' && ep[1] != '\0')
                    806:                errx(1, "%s `%s' is not a valid number.", desc, arg);
                    807:        switch (tolower((unsigned char)ep[0])) {
                    808:        case '\0':
                    809:        case 'b':
                    810:                break;
                    811:        case 'k':
                    812:                result <<= 10;
                    813:                break;
                    814:        case 'm':
                    815:                result <<= 20;
                    816:                break;
                    817:        case 'g':
                    818:                result <<= 30;
                    819:                break;
                    820:        default:
                    821:                errx(1, "`%s' is not a valid suffix for %s.", ep, desc);
                    822:        }
                    823:        if (result < min)
                    824:                errx(1, "%s `%s' (%lld) is less than minimum (%d).",
                    825:                    desc, arg, result, min);
                    826:        if (result > max)
                    827:                errx(1, "%s `%s' (%lld) is greater than maximum (%d).",
                    828:                    desc, arg, result, max);
                    829:        return ((int)result);
                    830: }
                    831:
1.25      christos  832: static void
1.40      simonb    833: usage(void)
1.1       cgd       834: {
1.43      lukem     835:
1.1       cgd       836:        if (mfs) {
                    837:                fprintf(stderr,
1.43      lukem     838:                    "usage: %s [ fsoptions ] special-device mount-point\n",
1.42      cgd       839:                        getprogname());
1.1       cgd       840:        } else
                    841:                fprintf(stderr,
1.43      lukem     842:                    "usage: %s [ fsoptions ] special-device%s\n",
1.42      cgd       843:                    getprogname(),
1.1       cgd       844: #ifdef COMPAT
                    845:                    " [device-type]");
                    846: #else
                    847:                    "");
                    848: #endif
                    849:        fprintf(stderr, "where fsoptions are:\n");
1.43      lukem     850:        if (!mfs) {
                    851:                fprintf(stderr,
                    852:                        "\t-B byteorder\tbyte order (`be' or `le')\n");
                    853:                fprintf(stderr,
                    854:                        "\t-F\t\tcreate file system image in regular file\n");
                    855:        }
                    856:        fprintf(stderr, "\t-N\t\tdo not create file system, "
                    857:                        "just print out parameters\n");
                    858:        if (!mfs) {
                    859:                fprintf(stderr,
                    860:                        "\t-O\t\tcreate a 4.3BSD format filesystem\n");
                    861:                fprintf(stderr,
                    862:                        "\t-S secsize\tsector size\n");
                    863:        }
1.1       cgd       864: #ifdef COMPAT
1.43      lukem     865:        fprintf(stderr, "\t-T disktype\tdisk type\n");
1.1       cgd       866: #endif
1.43      lukem     867:        if (!mfs)
                    868:                fprintf(stderr,
                    869:                        "\t-Z\t\tpre-zero the image file (with -F)\n");
                    870:        fprintf(stderr, "\t-a maxcontig\tmaximum contiguous blocks\n");
                    871:        fprintf(stderr, "\t-b bsize\tblock size\n");
                    872:        fprintf(stderr, "\t-c cpg\t\tcylinders/group\n");
                    873:        fprintf(stderr, "\t-d rotdelay\trotational delay between "
                    874:                        "contiguous blocks\n");
                    875:        fprintf(stderr, "\t-e maxbpg\tmaximum blocks per file "
                    876:                        "in a cylinder group\n");
                    877:        fprintf(stderr, "\t-f fsize\tfragment size\n");
1.47    ! lukem     878:        fprintf(stderr, "\t-g average file size\n");
        !           879:        fprintf(stderr, "\t-h average files per directory\n");
1.43      lukem     880:        fprintf(stderr, "\t-i density\tnumber of bytes per inode\n");
                    881:        if (!mfs) {
                    882:                fprintf(stderr,
                    883:                        "\t-k trackskew\tsector 0 skew, per track\n");
                    884:                fprintf(stderr,
                    885:                        "\t-l interleave\thardware sector interleave\n");
                    886:        }
                    887:        fprintf(stderr, "\t-m minfree\tminimum free space %%\n");
                    888:        if (!mfs)
                    889:                fprintf(stderr,
                    890:                        "\t-n nrpos\tnumber of distinguished "
                    891:                        "rotational positions\n");
                    892:        fprintf(stderr, "\t-o optim\toptimization preference "
                    893:                        "(`space' or `time')\n");
                    894:        if (!mfs)
                    895:                fprintf(stderr,
                    896:                        "\t-p trackspares\tspare sectors per track\n");
                    897:        fprintf(stderr, "\t-s fssize\tfile system size (sectors)\n");
                    898:        if (!mfs) {
                    899:                fprintf(stderr,
                    900:                        "\t-r rpm\t\trevolutions/minute\n");
                    901:                fprintf(stderr,
                    902:                        "\t-t ntracks\ttracks/cylinder\n");
                    903:                fprintf(stderr,
                    904:                        "\t-u nsectors\tsectors/track\n");
                    905:                fprintf(stderr,
                    906:                        "\t-x cylspares\tspare sectors per cylinder\n");
                    907:        }
1.1       cgd       908:        exit(1);
                    909: }

CVSweb <webmaster@jp.NetBSD.org>