merge mkfs and newfs; add support for disk labels
authorKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 14 Jan 1987 04:32:23 +0000 (20:32 -0800)
committerKirk McKusick <mckusick@ucbvax.Berkeley.EDU>
Wed, 14 Jan 1987 04:32:23 +0000 (20:32 -0800)
SCCS-vsn: sbin/newfs/newfs.c 6.1
SCCS-vsn: sbin/newfs/mkfs.c 6.1

usr/src/sbin/newfs/mkfs.c
usr/src/sbin/newfs/newfs.c

index 195fa99..5689fb1 100644 (file)
@@ -5,94 +5,12 @@
  */
 
 #ifndef lint
  */
 
 #ifndef lint
-char copyright[] =
-"@(#) Copyright (c) 1980 Regents of the University of California.\n\
- All rights reserved.\n";
-#endif not lint
-
-#ifndef lint
-static char sccsid[] = "@(#)mkfs.c     5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)mkfs.c     6.1 (Berkeley) %G%";
 #endif not lint
 
 /*
  * make file system for cylinder-group style file systems
 #endif not lint
 
 /*
  * make file system for cylinder-group style file systems
- *
- * usage:
- *    mkfs -N special size [ nsect ntrak bsize fsize cpg minfree rps nbpi opt ]
- */
-
-/*
- * The following constants set the defaults used for the number
- * of sectors (fs_nsect), and number of tracks (fs_ntrak).
- */
-#define DFLNSECT       32
-#define DFLNTRAK       16
-
-/*
- * The following two constants set the default block and fragment sizes.
- * Both constants must be a power of 2 and meet the following constraints:
- *     MINBSIZE <= DESBLKSIZE <= MAXBSIZE
- *     DEV_BSIZE <= DESFRAGSIZE <= DESBLKSIZE
- *     DESBLKSIZE / DESFRAGSIZE <= 8
- */
-#define DESBLKSIZE     8192
-#define DESFRAGSIZE    1024
-
-/*
- * Cylinder groups may have up to MAXCPG cylinders. The actual
- * number used depends upon how much information can be stored
- * on a single cylinder. The default is to used 16 cylinders
- * per group.
- */
-#define        DESCPG          16      /* desired fs_cpg */
-
-/*
- * MINFREE gives the minimum acceptable percentage of file system
- * blocks which may be free. If the freelist drops below this level
- * only the superuser may continue to allocate blocks. This may
- * be set to 0 if no reserve of free blocks is deemed necessary,
- * however throughput drops by fifty percent if the file system
- * is run at between 90% and 100% full; thus the default value of
- * fs_minfree is 10%. With 10% free space, fragmentation is not a
- * problem, so we choose to optimize for time.
- */
-#define MINFREE                10
-#define DEFAULTOPT     FS_OPTTIME
-
-/*
- * ROTDELAY gives the minimum number of milliseconds to initiate
- * another disk transfer on the same cylinder. It is used in
- * determining the rotationally optimal layout for disk blocks
- * within a file; the default of fs_rotdelay is 4ms.
- */
-#define ROTDELAY       4
-
-/*
- * MAXCONTIG sets the default for the maximum number of blocks
- * that may be allocated sequentially. Since UNIX drivers are
- * not capable of scheduling multi-block transfers, this defaults
- * to 1 (ie no contiguous blocks are allocated).
  */
  */
-#define MAXCONTIG      1
-
-/*
- * MAXBLKPG determines the maximum number of data blocks which are
- * placed in a single cylinder group. This is currently a function
- * of the block and fragment size of the file system.
- */
-#define MAXBLKPG(fs)   ((fs)->fs_fsize / sizeof(daddr_t))
-
-/*
- * Each file system has a number of inodes statically allocated.
- * We allocate one inode slot per NBPI bytes, expecting this
- * to be far more than we will ever need.
- */
-#define        NBPI            2048
-
-/*
- * Disks are assumed to rotate at 60HZ, unless otherwise specified.
- */
-#define        DEFHZ           60
 
 #ifndef STANDALONE
 #include <stdio.h>
 
 #ifndef STANDALONE
 #include <stdio.h>
@@ -103,11 +21,38 @@ static char sccsid[] = "@(#)mkfs.c 5.3 (Berkeley) %G%";
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include <sys/dir.h>
 #include <sys/inode.h>
 #include <sys/fs.h>
 #include <sys/dir.h>
+#include <sys/disklabel.h>
+
+/*
+ * MAXBLKPG determines the maximum number of data blocks which are
+ * placed in a single cylinder group. This is currently a function
+ * of the block and fragment size of the file system.
+ */
+#define MAXBLKPG(fs)   ((fs)->fs_fsize / sizeof(daddr_t))
 
 #define UMASK          0755
 #define MAXINOPB       (MAXBSIZE / sizeof(struct dinode))
 #define POWEROF2(num)  (((num) & ((num) - 1)) == 0)
 
 
 #define UMASK          0755
 #define MAXINOPB       (MAXBSIZE / sizeof(struct dinode))
 #define POWEROF2(num)  (((num) & ((num) - 1)) == 0)
 
+/*
+ * variables set up by front end.
+ */
+int    Nflag;                  /* run mkfs without writing file system */
+int    fssize;                 /* file system size */
+int    ntracks;                /* # tracks/cylinder */
+int    nsectors;               /* # sectors/track */
+int     secpercyl;              /* sectors per cylinder */
+int    sectorsize;             /* bytes/sector */
+int    rpm;                    /* revolutions/minute of drive */
+int    fsize;                  /* fragment size */
+int    bsize;                  /* block size */
+int    cpg;                    /* cylinders/cylinder group */
+int    minfree;                /* free space threshold */
+int    opt;                    /* optimization preference (space or time) */
+int    density;                /* number of bytes per inode */
+int    maxcontig;              /* max contiguous blocks to allocate */
+int    rotdelay;               /* rotational delay between blocks */
+
 union {
        struct fs fs;
        char pad[MAXBSIZE];
 union {
        struct fs fs;
        char pad[MAXBSIZE];
@@ -123,103 +68,44 @@ union {
 
 struct dinode zino[MAXIPG];
 
 
 struct dinode zino[MAXIPG];
 
-char   *fsys;
+int    fsi, fso;
 time_t utime;
 time_t utime;
-int    fsi;
-int    fso;
-int    Nflag;
 daddr_t        alloc();
 
 daddr_t        alloc();
 
-main(argc, argv)
-       int argc;
-       char *argv[];
+mkfs(pp, fsys, fi, fo)
+       struct partition *pp;
+       char *fsys;
+       int fi, fo;
 {
 {
-       long cylno, rpos, blk, i, j, inos, fssize, warn = 0;
+       long cylno, rpos, blk, i, j, warn = 0;
 
 #ifndef STANDALONE
 
 #ifndef STANDALONE
-       argc--, argv++;
-       if (argv[0][0] == '-') {
-               switch (argv[0][1]) {
-               case 'N':
-                       Nflag++;
-                       break;
-               default:
-                       printf("%s: unknown flag\n", &argv[0][1]);
-                       argc = 1;       /* force usage message */
-                       break;
-               }
-               argc--, argv++;
-       }
        time(&utime);
        time(&utime);
-       if (argc < 2) {
-               printf("usage: mkfs -N special size [ nsect ntrak bsize fsize cpg minfree rps nbpi ]\n");
-               exit(1);
-       }
-       fsys = argv[0];
-       fssize = atoi(argv[1]);
-       if (!Nflag) {
-               fso = creat(fsys, 0666);
-               if(fso < 0) {
-                       printf("%s: cannot create\n", fsys);
-                       exit(1);
-               }
-       }
-       fsi = open(fsys, 0);
-       if(fsi < 0) {
-               printf("%s: cannot open\n", fsys);
-               exit(1);
-       }
-#else
-       {
-               static char protos[60];
-               char fsbuf[100];
-
-               printf("file sys size: ");
-               gets(protos);
-               fssize = atoi(protos);
-               do {
-                       printf("file system: ");
-                       gets(fsbuf);
-                       fso = open(fsbuf, 1);
-                       fsi = open(fsbuf, 0);
-               } while (fso < 0 || fsi < 0);
-       }
-       argc = 0;
 #endif
 #endif
+       fsi = fi;
+       fso = fo;
        /*
         * Validate the given file system size.
         * Verify that its last block can actually be accessed.
         */
        if (fssize <= 0)
                printf("preposterous size %d\n", fssize), exit(1);
        /*
         * Validate the given file system size.
         * Verify that its last block can actually be accessed.
         */
        if (fssize <= 0)
                printf("preposterous size %d\n", fssize), exit(1);
-       wtfs(fssize - 1, DEV_BSIZE, (char *)&sblock);
+       wtfs(fssize - 1, sectorsize, (char *)&sblock);
        /*
         * collect and verify the sector and track info
         */
        /*
         * collect and verify the sector and track info
         */
-       if (argc > 2)
-               sblock.fs_nsect = atoi(argv[2]);
-       else
-               sblock.fs_nsect = DFLNSECT;
-       if (argc > 3)
-               sblock.fs_ntrak = atoi(argv[3]);
-       else
-               sblock.fs_ntrak = DFLNTRAK;
+       sblock.fs_nsect = nsectors;
+       sblock.fs_ntrak = ntracks;
        if (sblock.fs_ntrak <= 0)
                printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
        if (sblock.fs_nsect <= 0)
                printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
        if (sblock.fs_ntrak <= 0)
                printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1);
        if (sblock.fs_nsect <= 0)
                printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1);
-       sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect;
+       sblock.fs_spc = secpercyl;
        /*
         * collect and verify the block and fragment sizes
         */
        /*
         * collect and verify the block and fragment sizes
         */
-       if (argc > 4)
-               sblock.fs_bsize = atoi(argv[4]);
-       else
-               sblock.fs_bsize = DESBLKSIZE;
-       if (argc > 5)
-               sblock.fs_fsize = atoi(argv[5]);
-       else
-               sblock.fs_fsize = DESFRAGSIZE;
+       sblock.fs_bsize = bsize;
+       sblock.fs_fsize = fsize;
        if (!POWEROF2(sblock.fs_bsize)) {
                printf("block size must be a power of 2, not %d\n",
                    sblock.fs_bsize);
        if (!POWEROF2(sblock.fs_bsize)) {
                printf("block size must be a power of 2, not %d\n",
                    sblock.fs_bsize);
@@ -230,9 +116,9 @@ main(argc, argv)
                    sblock.fs_fsize);
                exit(1);
        }
                    sblock.fs_fsize);
                exit(1);
        }
-       if (sblock.fs_fsize < DEV_BSIZE) {
+       if (sblock.fs_fsize < sectorsize) {
                printf("fragment size %d is too small, minimum is %d\n",
                printf("fragment size %d is too small, minimum is %d\n",
-                   sblock.fs_fsize, DEV_BSIZE);
+                   sblock.fs_fsize, sectorsize);
                exit(1);
        }
        if (sblock.fs_bsize < MINBSIZE) {
                exit(1);
        }
        if (sblock.fs_bsize < MINBSIZE) {
@@ -262,8 +148,8 @@ main(argc, argv)
        }
        sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
        sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
        }
        sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
        sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode);
-       sblock.fs_nspf = sblock.fs_fsize / DEV_BSIZE;
-       for (sblock.fs_fsbtodb = 0, i = sblock.fs_nspf; i > 1; i >>= 1)
+       sblock.fs_nspf = sblock.fs_fsize / sectorsize;
+       for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
                sblock.fs_fsbtodb++;
        sblock.fs_sblkno =
            roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
                sblock.fs_fsbtodb++;
        sblock.fs_sblkno =
            roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag);
@@ -271,8 +157,7 @@ main(argc, argv)
            roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag));
        sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
        sblock.fs_cgoffset = roundup(
            roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag));
        sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
        sblock.fs_cgoffset = roundup(
-           howmany(sblock.fs_nsect, sblock.fs_fsize / DEV_BSIZE),
-           sblock.fs_frag);
+           howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
        for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
                sblock.fs_cgmask <<= 1;
        if (!POWEROF2(sblock.fs_ntrak))
        for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
                sblock.fs_cgmask <<= 1;
        if (!POWEROF2(sblock.fs_ntrak))
@@ -290,31 +175,27 @@ main(argc, argv)
        /* 
         * collect and verify the number of cylinders per group
         */
        /* 
         * collect and verify the number of cylinders per group
         */
-       if (argc > 6) {
-               sblock.fs_cpg = atoi(argv[6]);
-               sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
-       } else {
-               sblock.fs_cpg = MAX(sblock.fs_cpc, DESCPG);
+       sblock.fs_cpg = cpg;
+       if (sblock.fs_cpg % sblock.fs_cpc != 0) {
+               sblock.fs_cpg -= sblock.fs_cpg % sblock.fs_cpc;
+               printf("%s groups must have a multiple of %d cylinders\n",
+                       "Warning: cylinder", sblock.fs_cpc);
+       }
+       sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
+       while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) &&
+           sblock.fs_cpg > sblock.fs_cpc) {
+               sblock.fs_cpg -= sblock.fs_cpc;
                sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
                sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
-               while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) &&
-                   sblock.fs_cpg > sblock.fs_cpc) {
-                       sblock.fs_cpg -= sblock.fs_cpc;
-                       sblock.fs_fpg =
-                           (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
-               }
        }
        if (sblock.fs_cpg < 1) {
                printf("cylinder groups must have at least 1 cylinder\n");
                exit(1);
        }
        if (sblock.fs_cpg < 1) {
                printf("cylinder groups must have at least 1 cylinder\n");
                exit(1);
-       }
-       if (sblock.fs_cpg > MAXCPG) {
+       } else if (sblock.fs_cpg > MAXCPG) {
                printf("cylinder groups are limited to %d cylinders\n", MAXCPG);
                exit(1);
                printf("cylinder groups are limited to %d cylinders\n", MAXCPG);
                exit(1);
-       }
-       if (sblock.fs_cpg % sblock.fs_cpc != 0) {
-               printf("cylinder groups must have a multiple of %d cylinders\n",
-                   sblock.fs_cpc);
-               exit(1);
+       } else if (sblock.fs_cpg < cpg) {
+               printf("%s: block size restricts cylinders per group to %d\n",
+                       "Warning", sblock.fs_cpg);
        }
        /*
         * Now have size for file system and nsect and ntrak.
        }
        /*
         * Now have size for file system and nsect and ntrak.
@@ -411,22 +292,14 @@ next:
        }
        /*
         * Compute number of inode blocks per cylinder group.
        }
        /*
         * Compute number of inode blocks per cylinder group.
-        * Start with one inode per NBPI bytes; adjust as necessary.
+        * Start with one inode per density bytes; adjust as necessary.
         */
         */
-       inos = MAX(NBPI, sblock.fs_fsize);
-       if (argc > 9) {
-               i = atoi(argv[9]);
-               if (i <= 0)
-                       printf("%s: bogus nbpi reset to %d\n", argv[9], inos);
-               else
-                       inos = i;
-       }
        i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock);
        i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock);
-       inos = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize / inos /
+       density = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize / density /
            INOPB(&sblock);
            INOPB(&sblock);
-       if (inos <= 0)
-               inos = 1;
-       sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock);
+       if (density <= 0)
+               density = 1;
+       sblock.fs_ipg = ((density / sblock.fs_ncg) + 1) * INOPB(&sblock);
        if (sblock.fs_ipg > MAXIPG)
                sblock.fs_ipg = MAXIPG;
        sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
        if (sblock.fs_ipg > MAXIPG)
                sblock.fs_ipg = MAXIPG;
        sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
@@ -473,34 +346,12 @@ next:
        sblock.fs_sbsize = fragroundup(&sblock, i);
        fscs = (struct csum *)calloc(1, sblock.fs_cssize);
        sblock.fs_magic = FS_MAGIC;
        sblock.fs_sbsize = fragroundup(&sblock, i);
        fscs = (struct csum *)calloc(1, sblock.fs_cssize);
        sblock.fs_magic = FS_MAGIC;
-       sblock.fs_rotdelay = ROTDELAY;
-       if (argc > 7) {
-               sblock.fs_minfree = atoi(argv[7]);
-               if (sblock.fs_minfree < 0 || sblock.fs_minfree > 99) {
-                       printf("%s: bogus minfree reset to %d%%\n", argv[7],
-                               MINFREE);
-                       sblock.fs_minfree = MINFREE;
-               }
-       } else
-               sblock.fs_minfree = MINFREE;
-       sblock.fs_maxcontig = MAXCONTIG;
+       sblock.fs_rotdelay = rotdelay;
+       sblock.fs_minfree = minfree;
+       sblock.fs_maxcontig = maxcontig;
        sblock.fs_maxbpg = MAXBLKPG(&sblock);
        sblock.fs_maxbpg = MAXBLKPG(&sblock);
-       if (argc > 8)
-               sblock.fs_rps = atoi(argv[8]);
-       else
-               sblock.fs_rps = DEFHZ;
-       if (argc > 10)
-               if (*argv[10] == 's')
-                       sblock.fs_optim = FS_OPTSPACE;
-               else if (*argv[10] == 't')
-                       sblock.fs_optim = FS_OPTTIME;
-               else {
-                       printf("%s: bogus optimization preference %s\n",
-                               argv[10], "reset to time");
-                       sblock.fs_optim = FS_OPTTIME;
-               }
-       else
-               sblock.fs_optim = DEFAULTOPT;
+       sblock.fs_rps = rpm / 60;
+       sblock.fs_optim = opt;
        sblock.fs_cgrotor = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        sblock.fs_cstotal.cs_nbfree = 0;
        sblock.fs_cgrotor = 0;
        sblock.fs_cstotal.cs_ndir = 0;
        sblock.fs_cstotal.cs_nbfree = 0;
@@ -550,9 +401,14 @@ next:
        for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
                wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
                    SBSIZE, (char *)&sblock);
        for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
                wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
                    SBSIZE, (char *)&sblock);
-#ifndef STANDALONE
-       exit(0);
-#endif
+       /*
+        * Update information about this partion in pack
+        * label, to that it may be updated on disk.
+        */
+       pp->p_fstype = FS_BSDFFS;
+       pp->p_fsize = sblock.fs_fsize;
+       pp->p_frag = sblock.fs_frag;
+       pp->p_cpg = sblock.fs_cpg;
 }
 
 /*
 }
 
 /*
@@ -676,17 +532,27 @@ initcg(cylno)
  * initialize the file system
  */
 struct inode node;
  * initialize the file system
  */
 struct inode node;
+
+#ifdef LOSTDIR
 #define PREDEFDIR 3
 #define PREDEFDIR 3
+#else
+#define PREDEFDIR 2
+#endif
+
 struct direct root_dir[] = {
        { ROOTINO, sizeof(struct direct), 1, "." },
        { ROOTINO, sizeof(struct direct), 2, ".." },
 struct direct root_dir[] = {
        { ROOTINO, sizeof(struct direct), 1, "." },
        { ROOTINO, sizeof(struct direct), 2, ".." },
+#ifdef LOSTDIR
        { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
        { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
+#endif
 };
 };
+#ifdef LOSTDIR
 struct direct lost_found_dir[] = {
        { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
        { ROOTINO, sizeof(struct direct), 2, ".." },
        { 0, DIRBLKSIZ, 0, 0 },
 };
 struct direct lost_found_dir[] = {
        { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
        { ROOTINO, sizeof(struct direct), 2, ".." },
        { 0, DIRBLKSIZ, 0, 0 },
 };
+#endif
 char buf[MAXBSIZE];
 
 fsinit()
 char buf[MAXBSIZE];
 
 fsinit()
@@ -699,6 +565,7 @@ fsinit()
        node.i_atime = utime;
        node.i_mtime = utime;
        node.i_ctime = utime;
        node.i_atime = utime;
        node.i_mtime = utime;
        node.i_ctime = utime;
+#ifdef LOSTDIR
        /*
         * create the lost+found directory
         */
        /*
         * create the lost+found directory
         */
@@ -713,6 +580,7 @@ fsinit()
        node.i_blocks = btodb(fragroundup(&sblock, node.i_size));
        wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf);
        iput(&node);
        node.i_blocks = btodb(fragroundup(&sblock, node.i_size));
        wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf);
        iput(&node);
+#endif
        /*
         * create the root directory
         */
        /*
         * create the root directory
         */
@@ -845,7 +713,7 @@ rdfs(bno, size, bf)
 {
        int n;
 
 {
        int n;
 
-       if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) {
+       if (lseek(fsi, bno * sectorsize, 0) < 0) {
                printf("seek error: %ld\n", bno);
                perror("rdfs");
                exit(1);
                printf("seek error: %ld\n", bno);
                perror("rdfs");
                exit(1);
@@ -870,7 +738,7 @@ wtfs(bno, size, bf)
 
        if (Nflag)
                return;
 
        if (Nflag)
                return;
-       if (lseek(fso, bno * DEV_BSIZE, 0) < 0) {
+       if (lseek(fso, bno * sectorsize, 0) < 0) {
                printf("seek error: %ld\n", bno);
                perror("wtfs");
                exit(1);
                printf("seek error: %ld\n", bno);
                perror("wtfs");
                exit(1);
index 0d88c30..5f49963 100644 (file)
@@ -11,7 +11,7 @@ char copyright[] =
 #endif not lint
 
 #ifndef lint
 #endif not lint
 
 #ifndef lint
-static char sccsid[] = "@(#)newfs.c    5.3 (Berkeley) %G%";
+static char sccsid[] = "@(#)newfs.c    6.1 (Berkeley) %G%";
 #endif not lint
 
 /*
 #endif not lint
 
 /*
@@ -21,42 +21,87 @@ static char sccsid[] = "@(#)newfs.c 5.3 (Berkeley) %G%";
 #include <sys/stat.h>
 #include <sys/fs.h>
 #include <sys/dir.h>
 #include <sys/stat.h>
 #include <sys/fs.h>
 #include <sys/dir.h>
+#include <sys/ioctl.h>
+#include <sys/disklabel.h>
+#include <sys/file.h>
 
 #include <stdio.h>
 
 #include <stdio.h>
-#include <disktab.h>
+#include <ctype.h>
 
 
-#ifdef vax
-#define        BOOTDIR "/usr/mdec"     /* directory for boot blocks */
-#endif
+/*
+ * The following two constants set the default block and fragment sizes.
+ * Both constants must be a power of 2 and meet the following constraints:
+ *     MINBSIZE <= DESBLKSIZE <= MAXBSIZE
+ *     sectorsize <= DESFRAGSIZE <= DESBLKSIZE
+ *     DESBLKSIZE / DESFRAGSIZE <= 8
+ */
+#define        DFL_FRAGSIZE    1024
+#define        DFL_BLKSIZE     8192
+
+/*
+ * Cylinder groups may have up to MAXCPG cylinders. The actual
+ * number used depends upon how much information can be stored
+ * on a single cylinder. The default is to used 16 cylinders
+ * per group.
+ */
+#define        DESCPG          16      /* desired fs_cpg */
 
 
-int    Nflag;                  /* run mkfs without writing file system */
-int    verbose;                /* show mkfs line before exec */
-int    noboot;                 /* do not fill boot blocks */
+/*
+ * MINFREE gives the minimum acceptable percentage of file system
+ * blocks which may be free. If the freelist drops below this level
+ * only the superuser may continue to allocate blocks. This may
+ * be set to 0 if no reserve of free blocks is deemed necessary,
+ * however throughput drops by fifty percent if the file system
+ * is run at between 90% and 100% full; thus the default value of
+ * fs_minfree is 10%. With 10% free space, fragmentation is not a
+ * problem, so we choose to optimize for time.
+ */
+#define MINFREE                10
+#define DEFAULTOPT     FS_OPTTIME
+
+/*
+ * ROTDELAY gives the minimum number of milliseconds to initiate
+ * another disk transfer on the same cylinder. It is used in
+ * determining the rotationally optimal layout for disk blocks
+ * within a file; the default of fs_rotdelay is 4ms.
+ */
+#define ROTDELAY       4
+
+/*
+ * MAXCONTIG sets the default for the maximum number of blocks
+ * that may be allocated sequentially. Since UNIX drivers are
+ * not capable of scheduling multi-block transfers, this defaults
+ * to 1 (ie no contiguous blocks are allocated).
+ */
+#define MAXCONTIG      1
+
+/*
+ * Each file system has a number of inodes statically allocated.
+ * We allocate one inode slot per NBPI bytes, expecting this
+ * to be far more than we will ever need.
+ */
+#define        NBPI            2048
+
+int    Nflag;                  /* run without writing file system */
 int    fssize;                 /* file system size */
 int    fssize;                 /* file system size */
-int    fsize;                  /* fragment size */
-int    bsize;                  /* block size */
 int    ntracks;                /* # tracks/cylinder */
 int    nsectors;               /* # sectors/track */
 int    ntracks;                /* # tracks/cylinder */
 int    nsectors;               /* # sectors/track */
+int    nspares = -1;           /* spare sectors per cylinder */
+int    secpercyl;              /* sectors per cylinder */
 int    sectorsize;             /* bytes/sector */
 int    sectorsize;             /* bytes/sector */
-int    cpg;                    /* cylinders/cylinder group */
-int    minfree = -1;           /* free space threshold */
-int    opt;                    /* optimization preference (space or time) */
 int    rpm;                    /* revolutions/minute of drive */
 int    rpm;                    /* revolutions/minute of drive */
-int    density;                /* number of bytes per inode */
-
-char   *av[20];                /* argv array and buffers for exec */
-char   a2[20];
-char   a3[20];
-char   a4[20];
-char   a5[20];
-char   a6[20];
-char   a7[20];
-char   a8[20];
-char   a9[20];
-char   a10[20];
+int    fsize = DFL_FRAGSIZE;   /* fragment size */
+int    bsize = DFL_BLKSIZE;    /* block size */
+int    cpg = DESCPG;           /* cylinders/cylinder group */
+int    minfree = MINFREE;      /* free space threshold */
+int    opt = DEFAULTOPT;       /* optimization preference (space or time) */
+int    density = NBPI;         /* number of bytes per inode */
+int    maxcontig = MAXCONTIG;  /* max contiguous blocks to allocate */
+int    rotdelay = ROTDELAY;    /* rotational delay between blocks */
+
 char   device[MAXPATHLEN];
 char   device[MAXPATHLEN];
-char   cmd[BUFSIZ];
 
 
+extern int errno;
 char   *index();
 char   *rindex();
 char   *sprintf();
 char   *index();
 char   *rindex();
 char   *sprintf();
@@ -66,9 +111,12 @@ main(argc, argv)
        char *argv[];
 {
        char *cp, *special;
        char *argv[];
 {
        char *cp, *special;
-       register struct disktab *dp;
        register struct partition *pp;
        register struct partition *pp;
+       register struct disklabel *lp;
+       struct disklabel *getdisklabel();
+       struct partition oldpartition;
        struct stat st;
        struct stat st;
+       int fsi, fso;
        register int i;
        int status;
 
        register int i;
        int status;
 
@@ -77,49 +125,26 @@ main(argc, argv)
                for (cp = &argv[0][1]; *cp; cp++)
                        switch (*cp) {
 
                for (cp = &argv[0][1]; *cp; cp++)
                        switch (*cp) {
 
-                       case 'v':
-                               verbose++;
-                               break;
-
                        case 'N':
                                Nflag++;
                        case 'N':
                                Nflag++;
-                               /* fall through to */
-
-                       case 'n':
-                               noboot++;
                                break;
 
                                break;
 
-                       case 's':
-                               if (argc < 1)
-                                       fatal("-s: missing file system size");
-                               argc--, argv++;
-                               fssize = atoi(*argv);
-                               if (fssize < 0)
-                                       fatal("%s: bad file system size",
-                                               *argv);
-                               goto next;
-
-                       case 't':
+                       case 'S':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-t: missing track total");
+                                       fatal("-S: missing sector size");
                                argc--, argv++;
                                argc--, argv++;
-                               ntracks = atoi(*argv);
-                               if (ntracks < 0)
-                                       fatal("%s: bad total tracks", *argv);
+                               sectorsize = atoi(*argv);
+                               if (sectorsize <= 0)
+                                       fatal("%s: bad sector size", *argv);
                                goto next;
 
                                goto next;
 
-                       case 'o':
+                       case 'a':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-o: missing optimization preference");
+                                       fatal("-a: spare sectors per cylinder");
                                argc--, argv++;
                                argc--, argv++;
-                               if (strcmp(*argv, "space") == 0)
-                                       opt = FS_OPTSPACE;
-                               else if (strcmp(*argv, "time") == 0)
-                                       opt = FS_OPTTIME;
-                               else
-                                       fatal("%s: bad optimization preference %s",
-                                           *argv,
-                                           "(options are `space' or `time')");
+                               nspares = atoi(*argv);
+                               if (nspares < 0)
+                                       fatal("%s: bad spare sectors per cylinder", *argv);
                                goto next;
 
                        case 'b':
                                goto next;
 
                        case 'b':
@@ -127,35 +152,45 @@ main(argc, argv)
                                        fatal("-b: missing block size");
                                argc--, argv++;
                                bsize = atoi(*argv);
                                        fatal("-b: missing block size");
                                argc--, argv++;
                                bsize = atoi(*argv);
-                               if (bsize < 0 || bsize < MINBSIZE)
+                               if (bsize < MINBSIZE)
                                        fatal("%s: bad block size", *argv);
                                goto next;
 
                                        fatal("%s: bad block size", *argv);
                                goto next;
 
-                       case 'f':
+                       case 'c':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-f: missing frag size");
+                                       fatal("-c: missing cylinders/group");
                                argc--, argv++;
                                argc--, argv++;
-                               fsize = atoi(*argv);
-                               if (fsize < 0)
-                                       fatal("%s: bad frag size", *argv);
+                               cpg = atoi(*argv);
+                               if (cpg <= 0)
+                                       fatal("%s: bad cylinders/group", *argv);
                                goto next;
 
                                goto next;
 
-                       case 'S':
+                       case 'd':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-S: missing sector size");
+                                       fatal("-d: missing sectors/track");
                                argc--, argv++;
                                argc--, argv++;
-                               sectorsize = atoi(*argv);
-                               if (sectorsize < 0)
-                                       fatal("%s: bad sector size", *argv);
+                               nsectors = atoi(*argv);
+                               if (nsectors <= 0)
+                                       fatal("%s: bad sectors/track", *argv);
                                goto next;
 
                                goto next;
 
-                       case 'c':
+                       case 'f':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-c: missing cylinders/group");
+                                       fatal("-f: missing frag size");
                                argc--, argv++;
                                argc--, argv++;
-                               cpg = atoi(*argv);
-                               if (cpg < 0)
-                                       fatal("%s: bad cylinders/group", *argv);
+                               fsize = atoi(*argv);
+                               if (fsize <= 0)
+                                       fatal("%s: bad frag size", *argv);
+                               goto next;
+
+                       case 'i':
+                               if (argc < 1)
+                                       fatal("-i: missing bytes per inode\n");
+                               argc--, argv++;
+                               density = atoi(*argv);
+                               if (density <= 0)
+                                       fatal("%s: bad bytes per inode\n",
+                                               *argv);
                                goto next;
 
                        case 'm':
                                goto next;
 
                        case 'm':
@@ -168,48 +203,72 @@ main(argc, argv)
                                                *argv);
                                goto next;
 
                                                *argv);
                                goto next;
 
+                       case 'o':
+                               if (argc < 1)
+                                       fatal("-o: missing optimization preference");
+                               argc--, argv++;
+                               if (strcmp(*argv, "space") == 0)
+                                       opt = FS_OPTSPACE;
+                               else if (strcmp(*argv, "time") == 0)
+                                       opt = FS_OPTTIME;
+                               else
+                                       fatal("%s: bad optimization preference %s",
+                                           *argv,
+                                           "(options are `space' or `time')");
+                               goto next;
+
                        case 'r':
                                if (argc < 1)
                                        fatal("-r: missing revs/minute\n");
                                argc--, argv++;
                                rpm = atoi(*argv);
                        case 'r':
                                if (argc < 1)
                                        fatal("-r: missing revs/minute\n");
                                argc--, argv++;
                                rpm = atoi(*argv);
-                               if (rpm < 0)
+                               if (rpm <= 0)
                                        fatal("%s: bad revs/minute\n", *argv);
                                goto next;
 
                                        fatal("%s: bad revs/minute\n", *argv);
                                goto next;
 
-                       case 'i':
+                       case 's':
                                if (argc < 1)
                                if (argc < 1)
-                                       fatal("-i: missing bytes per inode\n");
+                                       fatal("-s: missing file system size");
                                argc--, argv++;
                                argc--, argv++;
-                               density = atoi(*argv);
-                               if (density < 0)
-                                       fatal("%s: bad bytes per inode\n",
+                               fssize = atoi(*argv);
+                               if (fssize <= 0)
+                                       fatal("%s: bad file system size",
                                                *argv);
                                goto next;
 
                                                *argv);
                                goto next;
 
+                       case 't':
+                               if (argc < 1)
+                                       fatal("-t: missing track total");
+                               argc--, argv++;
+                               ntracks = atoi(*argv);
+                               if (ntracks <= 0)
+                                       fatal("%s: bad total tracks", *argv);
+                               goto next;
+
                        default:
                                fatal("-%c: unknown flag", cp);
                        }
 next:
                argc--, argv++;
        }
                        default:
                                fatal("-%c: unknown flag", cp);
                        }
 next:
                argc--, argv++;
        }
-       if (argc < 2) {
-               fprintf(stderr, "usage: newfs [ -v ] [ mkfs-options ] %s\n",
-                       "special-device device-type");
-               fprintf(stderr, "where mkfs-options are:\n");
+       if (argc < 1) {
+               fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n");
+               fprintf(stderr, "where fsoptions are:\n");
                fprintf(stderr, "\t-N do not create file system, %s\n",
                        "just print out parameters");
                fprintf(stderr, "\t-s file system size (sectors)\n");
                fprintf(stderr, "\t-b block size\n");
                fprintf(stderr, "\t-f frag size\n");
                fprintf(stderr, "\t-N do not create file system, %s\n",
                        "just print out parameters");
                fprintf(stderr, "\t-s file system size (sectors)\n");
                fprintf(stderr, "\t-b block size\n");
                fprintf(stderr, "\t-f frag size\n");
+               fprintf(stderr, "\t-d sectors/track\n");
                fprintf(stderr, "\t-t tracks/cylinder\n");
                fprintf(stderr, "\t-c cylinders/group\n");
                fprintf(stderr, "\t-m minimum free space %%\n");
                fprintf(stderr, "\t-o optimization preference %s\n",
                        "(`space' or `time')");
                fprintf(stderr, "\t-r revolutions/minute\n");
                fprintf(stderr, "\t-t tracks/cylinder\n");
                fprintf(stderr, "\t-c cylinders/group\n");
                fprintf(stderr, "\t-m minimum free space %%\n");
                fprintf(stderr, "\t-o optimization preference %s\n",
                        "(`space' or `time')");
                fprintf(stderr, "\t-r revolutions/minute\n");
-               fprintf(stderr, "\t-S sector size\n");
                fprintf(stderr, "\t-i number of bytes per inode\n");
                fprintf(stderr, "\t-i number of bytes per inode\n");
+               fprintf(stderr, "\t-S sector size\n");
+               fprintf(stderr, "\t-a spare sectors per cylinder\n");
                exit(1);
        }
        special = argv[0];
                exit(1);
        }
        special = argv[0];
@@ -219,158 +278,207 @@ next:
        if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
                special++;
        special = sprintf(device, "/dev/r%s", special);
        if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
                special++;
        special = sprintf(device, "/dev/r%s", special);
-       if (stat(special, &st) < 0) {
+       if (!Nflag) {
+               fso = open(special, O_WRONLY);
+               if (fso < 0) {
+                       perror(special);
+                       exit(1);
+               }
+       } else
+               fso = -1;
+       fsi = open(special, O_RDONLY);
+       if (fsi < 0) {
+               perror(special);
+               exit(1);
+       }
+       if (fstat(fsi, &st) < 0) {
                fprintf(stderr, "newfs: "); perror(special);
                exit(2);
        }
        if ((st.st_mode & S_IFMT) != S_IFCHR)
                fatal("%s: not a character device", special);
                fprintf(stderr, "newfs: "); perror(special);
                exit(2);
        }
        if ((st.st_mode & S_IFMT) != S_IFCHR)
                fatal("%s: not a character device", special);
-       dp = getdiskbyname(argv[1]);
-       if (dp == 0)
-               fatal("%s: unknown disk type", argv[1]);
        cp = index(argv[0], '\0') - 1;
        cp = index(argv[0], '\0') - 1;
-       if (cp == 0 || *cp < 'a' || *cp > 'h')
+       if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
                fatal("%s: can't figure out file system partition", argv[0]);
                fatal("%s: can't figure out file system partition", argv[0]);
-       pp = &dp->d_partitions[*cp - 'a'];
-       if (fssize == 0) {
+       lp = getdisklabel(special, fsi);
+       if (isdigit(*cp))
+               pp = &lp->d_partitions[0];
+       else
+               pp = &lp->d_partitions[*cp - 'a'];
+       if (pp->p_size == 0)
+               fatal("%s: `%c' partition is unavailable", argv[0], *cp);
+       if (fssize == 0)
                fssize = pp->p_size;
                fssize = pp->p_size;
-               if (fssize < 0)
-                       fatal("%s: no default size for `%c' partition",
-                               argv[1], *cp);
-       }
-       if (nsectors == 0) {
-               nsectors = dp->d_nsectors;
-               if (nsectors < 0)
-                       fatal("%s: no default #sectors/track", argv[1]);
+       if (fssize > pp->p_size)
+              fatal("%s: maximum file system size on the `%c' partition is %d",
+                       argv[0], *cp, pp->p_size);
+       if (rpm == 0) {
+               rpm = lp->d_rpm;
+               if (rpm <= 0)
+                       fatal("%s: no default rpm", argv[1]);
        }
        if (ntracks == 0) {
        }
        if (ntracks == 0) {
-               ntracks = dp->d_ntracks;
-               if (ntracks < 0)
+               ntracks = lp->d_ntracks;
+               if (ntracks <= 0)
                        fatal("%s: no default #tracks", argv[1]);
        }
                        fatal("%s: no default #tracks", argv[1]);
        }
+       if (nsectors == 0) {
+               nsectors = lp->d_nsectors;
+               if (nsectors <= 0)
+                       fatal("%s: no default #sectors/track", argv[1]);
+       }
        if (sectorsize == 0) {
        if (sectorsize == 0) {
-               sectorsize = dp->d_secsize;
-               if (sectorsize < 0)
+               sectorsize = lp->d_secsize;
+               if (sectorsize <= 0)
                        fatal("%s: no default sector size", argv[1]);
        }
                        fatal("%s: no default sector size", argv[1]);
        }
-       if (bsize == 0) {
-               bsize = pp->p_bsize;
-               if (bsize < 0)
-                       fatal("%s: no default block size for `%c' partition",
-                               argv[1], *cp);
-       }
        if (fsize == 0) {
                fsize = pp->p_fsize;
        if (fsize == 0) {
                fsize = pp->p_fsize;
-               if (fsize < 0)
-                       fatal("%s: no default frag size for `%c' partition",
-                               argv[1], *cp);
+               if (fsize <= 0)
+                       fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
        }
        }
-       if (rpm == 0) {
-               rpm = dp->d_rpm;
-               if (rpm < 0)
-                       fatal("%s: no default revolutions/minute value",
-                               argv[1]);
+       if (bsize == 0) {
+               bsize = pp->p_frag * pp->p_fsize;
+               if (bsize <= 0)
+                       bsize = MIN(DFL_BLKSIZE, 8 * fsize);
        }
        }
-       if (density <= 0)
-               density = 2048;
-       if (minfree < 0)
-               minfree = 10;
        if (minfree < 10 && opt != FS_OPTSPACE) {
        if (minfree < 10 && opt != FS_OPTSPACE) {
-               fprintf(stderr, "setting optimization for space ");
-               fprintf(stderr, "with minfree less than 10%\n");
+               fprintf(stderr, "Warning: changing optimization to space ");
+               fprintf(stderr, "because minfree is less than 10%%\n");
                opt = FS_OPTSPACE;
        }
                opt = FS_OPTSPACE;
        }
-       if (cpg == 0)
-               cpg = 16;
-       i = 0;
-       if (Nflag)
-               av[i++] = "-N";
-       av[i++] = special;
-       av[i++] = sprintf(a2, "%d", fssize);
-       av[i++] = sprintf(a3, "%d", nsectors);
-       av[i++] = sprintf(a4, "%d", ntracks);
-       av[i++] = sprintf(a5, "%d", bsize);
-       av[i++] = sprintf(a6, "%d", fsize);
-       av[i++] = sprintf(a7, "%d", cpg);
-       av[i++] = sprintf(a8, "%d", minfree);
-       av[i++] = sprintf(a9, "%d", rpm / 60);
-       av[i++] = sprintf(a10, "%d", density);
-       av[i++] = opt == FS_OPTSPACE ? "s" : "t";
-       av[i++] = 0;
-       strcpy(cmd, "/etc/mkfs");
-       for (i = 0; av[i] != 0; i++) {
-               strcat(cmd, " ");
-               strcat(cmd, av[i]);
-       }
-       if (verbose)
-               printf("%s\n", cmd);
-       if (status = system(cmd))
-               exit(status >> 8);
-       if (*cp == 'a' && !noboot) {
-               char type[3];
-               struct stat sb;
-
-               cp = rindex(special, '/');
-               if (cp == NULL)
-                       fatal("%s: can't figure out disk type from name",
-                               special);
-               if (stat(special, &sb) >= 0 && (sb.st_mode & S_IFMT) == S_IFCHR)
-                       cp++;
-               type[0] = *++cp;
-               type[1] = *++cp;
-               type[2] = '\0';
-               installboot(special, type);
-       }
+       if (nspares == -1)
+               nspares = lp->d_sparespercyl;
+       secpercyl = nsectors * ntracks - nspares;
+       if (secpercyl != lp->d_secpercyl)
+               fprintf(stderr, "%s (%d) %s (%d)\n",
+                       "Warning: calculated sectors per cylinder", secpercyl,
+                       "disagrees with disk label", lp->d_secpercyl);
+       oldpartition = *pp;
+       mkfs(pp, special, fsi, fso);
+       if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
+               rewritelabel(special, fso, lp);
        exit(0);
 }
 
        exit(0);
 }
 
-installboot(dev, type)
-       char *dev, *type;
+#ifdef byioctl
+struct disklabel *
+getdisklabel(s, fd)
+       char *s;
+       int     fd;
 {
 {
-#ifdef BOOTDIR
+       static struct disklabel lab;
+
+       if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
+               perror("ioctl (GDINFO)");
+               fatal("%s: can't read disk label", s);
+       }
+       return (&lab);
+}
+
+rewritelabel(s, fd, lp)
+       char *s;
        int fd;
        int fd;
-       char bootblock[MAXPATHLEN], standalonecode[MAXPATHLEN];
-       char bootimage[BBSIZE];
-
-       sprintf(bootblock, "%s/%sboot", BOOTDIR, type);
-       sprintf(standalonecode, "%s/boot%s", BOOTDIR, type);
-       if (verbose) {
-               printf("installing boot code\n");
-               printf("sector 0 boot = %s\n", bootblock);
-               printf("1st level boot = %s\n", standalonecode);
+       register struct disklabel *lp;
+{
+
+       lp->d_checksum = 0;
+       lp->d_checksum = dkcksum(lp);
+       if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
+               perror("ioctl (GWINFO)");
+               fatal("%s: can't rewrite disk label", s);
        }
        }
-       fd = open(bootblock, 0);
-       if (fd < 0) {
-               fprintf(stderr, "newfs: "); perror(bootblock);
-               exit(1);
+}
+#else byioctl
+char specname[64];
+char boot[BBSIZE];
+
+struct disklabel *
+getdisklabel(s, fd)
+       char *s;
+       int     fd;
+{
+       char *cp;
+       u_long magic = htonl(DISKMAGIC);
+       register struct disklabel *lp;
+       int cfd;
+
+       /*
+        * Make name for 'c' partition.
+        */
+       strcpy(specname, s);
+       cp = specname + strlen(specname) - 1;
+       if (!isdigit(*cp))
+               *cp = 'c';
+       cfd = open(specname, O_RDONLY);
+       if (cfd < 0) {
+               perror(specname);
+               exit(2);
        }
        }
-       if (read(fd, bootimage, DEV_BSIZE) < 0) {
-               fprintf(stderr, "newfs: "); perror(bootblock);
+
+       if (read(cfd, boot, BBSIZE) < BBSIZE) {
+               perror(specname);
                exit(2);
        }
                exit(2);
        }
-       close(fd);
-       fd = open(standalonecode, 0);
-       if (fd < 0) {
-               fprintf(stderr, "newfs: "); perror(standalonecode);
+       close(cfd);
+       for (lp = (struct disklabel *)(boot + LABELOFFSET);
+           lp <= (struct disklabel *)(boot + BBSIZE -
+           sizeof(struct disklabel));
+           lp = (struct disklabel *)((char *)lp + 128))
+               if (lp->d_magic == magic && lp->d_magic2 == magic)
+                       break;
+       if (lp > (struct disklabel *)(boot + BBSIZE -
+           sizeof(struct disklabel)) ||
+           lp->d_magic != magic || lp->d_magic2 != magic ||
+           dkcksum(lp) != 0) {
+               fprintf(stderr,
+       "Bad pack magic number (label is damaged, or pack is unlabeled)\n");
                exit(1);
        }
                exit(1);
        }
-       if (read(fd, &bootimage[DEV_BSIZE], BBSIZE - DEV_BSIZE) < 0) {
-               fprintf(stderr, "newfs: "); perror(standalonecode);
+#if ENDIAN != BIG
+       swablabel(lp);
+#endif
+       return (lp);
+}
+
+rewritelabel(s, fd, lp)
+       char *s;
+       int fd;
+       register struct disklabel *lp;
+{
+       daddr_t alt;
+       register i;
+       int secsize, cfd;
+
+       secsize = lp->d_secsize;
+       alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
+#if ENDIAN != BIG
+       swablabel(lp);
+#endif
+       lp->d_checksum = 0;
+       lp->d_checksum = dkcksum(lp);
+       cfd = open(specname, O_WRONLY);
+       if (cfd < 0) {
+               perror(specname);
                exit(2);
        }
                exit(2);
        }
-       close(fd);
-       fd = open(dev, 1);
-       if (fd < 0) {
-               fprintf(stderr, "newfs: "); perror(dev);
-               exit(1);
-       }
-       if (write(fd, bootimage, BBSIZE) != BBSIZE) {
-               fprintf(stderr, "newfs: "); perror(dev);
+       lseek(cfd, (off_t)0, L_SET);
+       if (write(cfd, boot, BBSIZE) < BBSIZE) {
+               perror(specname);
                exit(2);
        }
                exit(2);
        }
-       close(fd);
-#endif
+       for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
+               lseek(cfd, (off_t)(alt + i) * secsize, L_SET);
+               if (write(cfd, boot, secsize) < secsize) {
+                       int oerrno = errno;
+                       fprintf(stderr, "alternate label %d ", i/2);
+                       errno = oerrno;
+                       perror("write");
+               }
+       }
+       close(cfd);
 }
 }
+#endif byioctl
 
 /*VARARGS*/
 fatal(fmt, arg1, arg2)
 
 /*VARARGS*/
 fatal(fmt, arg1, arg2)