Home | History | Annotate | Line # | Download | only in newfs
newfs.c revision 1.13
      1 /*
      2  * Copyright (c) 1983, 1989, 1993, 1994
      3  *	The Regents of the University of California.  All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. All advertising materials mentioning features or use of this software
     14  *    must display the following acknowledgement:
     15  *	This product includes software developed by the University of
     16  *	California, Berkeley and its contributors.
     17  * 4. Neither the name of the University nor the names of its contributors
     18  *    may be used to endorse or promote products derived from this software
     19  *    without specific prior written permission.
     20  *
     21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     31  * SUCH DAMAGE.
     32  */
     33 
     34 #ifndef lint
     35 static char copyright[] =
     36 "@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
     37 	The Regents of the University of California.  All rights reserved.\n";
     38 #endif /* not lint */
     39 
     40 #ifndef lint
     41 /*static char sccsid[] = "from: @(#)newfs.c	8.8 (Berkeley) 4/18/94";*/
     42 static char *rcsid = "$Id: newfs.c,v 1.13 1994/12/01 18:46:38 mycroft Exp $";
     43 #endif /* not lint */
     44 
     45 /*
     46  * newfs: friendly front end to mkfs
     47  */
     48 #include <sys/param.h>
     49 #include <sys/stat.h>
     50 #include <sys/ioctl.h>
     51 #include <sys/disklabel.h>
     52 #include <sys/file.h>
     53 #include <sys/mount.h>
     54 
     55 #include <ufs/ufs/dir.h>
     56 #include <ufs/ffs/fs.h>
     57 
     58 #include <ctype.h>
     59 #include <errno.h>
     60 #include <paths.h>
     61 #include <stdio.h>
     62 #include <stdlib.h>
     63 #include <string.h>
     64 #include <syslog.h>
     65 #include <unistd.h>
     66 
     67 #if __STDC__
     68 #include <stdarg.h>
     69 #else
     70 #include <varargs.h>
     71 #endif
     72 
     73 #include "mntopts.h"
     74 
     75 struct mntopt mopts[] = {
     76 	MOPT_STDOPTS,
     77 	MOPT_ASYNC,
     78 	{ NULL },
     79 };
     80 
     81 #if __STDC__
     82 void	fatal(const char *fmt, ...);
     83 #else
     84 void	fatal();
     85 #endif
     86 
     87 #define	COMPAT			/* allow non-labeled disks */
     88 
     89 /*
     90  * The following two constants set the default block and fragment sizes.
     91  * Both constants must be a power of 2 and meet the following constraints:
     92  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
     93  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
     94  *	DESBLKSIZE / DESFRAGSIZE <= 8
     95  */
     96 #define	DFL_FRAGSIZE	1024
     97 #define	DFL_BLKSIZE	8192
     98 
     99 /*
    100  * Cylinder groups may have up to many cylinders. The actual
    101  * number used depends upon how much information can be stored
    102  * on a single cylinder. The default is to use 16 cylinders
    103  * per group.
    104  */
    105 #define	DESCPG		16	/* desired fs_cpg */
    106 
    107 /*
    108  * ROTDELAY gives the minimum number of milliseconds to initiate
    109  * another disk transfer on the same cylinder. It is used in
    110  * determining the rotationally optimal layout for disk blocks
    111  * within a file; the default of fs_rotdelay is 0ms.
    112  */
    113 #define ROTDELAY	0
    114 
    115 /*
    116  * MAXBLKPG determines the maximum number of data blocks which are
    117  * placed in a single cylinder group. The default is one indirect
    118  * block worth of data blocks.
    119  */
    120 #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
    121 
    122 /*
    123  * Each file system has a number of inodes statically allocated.
    124  * We allocate one inode slot per NFPI fragments, expecting this
    125  * to be far more than we will ever need.
    126  */
    127 #define	NFPI		4
    128 
    129 /*
    130  * For each cylinder we keep track of the availability of blocks at different
    131  * rotational positions, so that we can lay out the data to be picked
    132  * up with minimum rotational latency.  NRPOS is the default number of
    133  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
    134  * of our summary information is 2ms for a typical 3600 rpm drive.  Caching
    135  * and zoning pretty much defeats rotational optimization, so we now use a
    136  * default of 1.
    137  */
    138 #define	NRPOS		1	/* number distinct rotational positions */
    139 
    140 
    141 int	mfs;			/* run as the memory based filesystem */
    142 int	Nflag;			/* run without writing file system */
    143 int	Oflag;			/* format as an 4.3BSD file system */
    144 int	fssize;			/* file system size */
    145 int	ntracks;		/* # tracks/cylinder */
    146 int	nsectors;		/* # sectors/track */
    147 int	nphyssectors;		/* # sectors/track including spares */
    148 int	secpercyl;		/* sectors per cylinder */
    149 int	trackspares = -1;	/* spare sectors per track */
    150 int	cylspares = -1;		/* spare sectors per cylinder */
    151 int	sectorsize;		/* bytes/sector */
    152 #ifdef tahoe
    153 int	realsectorsize;		/* bytes/sector in hardware */
    154 #endif
    155 int	rpm;			/* revolutions/minute of drive */
    156 int	interleave;		/* hardware sector interleave */
    157 int	trackskew = -1;		/* sector 0 skew, per track */
    158 int	headswitch;		/* head switch time, usec */
    159 int	trackseek;		/* track-to-track seek, usec */
    160 int	fsize = 0;		/* fragment size */
    161 int	bsize = 0;		/* block size */
    162 int	cpg = DESCPG;		/* cylinders/cylinder group */
    163 int	cpgflg;			/* cylinders/cylinder group flag was given */
    164 int	minfree = MINFREE;	/* free space threshold */
    165 int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
    166 int	density;		/* number of bytes per inode */
    167 int	maxcontig = 8;		/* max contiguous blocks to allocate */
    168 int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
    169 int	maxbpg;			/* maximum blocks per file in a cyl group */
    170 int	nrpos = NRPOS;		/* # of distinguished rotational positions */
    171 int	bbsize = BBSIZE;	/* boot block size */
    172 int	sbsize = SBSIZE;	/* superblock size */
    173 int	mntflags = MNT_ASYNC;	/* flags to be passed to mount */
    174 u_long	memleft;		/* virtual memory available */
    175 caddr_t	membase;		/* start address of memory based filesystem */
    176 #ifdef COMPAT
    177 char	*disktype;
    178 int	unlabeled;
    179 #endif
    180 
    181 char	device[MAXPATHLEN];
    182 char	*progname;
    183 
    184 int
    185 main(argc, argv)
    186 	int argc;
    187 	char *argv[];
    188 {
    189 	extern char *optarg;
    190 	extern int optind;
    191 	register int ch;
    192 	register struct partition *pp;
    193 	register struct disklabel *lp;
    194 	struct disklabel *getdisklabel();
    195 	struct partition oldpartition;
    196 	struct stat st;
    197 	struct statfs *mp;
    198 	int fsi, fso, len, n;
    199 	char *cp, *s1, *s2, *special, *opstring, buf[BUFSIZ];
    200 
    201 	if (progname = strrchr(*argv, '/'))
    202 		++progname;
    203 	else
    204 		progname = *argv;
    205 
    206 	if (strstr(progname, "mfs")) {
    207 		mfs = 1;
    208 		Nflag++;
    209 	}
    210 
    211 	opstring = mfs ?
    212 	    "NT:a:b:c:d:e:f:i:m:o:s:" :
    213 	    "NOS:T:a:b:c:d:e:f:i:k:l:m:n:o:p:r:s:t:u:x:";
    214 	while ((ch = getopt(argc, argv, opstring)) != EOF)
    215 		switch (ch) {
    216 		case 'N':
    217 			Nflag = 1;
    218 			break;
    219 		case 'O':
    220 			Oflag = 1;
    221 			break;
    222 		case 'S':
    223 			if ((sectorsize = atoi(optarg)) <= 0)
    224 				fatal("%s: bad sector size", optarg);
    225 			break;
    226 #ifdef COMPAT
    227 		case 'T':
    228 			disktype = optarg;
    229 			break;
    230 #endif
    231 		case 'a':
    232 			if ((maxcontig = atoi(optarg)) <= 0)
    233 				fatal("%s: bad maximum contiguous blocks\n",
    234 				    optarg);
    235 			break;
    236 		case 'b':
    237 			if ((bsize = atoi(optarg)) < MINBSIZE)
    238 				fatal("%s: bad block size", optarg);
    239 			break;
    240 		case 'c':
    241 			if ((cpg = atoi(optarg)) <= 0)
    242 				fatal("%s: bad cylinders/group", optarg);
    243 			cpgflg++;
    244 			break;
    245 		case 'd':
    246 			if ((rotdelay = atoi(optarg)) < 0)
    247 				fatal("%s: bad rotational delay\n", optarg);
    248 			break;
    249 		case 'e':
    250 			if ((maxbpg = atoi(optarg)) <= 0)
    251 		fatal("%s: bad blocks per file in a cylinder group\n",
    252 				    optarg);
    253 			break;
    254 		case 'f':
    255 			if ((fsize = atoi(optarg)) <= 0)
    256 				fatal("%s: bad fragment size", optarg);
    257 			break;
    258 		case 'i':
    259 			if ((density = atoi(optarg)) <= 0)
    260 				fatal("%s: bad bytes per inode\n", optarg);
    261 			break;
    262 		case 'k':
    263 			if ((trackskew = atoi(optarg)) < 0)
    264 				fatal("%s: bad track skew", optarg);
    265 			break;
    266 		case 'l':
    267 			if ((interleave = atoi(optarg)) <= 0)
    268 				fatal("%s: bad interleave", optarg);
    269 			break;
    270 		case 'm':
    271 			if ((minfree = atoi(optarg)) < 0 || minfree > 99)
    272 				fatal("%s: bad free space %%\n", optarg);
    273 			break;
    274 		case 'n':
    275 			if ((nrpos = atoi(optarg)) <= 0)
    276 				fatal("%s: bad rotational layout count\n",
    277 				    optarg);
    278 			break;
    279 		case 'o':
    280 			if (mfs)
    281 				getmntopts(optarg, mopts, &mntflags);
    282 			else {
    283 				if (strcmp(optarg, "space") == 0)
    284 					opt = FS_OPTSPACE;
    285 				else if (strcmp(optarg, "time") == 0)
    286 					opt = FS_OPTTIME;
    287 				else
    288 	fatal("%s: unknown optimization preference: use `space' or `time'.");
    289 			}
    290 			break;
    291 		case 'p':
    292 			if ((trackspares = atoi(optarg)) < 0)
    293 				fatal("%s: bad spare sectors per track",
    294 				    optarg);
    295 			break;
    296 		case 'r':
    297 			if ((rpm = atoi(optarg)) <= 0)
    298 				fatal("%s: bad revolutions/minute\n", optarg);
    299 			break;
    300 		case 's':
    301 			if ((fssize = atoi(optarg)) <= 0)
    302 				fatal("%s: bad file system size", optarg);
    303 			break;
    304 		case 't':
    305 			if ((ntracks = atoi(optarg)) <= 0)
    306 				fatal("%s: bad total tracks", optarg);
    307 			break;
    308 		case 'u':
    309 			if ((nsectors = atoi(optarg)) <= 0)
    310 				fatal("%s: bad sectors/track", optarg);
    311 			break;
    312 		case 'x':
    313 			if ((cylspares = atoi(optarg)) < 0)
    314 				fatal("%s: bad spare sectors per cylinder",
    315 				    optarg);
    316 			break;
    317 		case '?':
    318 		default:
    319 			usage();
    320 		}
    321 	argc -= optind;
    322 	argv += optind;
    323 
    324 	if (argc != 2 && (mfs || argc != 1))
    325 		usage();
    326 
    327 	special = argv[0];
    328 	cp = strrchr(special, '/');
    329 	if (cp == 0) {
    330 		/*
    331 		 * No path prefix; try /dev/r%s then /dev/%s.
    332 		 */
    333 		(void)sprintf(device, "%sr%s", _PATH_DEV, special);
    334 		if (stat(device, &st) == -1)
    335 			(void)sprintf(device, "%s%s", _PATH_DEV, special);
    336 		special = device;
    337 	}
    338 	if (Nflag) {
    339 		fso = -1;
    340 	} else {
    341 		fso = open(special, O_WRONLY);
    342 		if (fso < 0)
    343 			fatal("%s: %s", special, strerror(errno));
    344 
    345 		/* Bail if target special is mounted */
    346 		n = getmntinfo(&mp, MNT_NOWAIT);
    347 		if (n == 0)
    348 			fatal("%s: getmntinfo: %s", special, strerror(errno));
    349 
    350 		len = sizeof(_PATH_DEV) - 1;
    351 		s1 = special;
    352 		if (strncmp(_PATH_DEV, s1, len) == 0)
    353 			s1 += len;
    354 
    355 		while (--n >= 0) {
    356 			s2 = mp->f_mntfromname;
    357 			if (strncmp(_PATH_DEV, s2, len) == 0) {
    358 				s2 += len - 1;
    359 				*s2 = 'r';
    360 			}
    361 			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
    362 				fatal("%s is mounted on %s",
    363 				    special, mp->f_mntonname);
    364 			++mp;
    365 		}
    366 	}
    367 	if (mfs && disktype != NULL) {
    368 		lp = (struct disklabel *)getdiskbyname(disktype);
    369 		if (lp == NULL)
    370 			fatal("%s: unknown disk type", disktype);
    371 		pp = &lp->d_partitions[1];
    372 	} else {
    373 		fsi = open(special, O_RDONLY);
    374 		if (fsi < 0)
    375 			fatal("%s: %s", special, strerror(errno));
    376 		if (fstat(fsi, &st) < 0)
    377 			fatal("%s: %s", special, strerror(errno));
    378 		if ((st.st_mode & S_IFMT) != S_IFCHR && !mfs)
    379 			printf("%s: %s: not a character-special device\n",
    380 			    progname, special);
    381 		cp = strchr(argv[0], '\0') - 1;
    382 		if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
    383 			fatal("%s: can't figure out file system partition",
    384 			    argv[0]);
    385 #ifdef COMPAT
    386 		if (!mfs && disktype == NULL)
    387 			disktype = argv[1];
    388 #endif
    389 		lp = getdisklabel(special, fsi);
    390 		if (isdigit(*cp))
    391 			pp = &lp->d_partitions[0];
    392 		else
    393 			pp = &lp->d_partitions[*cp - 'a'];
    394 		if (pp->p_size == 0)
    395 			fatal("%s: `%c' partition is unavailable",
    396 			    argv[0], *cp);
    397 		if (pp->p_fstype == FS_BOOT)
    398 			fatal("%s: `%c' partition overlaps boot program",
    399 			      argv[0], *cp);
    400 	}
    401 	if (fssize == 0)
    402 		fssize = pp->p_size;
    403 	if (fssize > pp->p_size && !mfs)
    404 	       fatal("%s: maximum file system size on the `%c' partition is %d",
    405 			argv[0], *cp, pp->p_size);
    406 	if (rpm == 0) {
    407 		rpm = lp->d_rpm;
    408 		if (rpm <= 0)
    409 			rpm = 3600;
    410 	}
    411 	if (ntracks == 0) {
    412 		ntracks = lp->d_ntracks;
    413 		if (ntracks <= 0)
    414 			fatal("%s: no default #tracks", argv[0]);
    415 	}
    416 	if (nsectors == 0) {
    417 		nsectors = lp->d_nsectors;
    418 		if (nsectors <= 0)
    419 			fatal("%s: no default #sectors/track", argv[0]);
    420 	}
    421 	if (sectorsize == 0) {
    422 		sectorsize = lp->d_secsize;
    423 		if (sectorsize <= 0)
    424 			fatal("%s: no default sector size", argv[0]);
    425 	}
    426 	if (trackskew == -1) {
    427 		trackskew = lp->d_trackskew;
    428 		if (trackskew < 0)
    429 			trackskew = 0;
    430 	}
    431 	if (interleave == 0) {
    432 		interleave = lp->d_interleave;
    433 		if (interleave <= 0)
    434 			interleave = 1;
    435 	}
    436 	if (fsize == 0) {
    437 		fsize = pp->p_fsize;
    438 		if (fsize <= 0)
    439 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
    440 	}
    441 	if (bsize == 0) {
    442 		bsize = pp->p_frag * pp->p_fsize;
    443 		if (bsize <= 0)
    444 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
    445 	}
    446 	/*
    447 	 * Maxcontig sets the default for the maximum number of blocks
    448 	 * that may be allocated sequentially. With filesystem clustering
    449 	 * it is possible to allocate contiguous blocks up to the maximum
    450 	 * transfer size permitted by the controller or buffering.
    451 	 */
    452 	if (maxcontig == 0)
    453 		maxcontig = MAX(1, MIN(MAXPHYS, MAXBSIZE) / bsize - 1);
    454 	if (density == 0)
    455 		density = NFPI * fsize;
    456 	if (minfree < MINFREE && opt != FS_OPTSPACE) {
    457 		fprintf(stderr, "Warning: changing optimization to space ");
    458 		fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
    459 		opt = FS_OPTSPACE;
    460 	}
    461 	if (trackspares == -1) {
    462 		trackspares = lp->d_sparespertrack;
    463 		if (trackspares < 0)
    464 			trackspares = 0;
    465 	}
    466 	nphyssectors = nsectors + trackspares;
    467 	if (cylspares == -1) {
    468 		cylspares = lp->d_sparespercyl;
    469 		if (cylspares < 0)
    470 			cylspares = 0;
    471 	}
    472 	secpercyl = nsectors * ntracks - cylspares;
    473 	if (secpercyl != lp->d_secpercyl)
    474 		fprintf(stderr, "%s (%d) %s (%lu)\n",
    475 			"Warning: calculated sectors per cylinder", secpercyl,
    476 			"disagrees with disk label", lp->d_secpercyl);
    477 	if (maxbpg == 0)
    478 		maxbpg = MAXBLKPG(bsize);
    479 	headswitch = lp->d_headswitch;
    480 	trackseek = lp->d_trkseek;
    481 #ifdef notdef /* label may be 0 if faked up by kernel */
    482 	bbsize = lp->d_bbsize;
    483 	sbsize = lp->d_sbsize;
    484 #endif
    485 	oldpartition = *pp;
    486 #ifdef tahoe
    487 	realsectorsize = sectorsize;
    488 	if (sectorsize != DEV_BSIZE) {		/* XXX */
    489 		int secperblk = DEV_BSIZE / sectorsize;
    490 
    491 		sectorsize = DEV_BSIZE;
    492 		nsectors /= secperblk;
    493 		nphyssectors /= secperblk;
    494 		secpercyl /= secperblk;
    495 		fssize /= secperblk;
    496 		pp->p_size /= secperblk;
    497 	}
    498 #endif
    499 	mkfs(pp, special, fsi, fso);
    500 #ifdef tahoe
    501 	if (realsectorsize != DEV_BSIZE)
    502 		pp->p_size *= DEV_BSIZE / realsectorsize;
    503 #endif
    504 	if (!Nflag && memcmp(pp, &oldpartition, sizeof(oldpartition)))
    505 		rewritelabel(special, fso, lp);
    506 	if (!Nflag)
    507 		close(fso);
    508 	close(fsi);
    509 #ifdef MFS
    510 	if (mfs) {
    511 		struct mfs_args args;
    512 
    513 		sprintf(buf, "mfs:%d", getpid());
    514 		args.fspec = buf;
    515 		args.export.ex_root = -2;
    516 		if (mntflags & MNT_RDONLY)
    517 			args.export.ex_flags = MNT_EXRDONLY;
    518 		else
    519 			args.export.ex_flags = 0;
    520 		args.base = membase;
    521 		args.size = fssize * sectorsize;
    522 		if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0)
    523 			fatal("%s: %s", argv[1], strerror(errno));
    524 	}
    525 #endif
    526 	exit(0);
    527 }
    528 
    529 #ifdef COMPAT
    530 char lmsg[] = "%s: can't read disk label; disk type must be specified";
    531 #else
    532 char lmsg[] = "%s: can't read disk label";
    533 #endif
    534 
    535 struct disklabel *
    536 getdisklabel(s, fd)
    537 	char *s;
    538 	int fd;
    539 {
    540 	static struct disklabel lab;
    541 
    542 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
    543 #ifdef COMPAT
    544 		if (disktype) {
    545 			struct disklabel *lp, *getdiskbyname();
    546 
    547 			unlabeled++;
    548 			lp = getdiskbyname(disktype);
    549 			if (lp == NULL)
    550 				fatal("%s: unknown disk type", disktype);
    551 			return (lp);
    552 		}
    553 #endif
    554 		warn("ioctl (GDINFO)");
    555 		fatal(lmsg, s);
    556 	}
    557 	return (&lab);
    558 }
    559 
    560 rewritelabel(s, fd, lp)
    561 	char *s;
    562 	int fd;
    563 	register struct disklabel *lp;
    564 {
    565 #ifdef COMPAT
    566 	if (unlabeled)
    567 		return;
    568 #endif
    569 	lp->d_checksum = 0;
    570 	lp->d_checksum = dkcksum(lp);
    571 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
    572 		warn("ioctl (WDINFO)");
    573 		fatal("%s: can't rewrite disk label", s);
    574 	}
    575 #if vax
    576 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
    577 		register i;
    578 		int cfd;
    579 		daddr_t alt;
    580 		char specname[64];
    581 		char blk[1024];
    582 		char *cp;
    583 
    584 		/*
    585 		 * Make name for 'c' partition.
    586 		 */
    587 		strcpy(specname, s);
    588 		cp = specname + strlen(specname) - 1;
    589 		if (!isdigit(*cp))
    590 			*cp = 'c';
    591 		cfd = open(specname, O_WRONLY);
    592 		if (cfd < 0)
    593 			fatal("%s: %s", specname, strerror(errno));
    594 		memset(blk, 0, sizeof(blk));
    595 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
    596 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
    597 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
    598 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize,
    599 			    L_SET) == -1)
    600 				fatal("lseek to badsector area: %s",
    601 				    strerror(errno));
    602 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize)
    603 				warn("alternate label %d write", i/2);
    604 		}
    605 		close(cfd);
    606 	}
    607 #endif
    608 }
    609 
    610 /*VARARGS*/
    611 void
    612 #if __STDC__
    613 fatal(const char *fmt, ...)
    614 #else
    615 fatal(fmt, va_alist)
    616 	char *fmt;
    617 	va_dcl
    618 #endif
    619 {
    620 	va_list ap;
    621 
    622 #if __STDC__
    623 	va_start(ap, fmt);
    624 #else
    625 	va_start(ap);
    626 #endif
    627 	if (fcntl(STDERR_FILENO, F_GETFL) < 0) {
    628 		openlog(progname, LOG_CONS, LOG_DAEMON);
    629 		vsyslog(LOG_ERR, fmt, ap);
    630 		closelog();
    631 	} else {
    632 		vwarnx(fmt, ap);
    633 	}
    634 	va_end(ap);
    635 	exit(1);
    636 	/*NOTREACHED*/
    637 }
    638 
    639 usage()
    640 {
    641 	if (mfs) {
    642 		fprintf(stderr,
    643 		    "usage: %s [ -fsoptions ] special-device mount-point\n",
    644 			progname);
    645 	} else
    646 		fprintf(stderr,
    647 		    "usage: %s [ -fsoptions ] special-device%s\n",
    648 		    progname,
    649 #ifdef COMPAT
    650 		    " [device-type]");
    651 #else
    652 		    "");
    653 #endif
    654 	fprintf(stderr, "where fsoptions are:\n");
    655 	fprintf(stderr,
    656 	    "\t-N do not create file system, just print out parameters\n");
    657 	fprintf(stderr, "\t-O create a 4.3BSD format filesystem\n");
    658 	fprintf(stderr, "\t-S sector size\n");
    659 #ifdef COMPAT
    660 	fprintf(stderr, "\t-T disktype\n");
    661 #endif
    662 	fprintf(stderr, "\t-a maximum contiguous blocks\n");
    663 	fprintf(stderr, "\t-b block size\n");
    664 	fprintf(stderr, "\t-c cylinders/group\n");
    665 	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
    666 	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
    667 	fprintf(stderr, "\t-f frag size\n");
    668 	fprintf(stderr, "\t-i number of bytes per inode\n");
    669 	fprintf(stderr, "\t-k sector 0 skew, per track\n");
    670 	fprintf(stderr, "\t-l hardware sector interleave\n");
    671 	fprintf(stderr, "\t-m minimum free space %%\n");
    672 	fprintf(stderr, "\t-n number of distinguished rotational positions\n");
    673 	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
    674 	fprintf(stderr, "\t-p spare sectors per track\n");
    675 	fprintf(stderr, "\t-s file system size (sectors)\n");
    676 	fprintf(stderr, "\t-r revolutions/minute\n");
    677 	fprintf(stderr, "\t-t tracks/cylinder\n");
    678 	fprintf(stderr, "\t-u sectors/track\n");
    679 	fprintf(stderr, "\t-x spare sectors per cylinder\n");
    680 	exit(1);
    681 }
    682