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

1.95    ! christos    1: /*     $NetBSD: newfs.c,v 1.94 2006/08/27 18:49:08 christos Exp $      */
1.67      agc         2:
                      3: /*
                      4:  * Copyright (c) 1983, 1989, 1993, 1994
                      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.
                     15:  * 3. Neither the name of the University nor the names of its contributors
                     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:  */
1.18      cgd        31:
1.1       cgd        32: /*
1.64      fvdl       33:  * Copyright (c) 2002 Networks Associates Technology, Inc.
                     34:  * All rights reserved.
                     35:  *
                     36:  * This software was developed for the FreeBSD Project by Marshall
                     37:  * Kirk McKusick and Network Associates Laboratories, the Security
                     38:  * Research Division of Network Associates, Inc. under DARPA/SPAWAR
                     39:  * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
                     40:  * research program
                     41:  *
1.1       cgd        42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
                     50:  * 3. All advertising materials mentioning features or use of this software
                     51:  *    must display the following acknowledgement:
                     52:  *     This product includes software developed by the University of
                     53:  *     California, Berkeley and its contributors.
                     54:  * 4. Neither the name of the University nor the names of its contributors
                     55:  *    may be used to endorse or promote products derived from this software
                     56:  *    without specific prior written permission.
                     57:  *
                     58:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     59:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     60:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     61:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     62:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     63:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     64:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     65:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     66:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     67:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     68:  * SUCH DAMAGE.
                     69:  */
                     70:
1.25      christos   71: #include <sys/cdefs.h>
1.1       cgd        72: #ifndef lint
1.25      christos   73: __COPYRIGHT("@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
                     74:        The Regents of the University of California.  All rights reserved.\n");
1.1       cgd        75: #endif /* not lint */
                     76:
                     77: #ifndef lint
1.18      cgd        78: #if 0
1.27      lukem      79: static char sccsid[] = "@(#)newfs.c    8.13 (Berkeley) 5/1/95";
1.18      cgd        80: #else
1.95    ! christos   81: __RCSID("$NetBSD: newfs.c,v 1.94 2006/08/27 18:49:08 christos Exp $");
1.18      cgd        82: #endif
1.1       cgd        83: #endif /* not lint */
                     84:
                     85: /*
                     86:  * newfs: friendly front end to mkfs
                     87:  */
                     88: #include <sys/param.h>
                     89: #include <sys/ioctl.h>
                     90: #include <sys/disklabel.h>
1.92      christos   91: #include <sys/disk.h>
1.1       cgd        92: #include <sys/file.h>
                     93: #include <sys/mount.h>
1.19      thorpej    94: #include <sys/sysctl.h>
1.30      drochner   95: #include <sys/wait.h>
1.1       cgd        96:
1.10      mycroft    97: #include <ufs/ufs/dir.h>
1.27      lukem      98: #include <ufs/ufs/dinode.h>
1.32      fvdl       99: #include <ufs/ufs/ufsmount.h>
1.10      mycroft   100: #include <ufs/ffs/fs.h>
                    101:
                    102: #include <ctype.h>
1.37      tron      103: #include <disktab.h>
1.54      simonb    104: #include <err.h>
1.1       cgd       105: #include <errno.h>
1.54      simonb    106: #include <grp.h>
1.76      wiz       107: #include <limits.h>
1.10      mycroft   108: #include <paths.h>
1.54      simonb    109: #include <pwd.h>
                    110: #include <signal.h>
1.76      wiz       111: #include <stdint.h>
1.1       cgd       112: #include <stdio.h>
1.10      mycroft   113: #include <stdlib.h>
1.1       cgd       114: #include <string.h>
1.10      mycroft   115: #include <syslog.h>
                    116: #include <unistd.h>
1.20      thorpej   117: #include <util.h>
1.95    ! christos  118: #include <mntopts.h>
1.10      mycroft   119:
1.25      christos  120: #include "dkcksum.h"
                    121: #include "extern.h"
1.92      christos  122: #include "partutil.h"
1.10      mycroft   123:
                    124: struct mntopt mopts[] = {
                    125:        MOPT_STDOPTS,
                    126:        MOPT_ASYNC,
1.22      cgd       127:        MOPT_UPDATE,
1.60      christos  128:        MOPT_GETARGS,
1.23      tls       129:        MOPT_NOATIME,
1.95    ! christos  130:        { .m_option = NULL },
1.10      mycroft   131: };
                    132:
1.54      simonb    133: static gid_t mfs_group(const char *);
                    134: static uid_t mfs_user(const char *);
1.75      dsl       135: static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
1.92      christos  136: static void usage(void) __attribute__((__noreturn__));
1.1       cgd       137:
                    138: #define        COMPAT                  /* allow non-labeled disks */
                    139:
1.92      christos  140: #ifdef COMPAT
                    141: const char lmsg[] = "%s: can't read disk label; disk type must be specified";
                    142: #else
                    143: const char lmsg[] = "%s: can't read disk label";
                    144: #endif
                    145:
1.1       cgd       146: /*
                    147:  * The following two constants set the default block and fragment sizes.
                    148:  * Both constants must be a power of 2 and meet the following constraints:
                    149:  *     MINBSIZE <= DESBLKSIZE <= MAXBSIZE
                    150:  *     sectorsize <= DESFRAGSIZE <= DESBLKSIZE
                    151:  *     DESBLKSIZE / DESFRAGSIZE <= 8
                    152:  */
1.53      augustss  153: /*
                    154:  * For file systems smaller than SMALL_FSSIZE we use the S_DFL_* defaults,
                    155:  * otherwise if less than MEDIUM_FSSIZE use M_DFL_*, otherwise use
                    156:  * L_DFL_*.
                    157:  */
1.54      simonb    158: #define        SMALL_FSSIZE    (20*1024*2)
1.53      augustss  159: #define        S_DFL_FRAGSIZE  512
1.54      simonb    160: #define        MEDIUM_FSSIZE   (1000*1024*2)
1.53      augustss  161: #define        M_DFL_FRAGSIZE  1024
                    162: #define        L_DFL_FRAGSIZE  2048
1.75      dsl       163: #define        DFL_FRAG_BLK    8
1.1       cgd       164:
1.65      dbj       165: /* Apple requires the fragment size to be at least APPLEUFS_DIRBLKSIZ
                    166:  * but the block size cannot be larger than Darwin's PAGE_SIZE.  See
                    167:  * the mount check in Darwin's ffs_mountfs for an explanation.
                    168:  */
                    169: #define APPLEUFS_DFL_FRAGSIZE APPLEUFS_DIRBLKSIZ /* 1024 */
                    170: #define APPLEUFS_DFL_BLKSIZE 4096 /* default Darwin PAGE_SIZE */
                    171:
1.1       cgd       172: /*
1.43      lukem     173:  * Default sector size.
                    174:  */
1.54      simonb    175: #define        DFL_SECSIZE     512
1.43      lukem     176:
                    177: /*
1.1       cgd       178:  * MAXBLKPG determines the maximum number of data blocks which are
                    179:  * placed in a single cylinder group. The default is one indirect
                    180:  * block worth of data blocks.
                    181:  */
1.64      fvdl      182: #define        MAXBLKPG_UFS1(bsize)    ((bsize) / sizeof(int32_t))
                    183: #define        MAXBLKPG_UFS2(bsize)    ((bsize) / sizeof(int64_t))
1.1       cgd       184:
                    185: /*
                    186:  * Each file system has a number of inodes statically allocated.
                    187:  * We allocate one inode slot per NFPI fragments, expecting this
                    188:  * to be far more than we will ever need.
                    189:  */
                    190: #define        NFPI            4
                    191:
                    192:
                    193: int    mfs;                    /* run as the memory based filesystem */
                    194: int    Nflag;                  /* run without writing file system */
1.64      fvdl      195: int    Oflag = 1;              /* format as an 4.3BSD file system */
1.88      dsl       196: int    verbosity;              /* amount of printf() output */
1.94      christos  197: #define DEFAULT_VERBOSITY 3    /* 4 is traditional behavior */
1.64      fvdl      198: int64_t        fssize;                 /* file system size */
1.1       cgd       199: int    sectorsize;             /* bytes/sector */
                    200: int    fsize = 0;              /* fragment size */
                    201: int    bsize = 0;              /* block size */
1.64      fvdl      202: int    maxbsize = 0;           /* maximum clustering */
1.1       cgd       203: int    minfree = MINFREE;      /* free space threshold */
                    204: int    opt = DEFAULTOPT;       /* optimization preference (space or time) */
                    205: int    density;                /* number of bytes per inode */
1.84      lukem     206: int    num_inodes;             /* number of inodes (overrides density) */
1.36      mycroft   207: int    maxcontig = 0;          /* max contiguous blocks to allocate */
1.1       cgd       208: int    maxbpg;                 /* maximum blocks per file in a cyl group */
1.47      lukem     209: int    avgfilesize = AVFILESIZ;/* expected average file size */
                    210: int    avgfpdir = AFPDIR;      /* expected number of files per directory */
1.91      christos  211: int    mntflags = 0;           /* flags to be passed to mount */
1.1       cgd       212: u_long memleft;                /* virtual memory available */
                    213: caddr_t        membase;                /* start address of memory based filesystem */
1.43      lukem     214: int    needswap;               /* Filesystem not in native byte order */
1.92      christos  215: char   *disktype = NULL;
1.1       cgd       216: int    unlabeled;
1.61      dbj       217: char *appleufs_volname = 0; /* Apple UFS volume name */
                    218: int isappleufs = 0;
1.1       cgd       219:
                    220: char   device[MAXPATHLEN];
                    221:
1.10      mycroft   222: int
1.40      simonb    223: main(int argc, char *argv[])
1.1       cgd       224: {
1.92      christos  225:        struct disk_geom geo;
                    226:        struct dkwedge_info dkw;
1.82      christos  227:        struct statvfs *mp;
1.75      dsl       228:        struct stat sb;
                    229:        int ch, fsi, fso, len, n, Fflag, Iflag, Zflag;
                    230:        char *cp, *s1, *s2, *special;
1.43      lukem     231:        const char *opstring;
1.75      dsl       232:        int byte_sized = 0;
1.30      drochner  233: #ifdef MFS
1.79      dsl       234:        struct mfs_args args;
1.30      drochner  235:        char mountfromname[100];
                    236:        pid_t pid, res;
1.82      christos  237:        struct statvfs sf;
1.56      lukem     238:        int status;
                    239: #endif
1.75      dsl       240:        mode_t mfsmode = 01777; /* default mode for a /tmp-type directory */
                    241:        uid_t mfsuid = 0;       /* user root */
                    242:        gid_t mfsgid = 0;       /* group wheel */
1.90      christos  243:        mntoptparse_t mo;
1.1       cgd       244:
1.43      lukem     245:        cp = NULL;
                    246:        fsi = fso = -1;
1.58      lukem     247:        Fflag = Iflag = Zflag = 0;
1.88      dsl       248:        verbosity = -1;
1.42      cgd       249:        if (strstr(getprogname(), "mfs")) {
1.1       cgd       250:                mfs = 1;
1.80      dsl       251:        } else {
                    252:                /* Undocumented, for ease of testing */
1.81      dsl       253:                if (argv[1] != NULL && !strcmp(argv[1], "-mfs")) {
1.80      dsl       254:                        argv++;
                    255:                        argc--;
                    256:                        mfs = 1;
                    257:                }
1.1       cgd       258:        }
                    259:
1.10      mycroft   260:        opstring = mfs ?
1.88      dsl       261:            "NT:V:a:b:d:e:f:g:h:i:m:n:o:p:s:u:" :
                    262:            "B:FINO:S:T:V:Za:b:d:e:f:g:h:i:l:m:n:o:r:s:v:";
1.26      lukem     263:        while ((ch = getopt(argc, argv, opstring)) != -1)
1.10      mycroft   264:                switch (ch) {
1.33      bouyer    265:                case 'B':
                    266:                        if (strcmp(optarg, "be") == 0) {
                    267: #if BYTE_ORDER == LITTLE_ENDIAN
                    268:                                needswap = 1;
                    269: #endif
                    270:                        } else if (strcmp(optarg, "le") == 0) {
                    271: #if BYTE_ORDER == BIG_ENDIAN
                    272:                                needswap = 1;
                    273: #endif
                    274:                        } else
                    275:                                usage();
                    276:                        break;
1.43      lukem     277:                case 'F':
                    278:                        Fflag = 1;
                    279:                        break;
1.58      lukem     280:                case 'I':
                    281:                        Iflag = 1;
                    282:                        break;
1.10      mycroft   283:                case 'N':
                    284:                        Nflag = 1;
1.88      dsl       285:                        if (verbosity == -1)
1.93      christos  286:                                verbosity = DEFAULT_VERBOSITY;
1.1       cgd       287:                        break;
1.10      mycroft   288:                case 'O':
1.75      dsl       289:                        Oflag = strsuftoi64("format", optarg, 0, 2, NULL);
1.1       cgd       290:                        break;
                    291:                case 'S':
1.89      dsl       292:                        /* XXX: non-512 byte sectors almost certainly don't work. */
1.75      dsl       293:                        sectorsize = strsuftoi64("sector size",
1.88      dsl       294:                            optarg, 512, 65536, NULL);
                    295:                        if (sectorsize & (sectorsize - 1))
                    296:                                errx(1, "sector size `%s' is not a power of 2.",
                    297:                                    optarg);
1.1       cgd       298:                        break;
                    299: #ifdef COMPAT
                    300:                case 'T':
                    301:                        disktype = optarg;
                    302:                        break;
                    303: #endif
1.88      dsl       304:                case 'V':
                    305:                        verbosity = strsuftoi64("verbose", optarg, 0, 4, NULL);
                    306:                        break;
1.43      lukem     307:                case 'Z':
                    308:                        Zflag = 1;
                    309:                        break;
1.1       cgd       310:                case 'a':
1.75      dsl       311:                        maxcontig = strsuftoi64("maximum contiguous blocks",
                    312:                            optarg, 1, INT_MAX, NULL);
1.1       cgd       313:                        break;
                    314:                case 'b':
1.75      dsl       315:                        bsize = strsuftoi64("block size",
                    316:                            optarg, MINBSIZE, MAXBSIZE, NULL);
1.1       cgd       317:                        break;
                    318:                case 'd':
1.75      dsl       319:                        maxbsize = strsuftoi64("maximum extent size",
                    320:                            optarg, 0, INT_MAX, NULL);
1.1       cgd       321:                        break;
                    322:                case 'e':
1.75      dsl       323:                        maxbpg = strsuftoi64(
1.43      lukem     324:                            "blocks per file in a cylinder group",
1.75      dsl       325:                            optarg, 1, INT_MAX, NULL);
1.1       cgd       326:                        break;
                    327:                case 'f':
1.75      dsl       328:                        fsize = strsuftoi64("fragment size",
                    329:                            optarg, 1, MAXBSIZE, NULL);
1.1       cgd       330:                        break;
1.47      lukem     331:                case 'g':
1.54      simonb    332:                        if (mfs)
                    333:                                mfsgid = mfs_group(optarg);
                    334:                        else {
1.75      dsl       335:                                avgfilesize = strsuftoi64("average file size",
                    336:                                    optarg, 1, INT_MAX, NULL);
1.54      simonb    337:                        }
1.47      lukem     338:                        break;
                    339:                case 'h':
1.75      dsl       340:                        avgfpdir = strsuftoi64("expected files per directory",
                    341:                            optarg, 1, INT_MAX, NULL);
1.47      lukem     342:                        break;
1.1       cgd       343:                case 'i':
1.75      dsl       344:                        density = strsuftoi64("bytes per inode",
                    345:                            optarg, 1, INT_MAX, NULL);
1.1       cgd       346:                        break;
                    347:                case 'm':
1.75      dsl       348:                        minfree = strsuftoi64("free space %",
                    349:                            optarg, 0, 99, NULL);
1.1       cgd       350:                        break;
1.70      dsl       351:                case 'n':
1.75      dsl       352:                        num_inodes = strsuftoi64("number of inodes",
                    353:                            optarg, 1, INT_MAX, NULL);
1.70      dsl       354:                        break;
1.1       cgd       355:                case 'o':
1.90      christos  356:                        if (mfs) {
                    357:                                mo = getmntopts(optarg, mopts, &mntflags, 0);
                    358:                                if (mo == NULL)
                    359:                                        err(1, "getmntopts");
                    360:                                freemntopts(mo);
                    361:                        } else {
1.10      mycroft   362:                                if (strcmp(optarg, "space") == 0)
                    363:                                        opt = FS_OPTSPACE;
                    364:                                else if (strcmp(optarg, "time") == 0)
                    365:                                        opt = FS_OPTTIME;
                    366:                                else
1.25      christos  367:                                    errx(1, "%s %s",
                    368:                                        "unknown optimization preference: ",
                    369:                                        "use `space' or `time'.");
1.10      mycroft   370:                        }
1.1       cgd       371:                        break;
                    372:                case 'p':
1.88      dsl       373:                        /* mfs only */
                    374:                        if ((mfsmode = strtol(optarg, NULL, 8)) <= 0)
                    375:                                errx(1, "bad mode `%s'", optarg);
1.1       cgd       376:                        break;
                    377:                case 's':
1.75      dsl       378:                        fssize = strsuftoi64("file system size",
                    379:                            optarg, INT64_MIN, INT64_MAX, &byte_sized);
1.1       cgd       380:                        break;
                    381:                case 'u':
1.88      dsl       382:                        /* mfs only */
                    383:                        mfsuid = mfs_user(optarg);
1.1       cgd       384:                        break;
1.61      dbj       385:                case 'v':
                    386:                        appleufs_volname = optarg;
                    387:                        if (strchr(appleufs_volname, ':') || strchr(appleufs_volname, '/'))
                    388:                                errx(1,"Apple UFS volume name cannot contain ':' or '/'");
                    389:                        if (appleufs_volname[0] == '\0')
                    390:                                errx(1,"Apple UFS volume name cannot be zero length");
                    391:                        isappleufs = 1;
                    392:                        break;
1.1       cgd       393:                case '?':
                    394:                default:
                    395:                        usage();
                    396:                }
                    397:        argc -= optind;
                    398:        argv += optind;
1.79      dsl       399:
1.88      dsl       400:        if (verbosity == -1)
                    401:                /* Default to not showing CG info if mfs */
1.93      christos  402:                verbosity = mfs ? 0 : DEFAULT_VERBOSITY;
1.88      dsl       403:
1.79      dsl       404: #ifdef MFS
                    405:        /* This is enough to get through the correct kernel code paths */
                    406:        memset(&args, 0, sizeof args);
                    407:        args.fspec = mountfromname;
1.81      dsl       408:        if (mntflags & (MNT_GETARGS | MNT_UPDATE)) {
1.91      christos  409:                if ((mntflags & MNT_GETARGS) == 0)
                    410:                        mntflags |= MNT_ASYNC;
1.81      dsl       411:                if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0)
                    412:                        err(1, "mount `%s' failed", argv[1]);
                    413:                if (mntflags & MNT_GETARGS)
                    414:                        printf("base=%p, size=%ld\n", args.base, args.size);
                    415:                exit(0);
                    416:        }
1.79      dsl       417: #endif
1.1       cgd       418:
                    419:        if (argc != 2 && (mfs || argc != 1))
                    420:                usage();
                    421:
1.75      dsl       422:        memset(&sb, 0, sizeof sb);
1.1       cgd       423:        special = argv[0];
1.49      lukem     424:        if (Fflag || mfs) {
1.14      cgd       425:                /*
1.75      dsl       426:                 * It's a file system image or an MFS,
                    427:                 * no label, use fixed default for sectorsize.
1.14      cgd       428:                 */
1.75      dsl       429:                if (sectorsize == 0)
1.43      lukem     430:                        sectorsize = DFL_SECSIZE;
                    431:
1.80      dsl       432:                if (mfs) {
                    433:                        /* Default filesystem size to that of supplied device */
                    434:                        if (fssize == 0)
                    435:                                stat(special, &sb);
                    436:                } else {
                    437:                        /* creating image in a regular file */
1.75      dsl       438:                        int fl;
                    439:                        if (Nflag)
                    440:                                fl = O_RDONLY;
                    441:                        else {
                    442:                                if (fssize > 0)
                    443:                                        fl = O_RDWR | O_CREAT;
                    444:                                else
                    445:                                        fl = O_RDWR;
                    446:                        }
                    447:                        fsi = open(special, fl, 0777);
                    448:                        if (fsi == -1)
1.43      lukem     449:                                err(1, "can't open file %s", special);
1.75      dsl       450:                        if (fstat(fsi, &sb) == -1)
                    451:                                err(1, "can't fstat opened %s", special);
                    452:                        if (!Nflag)
                    453:                                fso = fsi;
1.43      lukem     454:                }
1.49      lukem     455:        } else {        /* !Fflag && !mfs */
                    456:                fsi = opendisk(special, O_RDONLY, device, sizeof(device), 0);
                    457:                special = device;
1.75      dsl       458:                if (fsi < 0 || fstat(fsi, &sb) == -1)
1.49      lukem     459:                        err(1, "%s: open for read", special);
                    460:
1.75      dsl       461:                if (!Nflag) {
                    462:                        fso = open(special, O_WRONLY, 0);
1.49      lukem     463:                        if (fso < 0)
                    464:                                err(1, "%s: open for write", special);
                    465:
                    466:                        /* Bail if target special is mounted */
                    467:                        n = getmntinfo(&mp, MNT_NOWAIT);
                    468:                        if (n == 0)
                    469:                                err(1, "%s: getmntinfo", special);
                    470:
                    471:                        len = sizeof(_PATH_DEV) - 1;
                    472:                        s1 = special;
                    473:                        if (strncmp(_PATH_DEV, s1, len) == 0)
                    474:                                s1 += len;
                    475:
                    476:                        while (--n >= 0) {
                    477:                                s2 = mp->f_mntfromname;
                    478:                                if (strncmp(_PATH_DEV, s2, len) == 0) {
                    479:                                        s2 += len - 1;
                    480:                                        *s2 = 'r';
                    481:                                }
                    482:                                if (strcmp(s1, s2) == 0 ||
                    483:                                    strcmp(s1, &s2[1]) == 0)
                    484:                                        errx(1, "%s is mounted on %s",
                    485:                                            special, mp->f_mntonname);
                    486:                                ++mp;
1.10      mycroft   487:                        }
                    488:                }
1.75      dsl       489:
1.1       cgd       490: #ifdef COMPAT
1.49      lukem     491:                if (disktype == NULL)
1.10      mycroft   492:                        disktype = argv[1];
1.1       cgd       493: #endif
1.92      christos  494:                if (getdiskinfo(special, fsi, disktype, &geo, &dkw) == -1)
                    495:                        errx(1, lmsg, special);
                    496:                unlabeled = disktype != NULL;
                    497:
1.75      dsl       498:                if (sectorsize == 0) {
1.92      christos  499:                        sectorsize = geo.dg_secsize;
1.75      dsl       500:                        if (sectorsize <= 0)
                    501:                                errx(1, "no default sector size");
                    502:                }
                    503:
1.92      christos  504:                if (dkw.dkw_parent[0]) {
                    505:                        if (dkw.dkw_size == 0)
                    506:                                errx(1, "%s partition is unavailable", special);
                    507:
                    508:                        if (strcmp(dkw.dkw_ptype, DKW_PTYPE_APPLEUFS) == 0)
1.75      dsl       509:                                isappleufs = 1;
1.92      christos  510:
1.75      dsl       511:                        if (!Iflag) {
1.92      christos  512:                                static const char m[] =
                    513:                                    "%s partition type is not `%s'";
1.75      dsl       514:                                if (isappleufs) {
1.92      christos  515:                                        if (strcmp(dkw.dkw_ptype,
                    516:                                            DKW_PTYPE_APPLEUFS))
                    517:                                                errx(1, m,
                    518:                                                    special, "Apple UFS");
1.75      dsl       519:                                } else {
1.92      christos  520:                                        if (strcmp(dkw.dkw_ptype,
                    521:                                            DKW_PTYPE_FFS))
                    522:                                                errx(1, m, special, "4.2BSD");
1.75      dsl       523:                                }
                    524:                        }
1.92      christos  525:                }       /* !Fflag && !mfs */
                    526:        }
1.43      lukem     527:
1.75      dsl       528:        if (byte_sized)
                    529:                fssize /= sectorsize;
                    530:        if (fssize <= 0) {
                    531:                if (sb.st_size != 0)
                    532:                        fssize += sb.st_size / sectorsize;
                    533:                else
1.92      christos  534:                        fssize += dkw.dkw_size;
1.75      dsl       535:                if (fssize <= 0)
                    536:                        errx(1, "Unable to determine file system size");
                    537:        }
                    538:
1.92      christos  539:        if (dkw.dkw_parent[0] && fssize > dkw.dkw_size)
1.87      dsl       540:                errx(1, "size %" PRIu64 " exceeds maximum file system size on "
1.92      christos  541:                    "`%s' of %" PRIu64 " sectors",
                    542:                    fssize, special, dkw.dkw_size);
1.75      dsl       543:
                    544:        /* XXXLUKEM: only ftruncate() regular files ? (dsl: or at all?) */
                    545:        if (Fflag && fso != -1
                    546:            && ftruncate(fso, (off_t)fssize * sectorsize) == -1)
                    547:                err(1, "can't ftruncate %s to %" PRId64, special, fssize);
                    548:
                    549:        if (Zflag && fso != -1) {       /* pre-zero (and de-sparce) the file */
                    550:                char    *buf;
                    551:                int     bufsize, i;
                    552:                off_t   bufrem;
1.82      christos  553:                struct statvfs sfs;
1.75      dsl       554:
1.82      christos  555:                if (fstatvfs(fso, &sfs) == -1) {
                    556:                        warn("can't fstatvfs `%s'", special);
1.75      dsl       557:                        bufsize = 8192;
                    558:                } else
                    559:                        bufsize = sfs.f_iosize;
                    560:
                    561:                if ((buf = calloc(1, bufsize)) == NULL)
                    562:                        err(1, "can't malloc buffer of %d",
                    563:                        bufsize);
                    564:                bufrem = fssize * sectorsize;
1.88      dsl       565:                if (verbosity > 0)
                    566:                        printf( "Creating file system image in `%s', "
                    567:                            "size %lld bytes, in %d byte chunks.\n",
                    568:                            special, (long long)bufrem, bufsize);
1.75      dsl       569:                while (bufrem > 0) {
                    570:                        i = write(fso, buf, MIN(bufsize, bufrem));
                    571:                        if (i == -1)
                    572:                                err(1, "writing image");
                    573:                        bufrem -= i;
                    574:                }
                    575:                free(buf);
1.53      augustss  576:        }
                    577:
1.75      dsl       578:        /* Sort out fragment and block sizes */
1.1       cgd       579:        if (fsize == 0) {
1.75      dsl       580:                fsize = bsize / DFL_FRAG_BLK;
                    581:                if (fsize <= 0) {
                    582:                        if (isappleufs) {
                    583:                                fsize = APPLEUFS_DFL_FRAGSIZE;
                    584:                        } else {
                    585:                                if (fssize < SMALL_FSSIZE)
                    586:                                        fsize = S_DFL_FRAGSIZE;
                    587:                                else if (fssize < MEDIUM_FSSIZE)
                    588:                                        fsize = M_DFL_FRAGSIZE;
                    589:                                else
                    590:                                        fsize = L_DFL_FRAGSIZE;
                    591:                                if (fsize < sectorsize)
                    592:                                        fsize = sectorsize;
                    593:                        }
                    594:                }
1.1       cgd       595:        }
1.92      christos  596:        if (bsize <= 0) {
                    597:                if (isappleufs)
                    598:                        bsize = APPLEUFS_DFL_BLKSIZE;
                    599:                else
                    600:                        bsize = DFL_FRAG_BLK * fsize;
1.1       cgd       601:        }
1.65      dbj       602:
                    603:        if (isappleufs && (fsize < APPLEUFS_DFL_FRAGSIZE)) {
                    604:                warnx("Warning: chosen fsize of %d is less than Apple UFS minimum of %d",
1.75      dsl       605:                        fsize, APPLEUFS_DFL_FRAGSIZE);
1.65      dbj       606:        }
                    607:        if (isappleufs && (bsize > APPLEUFS_DFL_BLKSIZE)) {
                    608:                warnx("Warning: chosen bsize of %d is greater than Apple UFS maximum of %d",
1.75      dsl       609:                        bsize, APPLEUFS_DFL_BLKSIZE);
1.65      dbj       610:        }
                    611:
1.10      mycroft   612:        /*
                    613:         * Maxcontig sets the default for the maximum number of blocks
                    614:         * that may be allocated sequentially. With filesystem clustering
                    615:         * it is possible to allocate contiguous blocks up to the maximum
                    616:         * transfer size permitted by the controller or buffering.
                    617:         */
                    618:        if (maxcontig == 0)
1.27      lukem     619:                maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize);
1.1       cgd       620:        if (density == 0)
                    621:                density = NFPI * fsize;
1.8       cgd       622:        if (minfree < MINFREE && opt != FS_OPTSPACE) {
1.25      christos  623:                warnx("%s %s %d%%", "Warning: changing optimization to space",
                    624:                    "because minfree is less than", MINFREE);
1.1       cgd       625:                opt = FS_OPTSPACE;
                    626:        }
1.64      fvdl      627:        if (maxbpg == 0) {
                    628:                if (Oflag <= 1)
                    629:                        maxbpg = MAXBLKPG_UFS1(bsize);
                    630:                else
                    631:                        maxbpg = MAXBLKPG_UFS2(bsize);
                    632:        }
1.92      christos  633:        mkfs(special, fsi, fso, mfsmode, mfsuid, mfsgid);
1.75      dsl       634:        if (fsi != -1 && fsi != fso)
                    635:                close(fsi);
                    636:        if (fso != -1)
1.1       cgd       637:                close(fso);
                    638: #ifdef MFS
                    639:        if (mfs) {
                    640:
1.30      drochner  641:                switch (pid = fork()) {
                    642:                case -1:
                    643:                        perror("mfs");
                    644:                        exit(10);
                    645:                case 0:
1.34      mycroft   646:                        (void)snprintf(mountfromname, sizeof(mountfromname),
                    647:                            "mfs:%d", getpid());
1.30      drochner  648:                        break;
                    649:                default:
1.34      mycroft   650:                        (void)snprintf(mountfromname, sizeof(mountfromname),
                    651:                            "mfs:%d", pid);
1.30      drochner  652:                        for (;;) {
                    653:                                /*
                    654:                                 * spin until the mount succeeds
                    655:                                 * or the child exits
                    656:                                 */
                    657:                                usleep(1);
                    658:
                    659:                                /*
                    660:                                 * XXX Here is a race condition: another process
                    661:                                 * can mount a filesystem which hides our
                    662:                                 * ramdisk before we see the success.
                    663:                                 */
1.82      christos  664:                                if (statvfs(argv[1], &sf) < 0)
                    665:                                        err(88, "statvfs %s", argv[1]);
1.30      drochner  666:                                if (!strcmp(sf.f_mntfromname, mountfromname) &&
                    667:                                    !strncmp(sf.f_mntonname, argv[1],
                    668:                                             MNAMELEN) &&
                    669:                                    !strcmp(sf.f_fstypename, "mfs"))
                    670:                                        exit(0);
                    671:
                    672:                                res = waitpid(pid, &status, WNOHANG);
                    673:                                if (res == -1)
                    674:                                        err(11, "waitpid");
                    675:                                if (res != pid)
                    676:                                        continue;
1.31      drochner  677:                                if (WIFEXITED(status)) {
                    678:                                        if (WEXITSTATUS(status) == 0)
                    679:                                                exit(0);
1.30      drochner  680:                                        errx(1, "%s: mount: %s", argv[1],
                    681:                                             strerror(WEXITSTATUS(status)));
1.31      drochner  682:                                } else
1.30      drochner  683:                                        errx(11, "abnormal termination");
                    684:                        }
                    685:                        /* NOTREACHED */
                    686:                }
                    687:
                    688:                (void) setsid();
                    689:                (void) close(0);
                    690:                (void) close(1);
                    691:                (void) close(2);
                    692:                (void) chdir("/");
                    693:
1.1       cgd       694:                args.base = membase;
                    695:                args.size = fssize * sectorsize;
1.91      christos  696:                if (mount(MOUNT_MFS, argv[1], mntflags | MNT_ASYNC, &args) < 0)
1.30      drochner  697:                        exit(errno); /* parent prints message */
1.1       cgd       698:        }
                    699: #endif
                    700:        exit(0);
                    701: }
                    702:
1.54      simonb    703: static gid_t
                    704: mfs_group(const char *gname)
                    705: {
                    706:        struct group *gp;
                    707:
                    708:        if (!(gp = getgrnam(gname)) && !isdigit((unsigned char)*gname))
                    709:                errx(1, "unknown gname %s", gname);
                    710:        return gp ? gp->gr_gid : atoi(gname);
                    711: }
                    712:
                    713: static uid_t
                    714: mfs_user(const char *uname)
                    715: {
                    716:        struct passwd *pp;
                    717:
                    718:        if (!(pp = getpwnam(uname)) && !isdigit((unsigned char)*uname))
                    719:                errx(1, "unknown user %s", uname);
                    720:        return pp ? pp->pw_uid : atoi(uname);
                    721: }
                    722:
1.75      dsl       723: static int64_t
                    724: strsuftoi64(const char *desc, const char *arg, int64_t min, int64_t max, int *num_suffix)
1.43      lukem     725: {
1.75      dsl       726:        int64_t result, r1;
                    727:        int shift = 0;
1.43      lukem     728:        char    *ep;
                    729:
                    730:        errno = 0;
1.75      dsl       731:        r1 = strtoll(arg, &ep, 10);
1.43      lukem     732:        if (ep[0] != '\0' && ep[1] != '\0')
                    733:                errx(1, "%s `%s' is not a valid number.", desc, arg);
1.75      dsl       734:        switch (ep[0]) {
1.43      lukem     735:        case '\0':
1.75      dsl       736:        case 's': case 'S':
                    737:                if (num_suffix != NULL)
                    738:                        *num_suffix = 0;
1.43      lukem     739:                break;
1.75      dsl       740:        case 'g': case 'G':
                    741:                shift += 10;
                    742:                /* FALLTHROUGH */
                    743:        case 'm': case 'M':
                    744:                shift += 10;
                    745:                /* FALLTHROUGH */
                    746:        case 'k': case 'K':
                    747:                shift += 10;
                    748:                /* FALLTHROUGH */
                    749:        case 'b': case 'B':
                    750:                if (num_suffix != NULL)
                    751:                        *num_suffix = 1;
1.43      lukem     752:                break;
                    753:        default:
                    754:                errx(1, "`%s' is not a valid suffix for %s.", ep, desc);
                    755:        }
1.75      dsl       756:        result = r1 << shift;
                    757:        if (errno == ERANGE || result >> shift != r1)
                    758:                errx(1, "%s `%s' is too large to convert.", desc, arg);
1.43      lukem     759:        if (result < min)
1.75      dsl       760:                errx(1, "%s `%s' (%" PRId64 ") is less than the minimum (%" PRId64 ").",
1.43      lukem     761:                    desc, arg, result, min);
                    762:        if (result > max)
1.75      dsl       763:                errx(1, "%s `%s' (%" PRId64 ") is greater than the maximum (%" PRId64 ").",
1.43      lukem     764:                    desc, arg, result, max);
1.75      dsl       765:        return result;
1.43      lukem     766: }
                    767:
1.54      simonb    768: #define        NEWFS           1
                    769: #define        MFS_MOUNT       2
                    770: #define        BOTH            NEWFS | MFS_MOUNT
                    771:
                    772: struct help_strings {
                    773:        int flags;
                    774:        const char *str;
                    775: } const help_strings[] = {
                    776:        { NEWFS,        "-B byteorder\tbyte order (`be' or `le')" },
                    777:        { NEWFS,        "-F \t\tcreate file system image in regular file" },
1.58      lukem     778:        { NEWFS,        "-I \t\tdo not check that the file system type is '4.2BSD'" },
1.54      simonb    779:        { BOTH,         "-N \t\tdo not create file system, just print out "
                    780:                            "parameters" },
1.75      dsl       781:        { NEWFS,        "-O N\t\tfilesystem format: 0 ==> 4.3BSD, 1 ==> FFS, 2 ==> UFS2" },
1.54      simonb    782:        { NEWFS,        "-S secsize\tsector size" },
                    783: #ifdef COMPAT
                    784:        { NEWFS,        "-T disktype\tdisk type" },
                    785: #endif
1.89      dsl       786:        { BOTH,         "-V verbose\toutput verbosity: 0 ==> none, 4 ==> max" },
1.75      dsl       787:        { NEWFS,        "-Z \t\tpre-zero the image file" },
1.54      simonb    788:        { BOTH,         "-a maxcontig\tmaximum contiguous blocks" },
                    789:        { BOTH,         "-b bsize\tblock size" },
1.75      dsl       790:        { BOTH,         "-d maxbsize\tmaximum extent size" },
1.54      simonb    791:        { BOTH,         "-e maxbpg\tmaximum blocks per file in a cylinder group"
                    792:                            },
                    793:        { BOTH,         "-f fsize\tfrag size" },
                    794:        { NEWFS,        "-g avgfilesize\taverage file size" },
                    795:        { MFS_MOUNT,    "-g groupname\tgroup name of mount point" },
                    796:        { BOTH,         "-h avgfpdir\taverage files per directory" },
                    797:        { BOTH,         "-i density\tnumber of bytes per inode" },
                    798:        { BOTH,         "-m minfree\tminimum free space %%" },
1.78      jmmv      799:        { BOTH,         "-n inodes\tnumber of inodes (overrides -i density)" },
1.54      simonb    800:        { BOTH,         "-o optim\toptimization preference (`space' or `time')"
                    801:                            },
                    802:        { MFS_MOUNT,    "-p perm\t\tpermissions (in octal)" },
                    803:        { BOTH,         "-s fssize\tfile system size (sectors)" },
                    804:        { MFS_MOUNT,    "-u username\tuser name of mount point" },
1.61      dbj       805:        { NEWFS,        "-v volname\tApple UFS volume name" },
1.54      simonb    806:        { 0, NULL }
                    807: };
                    808:
1.25      christos  809: static void
1.40      simonb    810: usage(void)
1.1       cgd       811: {
1.54      simonb    812:        int match;
                    813:        const struct help_strings *hs;
1.43      lukem     814:
1.1       cgd       815:        if (mfs) {
                    816:                fprintf(stderr,
1.43      lukem     817:                    "usage: %s [ fsoptions ] special-device mount-point\n",
1.42      cgd       818:                        getprogname());
1.1       cgd       819:        } else
                    820:                fprintf(stderr,
1.43      lukem     821:                    "usage: %s [ fsoptions ] special-device%s\n",
1.42      cgd       822:                    getprogname(),
1.1       cgd       823: #ifdef COMPAT
1.75      dsl       824:                    " [disk-type]");
1.1       cgd       825: #else
                    826:                    "");
                    827: #endif
                    828:        fprintf(stderr, "where fsoptions are:\n");
1.54      simonb    829:
                    830:        match = mfs ? MFS_MOUNT : NEWFS;
                    831:        for (hs = help_strings; hs->flags != 0; hs++)
                    832:                if (hs->flags & match)
                    833:                        fprintf(stderr, "\t%s\n", hs->str);
1.1       cgd       834:        exit(1);
                    835: }

CVSweb <webmaster@jp.NetBSD.org>