newfs.c revision 92711
11558Srgrimes/*
21558Srgrimes * Copyright (c) 1983, 1989, 1993, 1994
31558Srgrimes *	The Regents of the University of California.  All rights reserved.
41558Srgrimes *
51558Srgrimes * Redistribution and use in source and binary forms, with or without
61558Srgrimes * modification, are permitted provided that the following conditions
71558Srgrimes * are met:
81558Srgrimes * 1. Redistributions of source code must retain the above copyright
91558Srgrimes *    notice, this list of conditions and the following disclaimer.
101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright
111558Srgrimes *    notice, this list of conditions and the following disclaimer in the
121558Srgrimes *    documentation and/or other materials provided with the distribution.
131558Srgrimes * 3. All advertising materials mentioning features or use of this software
141558Srgrimes *    must display the following acknowledgement:
151558Srgrimes *	This product includes software developed by the University of
161558Srgrimes *	California, Berkeley and its contributors.
171558Srgrimes * 4. Neither the name of the University nor the names of its contributors
181558Srgrimes *    may be used to endorse or promote products derived from this software
191558Srgrimes *    without specific prior written permission.
201558Srgrimes *
211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
241558Srgrimes * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
311558Srgrimes * SUCH DAMAGE.
321558Srgrimes */
331558Srgrimes
341558Srgrimes#ifndef lint
3537664Scharnierstatic const char copyright[] =
3637664Scharnier"@(#) Copyright (c) 1983, 1989, 1993, 1994\n\
3737664Scharnier	The Regents of the University of California.  All rights reserved.\n";
381558Srgrimes#endif /* not lint */
391558Srgrimes
401558Srgrimes#ifndef lint
4137664Scharnier#if 0
4237664Scharnierstatic char sccsid[] = "@(#)newfs.c	8.13 (Berkeley) 5/1/95";
4337664Scharnier#endif
4437664Scharnierstatic const char rcsid[] =
4550476Speter  "$FreeBSD: head/sbin/newfs/newfs.c 92711 2002-03-19 17:20:02Z iedowse $";
461558Srgrimes#endif /* not lint */
471558Srgrimes
481558Srgrimes/*
491558Srgrimes * newfs: friendly front end to mkfs
501558Srgrimes */
511558Srgrimes#include <sys/param.h>
521558Srgrimes#include <sys/stat.h>
531558Srgrimes#include <sys/disklabel.h>
541558Srgrimes#include <sys/file.h>
551558Srgrimes#include <sys/mount.h>
561558Srgrimes
5737707Scharnier#include <ufs/ufs/dir.h>
5837707Scharnier#include <ufs/ufs/dinode.h>
591558Srgrimes#include <ufs/ffs/fs.h>
6023682Speter#include <ufs/ufs/ufsmount.h>
611558Srgrimes
621558Srgrimes#include <ctype.h>
6337664Scharnier#include <err.h>
641558Srgrimes#include <errno.h>
651558Srgrimes#include <paths.h>
661558Srgrimes#include <stdio.h>
671558Srgrimes#include <stdlib.h>
681558Srgrimes#include <string.h>
691558Srgrimes#include <syslog.h>
701558Srgrimes#include <unistd.h>
711558Srgrimes
721558Srgrimes#include <stdarg.h>
731558Srgrimes
7481911Skrisvoid	fatal(const char *fmt, ...) __printflike(1, 2);
751558Srgrimes
761558Srgrimes#define	COMPAT			/* allow non-labeled disks */
771558Srgrimes
781558Srgrimes/*
791558Srgrimes * The following two constants set the default block and fragment sizes.
801558Srgrimes * Both constants must be a power of 2 and meet the following constraints:
811558Srgrimes *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
821558Srgrimes *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
831558Srgrimes *	DESBLKSIZE / DESFRAGSIZE <= 8
841558Srgrimes */
8587661Ssheldonh#define	DFL_FRAGSIZE	2048
8687661Ssheldonh#define	DFL_BLKSIZE	16384
871558Srgrimes
881558Srgrimes/*
891558Srgrimes * Cylinder groups may have up to many cylinders. The actual
901558Srgrimes * number used depends upon how much information can be stored
9184466Sroberto * on a single cylinder. The default is to use as many as possible
9284466Sroberto * cylinders per group.
931558Srgrimes */
9484466Sroberto#define	DESCPG		65536	/* desired fs_cpg ("infinity") */
951558Srgrimes
961558Srgrimes/*
973271Sdg * Once upon a time...
983271Sdg *    ROTDELAY gives the minimum number of milliseconds to initiate
993271Sdg *    another disk transfer on the same cylinder. It is used in
1003271Sdg *    determining the rotationally optimal layout for disk blocks
1013271Sdg *    within a file; the default of fs_rotdelay is 4ms.
1023271Sdg *
1033271Sdg * ...but now we make this 0 to disable the rotdelay delay because
1043271Sdg * modern drives with read/write-behind achieve higher performance
1053271Sdg * without the delay.
1061558Srgrimes */
1073271Sdg#define ROTDELAY	0
1081558Srgrimes
1091558Srgrimes/*
1101558Srgrimes * MAXBLKPG determines the maximum number of data blocks which are
1111558Srgrimes * placed in a single cylinder group. The default is one indirect
1121558Srgrimes * block worth of data blocks.
1131558Srgrimes */
1141558Srgrimes#define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
1151558Srgrimes
1161558Srgrimes/*
1171558Srgrimes * Each file system has a number of inodes statically allocated.
1181558Srgrimes * We allocate one inode slot per NFPI fragments, expecting this
1191558Srgrimes * to be far more than we will ever need.
1201558Srgrimes */
1211558Srgrimes#define	NFPI		4
1221558Srgrimes
1231558Srgrimes/*
1243271Sdg * Once upon a time...
1253271Sdg *    For each cylinder we keep track of the availability of blocks at different
1263271Sdg *    rotational positions, so that we can lay out the data to be picked
1273271Sdg *    up with minimum rotational latency.  NRPOS is the default number of
1283271Sdg *    rotational positions that we distinguish.  With NRPOS of 8 the resolution
1293271Sdg *    of our summary information is 2ms for a typical 3600 rpm drive.
1303271Sdg *
13132537Sbde * ...but now we make this 1 (which essentially disables the rotational
1323467Sdg * position table because modern drives with read-ahead and write-behind do
1333467Sdg * better without the rotational position table.
1341558Srgrimes */
1353467Sdg#define	NRPOS		1	/* number distinct rotational positions */
1361558Srgrimes
1376192Sphk/*
1386192Sphk * About the same time as the above, we knew what went where on the disks.
1396192Sphk * no longer so, so kill the code which finds the different platters too...
1406192Sphk * We do this by saying one head, with a lot of sectors on it.
1416192Sphk * The number of sectors are used to determine the size of a cyl-group.
1426192Sphk * Kirk suggested one or two meg per "cylinder" so we say two.
1436192Sphk */
1446192Sphk#define NTRACKS		1	/* number of heads */
1456192Sphk#define NSECTORS	4096	/* number of sectors */
1466192Sphk
1471558Srgrimesint	Nflag;			/* run without writing file system */
1481558Srgrimesint	Oflag;			/* format as an 4.3BSD file system */
14975078Sobrienint	Uflag;			/* enable soft updates for file system */
1501558Srgrimesint	fssize;			/* file system size */
1516192Sphkint	ntracks = NTRACKS;	/* # tracks/cylinder */
1526192Sphkint	nsectors = NSECTORS;	/* # sectors/track */
1531558Srgrimesint	nphyssectors;		/* # sectors/track including spares */
1541558Srgrimesint	secpercyl;		/* sectors per cylinder */
1551558Srgrimesint	trackspares = -1;	/* spare sectors per track */
1561558Srgrimesint	cylspares = -1;		/* spare sectors per cylinder */
1571558Srgrimesint	sectorsize;		/* bytes/sector */
1581558Srgrimesint	realsectorsize;		/* bytes/sector in hardware */
1591558Srgrimesint	rpm;			/* revolutions/minute of drive */
1601558Srgrimesint	interleave;		/* hardware sector interleave */
1611558Srgrimesint	trackskew = -1;		/* sector 0 skew, per track */
1621558Srgrimesint	headswitch;		/* head switch time, usec */
1631558Srgrimesint	trackseek;		/* track-to-track seek, usec */
1641558Srgrimesint	fsize = 0;		/* fragment size */
1651558Srgrimesint	bsize = 0;		/* block size */
16685098Srobertoint	cpg = DESCPG;		/* cylinders/cylinder group */
1671558Srgrimesint	cpgflg;			/* cylinders/cylinder group flag was given */
1681558Srgrimesint	minfree = MINFREE;	/* free space threshold */
1691558Srgrimesint	opt = DEFAULTOPT;	/* optimization preference (space or time) */
1701558Srgrimesint	density;		/* number of bytes per inode */
1711558Srgrimesint	maxcontig = 0;		/* max contiguous blocks to allocate */
1721558Srgrimesint	rotdelay = ROTDELAY;	/* rotational delay between blocks */
1731558Srgrimesint	maxbpg;			/* maximum blocks per file in a cyl group */
1741558Srgrimesint	nrpos = NRPOS;		/* # of distinguished rotational positions */
17575377Smckusickint	avgfilesize = AVFILESIZ;/* expected average file size */
17675377Smckusickint	avgfilesperdir = AFPDIR;/* expected number of files per directory */
1771558Srgrimesint	bbsize = BBSIZE;	/* boot block size */
1781558Srgrimesint	sbsize = SBSIZE;	/* superblock size */
17910846Sdgint	t_or_u_flag = 0;	/* user has specified -t or -u */
1801558Srgrimes#ifdef COMPAT
1811558Srgrimeschar	*disktype;
1821558Srgrimesint	unlabeled;
1831558Srgrimes#endif
1841558Srgrimes
1851558Srgrimeschar	device[MAXPATHLEN];
1861558Srgrimeschar	*progname;
1871558Srgrimes
18892483Sphkextern void mkfs (struct partition *, char *, int, int);
18992533Sbdestatic void rewritelabel (char *s, int fd, register struct disklabel *lp);
19092483Sphkstatic void usage (void);
19137664Scharnier
1921558Srgrimesint
19392711Siedowsemain(int argc, char *argv[])
1941558Srgrimes{
19592483Sphk	struct partition *pp;
19692483Sphk	struct disklabel *lp;
1971558Srgrimes	struct disklabel *getdisklabel();
1981558Srgrimes	struct partition oldpartition;
1991558Srgrimes	struct stat st;
2001558Srgrimes	struct statfs *mp;
20137664Scharnier	char *cp, *s1, *s2, *special, *opstring;
20292711Siedowse	int ch, fsi, fso, len, n, vflag;
2031558Srgrimes
20439066Sgrog	vflag = 0;
20537664Scharnier	if ((progname = strrchr(*argv, '/')))
2061558Srgrimes		++progname;
2071558Srgrimes	else
2081558Srgrimes		progname = *argv;
2091558Srgrimes
21077420Sphk	opstring = "NOS:T:Ua:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:vx:";
21124359Simp	while ((ch = getopt(argc, argv, opstring)) != -1)
2121558Srgrimes		switch (ch) {
2131558Srgrimes		case 'N':
2141558Srgrimes			Nflag = 1;
2151558Srgrimes			break;
2161558Srgrimes		case 'O':
2171558Srgrimes			Oflag = 1;
2181558Srgrimes			break;
2191558Srgrimes		case 'S':
2201558Srgrimes			if ((sectorsize = atoi(optarg)) <= 0)
2211558Srgrimes				fatal("%s: bad sector size", optarg);
2221558Srgrimes			break;
2231558Srgrimes#ifdef COMPAT
2241558Srgrimes		case 'T':
2251558Srgrimes			disktype = optarg;
2261558Srgrimes			break;
2271558Srgrimes#endif
22875078Sobrien		case 'U':
22975078Sobrien			Uflag = 1;
23075078Sobrien			break;
2311558Srgrimes		case 'a':
2321558Srgrimes			if ((maxcontig = atoi(optarg)) <= 0)
23337664Scharnier				fatal("%s: bad maximum contiguous blocks",
2341558Srgrimes				    optarg);
2351558Srgrimes			break;
2361558Srgrimes		case 'b':
2371558Srgrimes			if ((bsize = atoi(optarg)) < MINBSIZE)
2381558Srgrimes				fatal("%s: bad block size", optarg);
2391558Srgrimes			break;
2401558Srgrimes		case 'c':
2411558Srgrimes			if ((cpg = atoi(optarg)) <= 0)
2421558Srgrimes				fatal("%s: bad cylinders/group", optarg);
2431558Srgrimes			cpgflg++;
2441558Srgrimes			break;
2451558Srgrimes		case 'd':
2461558Srgrimes			if ((rotdelay = atoi(optarg)) < 0)
24737664Scharnier				fatal("%s: bad rotational delay", optarg);
2481558Srgrimes			break;
2491558Srgrimes		case 'e':
2501558Srgrimes			if ((maxbpg = atoi(optarg)) <= 0)
25137664Scharnier		fatal("%s: bad blocks per file in a cylinder group",
2521558Srgrimes				    optarg);
2531558Srgrimes			break;
2541558Srgrimes		case 'f':
2551558Srgrimes			if ((fsize = atoi(optarg)) <= 0)
2561558Srgrimes				fatal("%s: bad fragment size", optarg);
2571558Srgrimes			break;
25875377Smckusick		case 'g':
25975377Smckusick			if ((avgfilesize = atoi(optarg)) <= 0)
26075377Smckusick				fatal("%s: bad average file size", optarg);
26175377Smckusick			break;
26275377Smckusick		case 'h':
26375377Smckusick			if ((avgfilesperdir = atoi(optarg)) <= 0)
26475377Smckusick				fatal("%s: bad average files per dir", optarg);
26575377Smckusick			break;
2661558Srgrimes		case 'i':
2671558Srgrimes			if ((density = atoi(optarg)) <= 0)
26837664Scharnier				fatal("%s: bad bytes per inode", optarg);
2691558Srgrimes			break;
2701558Srgrimes		case 'k':
2711558Srgrimes			if ((trackskew = atoi(optarg)) < 0)
2721558Srgrimes				fatal("%s: bad track skew", optarg);
2731558Srgrimes			break;
2741558Srgrimes		case 'l':
2751558Srgrimes			if ((interleave = atoi(optarg)) <= 0)
2761558Srgrimes				fatal("%s: bad interleave", optarg);
2771558Srgrimes			break;
2781558Srgrimes		case 'm':
2791558Srgrimes			if ((minfree = atoi(optarg)) < 0 || minfree > 99)
28037664Scharnier				fatal("%s: bad free space %%", optarg);
2811558Srgrimes			break;
2821558Srgrimes		case 'n':
2833271Sdg			if ((nrpos = atoi(optarg)) < 0)
28437664Scharnier				fatal("%s: bad rotational layout count",
2851558Srgrimes				    optarg);
2863467Sdg			if (nrpos == 0)
2873467Sdg				nrpos = 1;
2881558Srgrimes			break;
2891558Srgrimes		case 'o':
29077420Sphk			if (strcmp(optarg, "space") == 0)
29177420Sphk				opt = FS_OPTSPACE;
29277420Sphk			else if (strcmp(optarg, "time") == 0)
29377420Sphk				opt = FS_OPTTIME;
29477420Sphk			else
29592533Sbde				fatal(
29692533Sbde		"%s: unknown optimization preference: use `space' or `time'",
29792533Sbde				    optarg);
2981558Srgrimes			break;
2991558Srgrimes		case 'p':
3001558Srgrimes			if ((trackspares = atoi(optarg)) < 0)
3011558Srgrimes				fatal("%s: bad spare sectors per track",
3021558Srgrimes				    optarg);
3031558Srgrimes			break;
3041558Srgrimes		case 'r':
3051558Srgrimes			if ((rpm = atoi(optarg)) <= 0)
30637664Scharnier				fatal("%s: bad revolutions/minute", optarg);
3071558Srgrimes			break;
3081558Srgrimes		case 's':
3091558Srgrimes			if ((fssize = atoi(optarg)) <= 0)
3101558Srgrimes				fatal("%s: bad file system size", optarg);
3111558Srgrimes			break;
3121558Srgrimes		case 't':
31310846Sdg			t_or_u_flag++;
3146202Sphk			if ((ntracks = atoi(optarg)) < 0)
3151558Srgrimes				fatal("%s: bad total tracks", optarg);
3161558Srgrimes			break;
3171558Srgrimes		case 'u':
31810846Sdg			t_or_u_flag++;
3196202Sphk			if ((nsectors = atoi(optarg)) < 0)
3201558Srgrimes				fatal("%s: bad sectors/track", optarg);
3211558Srgrimes			break;
32239066Sgrog		case 'v':
32339066Sgrog			vflag = 1;
32439066Sgrog			break;
3251558Srgrimes		case 'x':
3261558Srgrimes			if ((cylspares = atoi(optarg)) < 0)
3271558Srgrimes				fatal("%s: bad spare sectors per cylinder",
3281558Srgrimes				    optarg);
3291558Srgrimes			break;
3301558Srgrimes		case '?':
3311558Srgrimes		default:
3321558Srgrimes			usage();
3331558Srgrimes		}
3341558Srgrimes	argc -= optind;
3351558Srgrimes	argv += optind;
3361558Srgrimes
33777420Sphk	if (argc != 2 && argc != 1)
3381558Srgrimes		usage();
3391558Srgrimes
3401558Srgrimes	special = argv[0];
34123682Speter	cp = strrchr(special, '/');
3421558Srgrimes	if (cp == 0) {
3431558Srgrimes		/*
34492533Sbde		 * No path prefix; try prefixing _PATH_DEV.
3451558Srgrimes		 */
34692533Sbde		snprintf(device, sizeof(device), "%s%s", _PATH_DEV, special);
3471558Srgrimes		special = device;
3481558Srgrimes	}
34985860Sphk	if (Nflag)
3501558Srgrimes		fso = -1;
35185860Sphk	else {
3521558Srgrimes		fso = open(special, O_WRONLY);
3531558Srgrimes		if (fso < 0)
3541558Srgrimes			fatal("%s: %s", special, strerror(errno));
3551558Srgrimes
3561558Srgrimes		/* Bail if target special is mounted */
3571558Srgrimes		n = getmntinfo(&mp, MNT_NOWAIT);
3581558Srgrimes		if (n == 0)
3591558Srgrimes			fatal("%s: getmntinfo: %s", special, strerror(errno));
3601558Srgrimes
3611558Srgrimes		len = sizeof(_PATH_DEV) - 1;
3621558Srgrimes		s1 = special;
3631558Srgrimes		if (strncmp(_PATH_DEV, s1, len) == 0)
3641558Srgrimes			s1 += len;
3651558Srgrimes
3661558Srgrimes		while (--n >= 0) {
3671558Srgrimes			s2 = mp->f_mntfromname;
3681558Srgrimes			if (strncmp(_PATH_DEV, s2, len) == 0) {
3691558Srgrimes				s2 += len - 1;
3701558Srgrimes				*s2 = 'r';
3711558Srgrimes			}
3721558Srgrimes			if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
3731558Srgrimes				fatal("%s is mounted on %s",
3741558Srgrimes				    special, mp->f_mntonname);
3751558Srgrimes			++mp;
3761558Srgrimes		}
3771558Srgrimes	}
37877420Sphk	fsi = open(special, O_RDONLY);
37977420Sphk	if (fsi < 0)
38077420Sphk		fatal("%s: %s", special, strerror(errno));
38177420Sphk	if (fstat(fsi, &st) < 0)
38277420Sphk		fatal("%s: %s", special, strerror(errno));
38377420Sphk	if ((st.st_mode & S_IFMT) != S_IFCHR)
38477420Sphk		printf("%s: %s: not a character-special device\n",
38577420Sphk		    progname, special);
38677420Sphk	cp = strchr(argv[0], '\0');
38777420Sphk	if (cp == argv[0])
38877420Sphk		fatal("null special file name");
38977420Sphk	cp--;
39077420Sphk	if (!vflag && (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
39177420Sphk		fatal("%s: can't figure out file system partition",
39277420Sphk		    argv[0]);
3931558Srgrimes#ifdef COMPAT
39477420Sphk	if (disktype == NULL)
39577420Sphk		disktype = argv[1];
3961558Srgrimes#endif
39777420Sphk	lp = getdisklabel(special, fsi);
39877420Sphk	if (vflag || isdigit(*cp))
39977420Sphk		pp = &lp->d_partitions[0];
40077420Sphk	else
40177420Sphk		pp = &lp->d_partitions[*cp - 'a'];
40277420Sphk	if (pp->p_size == 0)
40377420Sphk		fatal("%s: `%c' partition is unavailable",
40477420Sphk		    argv[0], *cp);
40577420Sphk	if (pp->p_fstype == FS_BOOT)
40677420Sphk		fatal("%s: `%c' partition overlaps boot program",
40785860Sphk		    argv[0], *cp);
4081558Srgrimes	if (fssize == 0)
4091558Srgrimes		fssize = pp->p_size;
41077420Sphk	if (fssize > pp->p_size)
41192533Sbde		fatal(
41292533Sbde		    "%s: maximum file system size on the `%c' partition is %d",
41392533Sbde		    argv[0], *cp, pp->p_size);
4141558Srgrimes	if (rpm == 0) {
4151558Srgrimes		rpm = lp->d_rpm;
4161558Srgrimes		if (rpm <= 0)
4171558Srgrimes			rpm = 3600;
4181558Srgrimes	}
4191558Srgrimes	if (ntracks == 0) {
4201558Srgrimes		ntracks = lp->d_ntracks;
4211558Srgrimes		if (ntracks <= 0)
4221558Srgrimes			fatal("%s: no default #tracks", argv[0]);
4231558Srgrimes	}
4241558Srgrimes	if (nsectors == 0) {
4251558Srgrimes		nsectors = lp->d_nsectors;
4261558Srgrimes		if (nsectors <= 0)
4271558Srgrimes			fatal("%s: no default #sectors/track", argv[0]);
4281558Srgrimes	}
4291558Srgrimes	if (sectorsize == 0) {
4301558Srgrimes		sectorsize = lp->d_secsize;
4311558Srgrimes		if (sectorsize <= 0)
4321558Srgrimes			fatal("%s: no default sector size", argv[0]);
4331558Srgrimes	}
4341558Srgrimes	if (trackskew == -1) {
4351558Srgrimes		trackskew = lp->d_trackskew;
4361558Srgrimes		if (trackskew < 0)
4371558Srgrimes			trackskew = 0;
4381558Srgrimes	}
4391558Srgrimes	if (interleave == 0) {
4401558Srgrimes		interleave = lp->d_interleave;
4411558Srgrimes		if (interleave <= 0)
4421558Srgrimes			interleave = 1;
4431558Srgrimes	}
4441558Srgrimes	if (fsize == 0) {
4451558Srgrimes		fsize = pp->p_fsize;
4461558Srgrimes		if (fsize <= 0)
4471558Srgrimes			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
4481558Srgrimes	}
4491558Srgrimes	if (bsize == 0) {
4501558Srgrimes		bsize = pp->p_frag * pp->p_fsize;
4511558Srgrimes		if (bsize <= 0)
4521558Srgrimes			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
4531558Srgrimes	}
4541558Srgrimes	/*
4551558Srgrimes	 * Maxcontig sets the default for the maximum number of blocks
4561558Srgrimes	 * that may be allocated sequentially. With filesystem clustering
4571558Srgrimes	 * it is possible to allocate contiguous blocks up to the maximum
4581558Srgrimes	 * transfer size permitted by the controller or buffering.
4591558Srgrimes	 */
4601558Srgrimes	if (maxcontig == 0)
46110627Sdg		maxcontig = MAX(1, MAXPHYS / bsize - 1);
4621558Srgrimes	if (density == 0)
4631558Srgrimes		density = NFPI * fsize;
4641558Srgrimes	if (minfree < MINFREE && opt != FS_OPTSPACE) {
4651558Srgrimes		fprintf(stderr, "Warning: changing optimization to space ");
4661558Srgrimes		fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
4671558Srgrimes		opt = FS_OPTSPACE;
4681558Srgrimes	}
4691558Srgrimes	if (trackspares == -1) {
4701558Srgrimes		trackspares = lp->d_sparespertrack;
4711558Srgrimes		if (trackspares < 0)
4721558Srgrimes			trackspares = 0;
4731558Srgrimes	}
4741558Srgrimes	nphyssectors = nsectors + trackspares;
4751558Srgrimes	if (cylspares == -1) {
4761558Srgrimes		cylspares = lp->d_sparespercyl;
4771558Srgrimes		if (cylspares < 0)
4781558Srgrimes			cylspares = 0;
4791558Srgrimes	}
4801558Srgrimes	secpercyl = nsectors * ntracks - cylspares;
48110649Sjoerg	/*
48210649Sjoerg	 * Only complain if -t or -u have been specified; the default
48332537Sbde	 * case (4096 sectors per cylinder) is intended to disagree
48410649Sjoerg	 * with the disklabel.
48510649Sjoerg	 */
48610846Sdg	if (t_or_u_flag && secpercyl != lp->d_secpercyl)
4871558Srgrimes		fprintf(stderr, "%s (%d) %s (%lu)\n",
48885860Sphk		    "Warning: calculated sectors per cylinder", secpercyl,
48985860Sphk		    "disagrees with disk label", (u_long)lp->d_secpercyl);
4901558Srgrimes	if (maxbpg == 0)
4911558Srgrimes		maxbpg = MAXBLKPG(bsize);
4921558Srgrimes	headswitch = lp->d_headswitch;
4931558Srgrimes	trackseek = lp->d_trkseek;
4941558Srgrimes#ifdef notdef /* label may be 0 if faked up by kernel */
4951558Srgrimes	bbsize = lp->d_bbsize;
4961558Srgrimes	sbsize = lp->d_sbsize;
4971558Srgrimes#endif
4981558Srgrimes	oldpartition = *pp;
4991558Srgrimes	realsectorsize = sectorsize;
5001558Srgrimes	if (sectorsize != DEV_BSIZE) {		/* XXX */
50120061Ssos		int secperblk = sectorsize / DEV_BSIZE;
50220061Ssos
50320061Ssos		sectorsize = DEV_BSIZE;
50420061Ssos		nsectors *= secperblk;
50520061Ssos		nphyssectors *= secperblk;
50620061Ssos		secpercyl *= secperblk;
50720061Ssos		fssize *= secperblk;
50820061Ssos		pp->p_size *= secperblk;
50920061Ssos	}
5101558Srgrimes	mkfs(pp, special, fsi, fso);
5111558Srgrimes	if (realsectorsize != DEV_BSIZE)
51220061Ssos		pp->p_size /= realsectorsize /DEV_BSIZE;
51337775Sbde	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
51437775Sbde		rewritelabel(special, fso, lp);
5151558Srgrimes	if (!Nflag)
5161558Srgrimes		close(fso);
5171558Srgrimes	close(fsi);
5181558Srgrimes	exit(0);
5191558Srgrimes}
5201558Srgrimes
5211558Srgrimes#ifdef COMPAT
52281911Skrisconst char lmsg[] = "%s: can't read disk label; disk type must be specified";
5231558Srgrimes#else
52481911Skrisconst char lmsg[] = "%s: can't read disk label";
5251558Srgrimes#endif
5261558Srgrimes
5271558Srgrimesstruct disklabel *
52892711Siedowsegetdisklabel(char *s, int fd)
5291558Srgrimes{
5301558Srgrimes	static struct disklabel lab;
5311558Srgrimes
5321558Srgrimes	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
5331558Srgrimes#ifdef COMPAT
5341558Srgrimes		if (disktype) {
5351558Srgrimes			struct disklabel *lp, *getdiskbyname();
5361558Srgrimes
5371558Srgrimes			unlabeled++;
5381558Srgrimes			lp = getdiskbyname(disktype);
5391558Srgrimes			if (lp == NULL)
5401558Srgrimes				fatal("%s: unknown disk type", disktype);
5411558Srgrimes			return (lp);
5421558Srgrimes		}
5431558Srgrimes#endif
5441558Srgrimes		warn("ioctl (GDINFO)");
5451558Srgrimes		fatal(lmsg, s);
5461558Srgrimes	}
5471558Srgrimes	return (&lab);
5481558Srgrimes}
5491558Srgrimes
55077420Sphkvoid
55192711Siedowserewritelabel(char *s, int fd, struct disklabel *lp)
55237775Sbde{
55337775Sbde#ifdef COMPAT
55437775Sbde	if (unlabeled)
55537775Sbde		return;
55637775Sbde#endif
55737775Sbde	lp->d_checksum = 0;
55837775Sbde	lp->d_checksum = dkcksum(lp);
55937775Sbde	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
56037775Sbde		warn("ioctl (WDINFO)");
56137775Sbde		fatal("%s: can't rewrite disk label", s);
56237775Sbde	}
56337775Sbde}
56437775Sbde
5651558Srgrimes/*VARARGS*/
5661558Srgrimesvoid
5671558Srgrimesfatal(const char *fmt, ...)
5681558Srgrimes{
5691558Srgrimes	va_list ap;
5701558Srgrimes
5711558Srgrimes	va_start(ap, fmt);
5721558Srgrimes	if (fcntl(STDERR_FILENO, F_GETFL) < 0) {
5731558Srgrimes		openlog(progname, LOG_CONS, LOG_DAEMON);
5741558Srgrimes		vsyslog(LOG_ERR, fmt, ap);
5751558Srgrimes		closelog();
57685860Sphk	} else
5771558Srgrimes		vwarnx(fmt, ap);
5781558Srgrimes	va_end(ap);
5791558Srgrimes	exit(1);
5801558Srgrimes	/*NOTREACHED*/
5811558Srgrimes}
5821558Srgrimes
58337664Scharnierstatic void
5841558Srgrimesusage()
5851558Srgrimes{
58677420Sphk	fprintf(stderr,
58777420Sphk	    "usage: %s [ -fsoptions ] special-device%s\n",
58877420Sphk	    progname,
5891558Srgrimes#ifdef COMPAT
59077420Sphk	    " [device-type]");
5911558Srgrimes#else
59277420Sphk	    "");
5931558Srgrimes#endif
5941558Srgrimes	fprintf(stderr, "where fsoptions are:\n");
5951558Srgrimes	fprintf(stderr,
5961558Srgrimes	    "\t-N do not create file system, just print out parameters\n");
5971558Srgrimes	fprintf(stderr, "\t-O create a 4.3BSD format filesystem\n");
5981558Srgrimes	fprintf(stderr, "\t-S sector size\n");
5991558Srgrimes#ifdef COMPAT
6001558Srgrimes	fprintf(stderr, "\t-T disktype\n");
6011558Srgrimes#endif
60275078Sobrien	fprintf(stderr, "\t-U enable soft updates\n");
6031558Srgrimes	fprintf(stderr, "\t-a maximum contiguous blocks\n");
6041558Srgrimes	fprintf(stderr, "\t-b block size\n");
6051558Srgrimes	fprintf(stderr, "\t-c cylinders/group\n");
6061558Srgrimes	fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
6071558Srgrimes	fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
6081558Srgrimes	fprintf(stderr, "\t-f frag size\n");
60975377Smckusick	fprintf(stderr, "\t-g average file size\n");
61075377Smckusick	fprintf(stderr, "\t-h average files per directory\n");
6111558Srgrimes	fprintf(stderr, "\t-i number of bytes per inode\n");
6121558Srgrimes	fprintf(stderr, "\t-k sector 0 skew, per track\n");
6131558Srgrimes	fprintf(stderr, "\t-l hardware sector interleave\n");
6141558Srgrimes	fprintf(stderr, "\t-m minimum free space %%\n");
6151558Srgrimes	fprintf(stderr, "\t-n number of distinguished rotational positions\n");
6161558Srgrimes	fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
6171558Srgrimes	fprintf(stderr, "\t-p spare sectors per track\n");
6181558Srgrimes	fprintf(stderr, "\t-s file system size (sectors)\n");
6191558Srgrimes	fprintf(stderr, "\t-r revolutions/minute\n");
6201558Srgrimes	fprintf(stderr, "\t-t tracks/cylinder\n");
6211558Srgrimes	fprintf(stderr, "\t-u sectors/track\n");
62239791Sgrog	fprintf(stderr,
62339791Sgrog        "\t-v do not attempt to determine partition name from device name\n");
6241558Srgrimes	fprintf(stderr, "\t-x spare sectors per cylinder\n");
6251558Srgrimes	exit(1);
6261558Srgrimes}
627