xref: /csrg-svn/sbin/newfs/newfs.c (revision 43314)
121159Sdist /*
239049Smckusick  * Copyright (c) 1983, 1989 The Regents of the University of California.
339049Smckusick  * All rights reserved.
439049Smckusick  *
542704Sbostic  * %sccs.include.redist.c%
621159Sdist  */
721159Sdist 
810762Ssam #ifndef lint
9*43314Smckusick static char sccsid[] = "@(#)newfs.c	6.22 (Berkeley) 06/19/90";
1039049Smckusick #endif /* not lint */
1139049Smckusick 
1239049Smckusick #ifndef lint
1321159Sdist char copyright[] =
1439049Smckusick "@(#) Copyright (c) 1983, 1989 Regents of the University of California.\n\
1521159Sdist  All rights reserved.\n";
1639049Smckusick #endif /* not lint */
1710762Ssam 
1810762Ssam /*
1911069Ssam  * newfs: friendly front end to mkfs
2010762Ssam  */
2110762Ssam #include <sys/param.h>
2210762Ssam #include <sys/stat.h>
2338380Smckusick #include <ufs/fs.h>
2438380Smckusick #include <ufs/dir.h>
2530380Smckusick #include <sys/ioctl.h>
2630380Smckusick #include <sys/disklabel.h>
2730380Smckusick #include <sys/file.h>
2839049Smckusick #include <sys/mount.h>
2910762Ssam 
3010762Ssam #include <stdio.h>
3130380Smckusick #include <ctype.h>
3237951Sbostic #include <paths.h>
3310762Ssam 
3431680Skarels #define COMPAT			/* allow non-labeled disks */
3531680Skarels 
3630380Smckusick /*
3730380Smckusick  * The following two constants set the default block and fragment sizes.
3830380Smckusick  * Both constants must be a power of 2 and meet the following constraints:
3930380Smckusick  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
4030380Smckusick  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
4130380Smckusick  *	DESBLKSIZE / DESFRAGSIZE <= 8
4230380Smckusick  */
4330380Smckusick #define	DFL_FRAGSIZE	1024
4430380Smckusick #define	DFL_BLKSIZE	8192
4511183Ssam 
4630380Smckusick /*
4734137Smckusick  * Cylinder groups may have up to many cylinders. The actual
4830380Smckusick  * number used depends upon how much information can be stored
4934137Smckusick  * on a single cylinder. The default is to use 16 cylinders
5030380Smckusick  * per group.
5130380Smckusick  */
5230380Smckusick #define	DESCPG		16	/* desired fs_cpg */
5330380Smckusick 
5430380Smckusick /*
5530380Smckusick  * MINFREE gives the minimum acceptable percentage of file system
5630380Smckusick  * blocks which may be free. If the freelist drops below this level
5730380Smckusick  * only the superuser may continue to allocate blocks. This may
5830380Smckusick  * be set to 0 if no reserve of free blocks is deemed necessary,
5930380Smckusick  * however throughput drops by fifty percent if the file system
6030380Smckusick  * is run at between 90% and 100% full; thus the default value of
6130380Smckusick  * fs_minfree is 10%. With 10% free space, fragmentation is not a
6230380Smckusick  * problem, so we choose to optimize for time.
6330380Smckusick  */
6430380Smckusick #define MINFREE		10
6530380Smckusick #define DEFAULTOPT	FS_OPTTIME
6630380Smckusick 
6730380Smckusick /*
6830380Smckusick  * ROTDELAY gives the minimum number of milliseconds to initiate
6930380Smckusick  * another disk transfer on the same cylinder. It is used in
7030380Smckusick  * determining the rotationally optimal layout for disk blocks
7130380Smckusick  * within a file; the default of fs_rotdelay is 4ms.
7230380Smckusick  */
7330380Smckusick #define ROTDELAY	4
7430380Smckusick 
7530380Smckusick /*
7630380Smckusick  * MAXCONTIG sets the default for the maximum number of blocks
7730380Smckusick  * that may be allocated sequentially. Since UNIX drivers are
7830380Smckusick  * not capable of scheduling multi-block transfers, this defaults
7930380Smckusick  * to 1 (ie no contiguous blocks are allocated).
8030380Smckusick  */
8130380Smckusick #define MAXCONTIG	1
8230380Smckusick 
8330380Smckusick /*
8432309Smckusick  * MAXBLKPG determines the maximum number of data blocks which are
8532309Smckusick  * placed in a single cylinder group. The default is one indirect
8632309Smckusick  * block worth of data blocks.
8732309Smckusick  */
8832309Smckusick #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
8932309Smckusick 
9032309Smckusick /*
9130380Smckusick  * Each file system has a number of inodes statically allocated.
9239049Smckusick  * We allocate one inode slot per NFPI fragments, expecting this
9330380Smckusick  * to be far more than we will ever need.
9430380Smckusick  */
9539049Smckusick #define	NFPI		4
9630380Smckusick 
9734137Smckusick /*
9834137Smckusick  * For each cylinder we keep track of the availability of blocks at different
9934137Smckusick  * rotational positions, so that we can lay out the data to be picked
10034137Smckusick  * up with minimum rotational latency.  NRPOS is the default number of
10134137Smckusick  * rotational positions that we distinguish.  With NRPOS of 8 the resolution
10234137Smckusick  * of our summary information is 2ms for a typical 3600 rpm drive.
10334137Smckusick  */
10434137Smckusick #define	NRPOS		8	/* number distinct rotational positions */
10534137Smckusick 
10634137Smckusick 
10739325Smckusick int	mfs;			/* run as the memory based filesystem */
10830380Smckusick int	Nflag;			/* run without writing file system */
10910762Ssam int	fssize;			/* file system size */
11010762Ssam int	ntracks;		/* # tracks/cylinder */
11110762Ssam int	nsectors;		/* # sectors/track */
11230386Smckusick int	nphyssectors;		/* # sectors/track including spares */
11330380Smckusick int	secpercyl;		/* sectors per cylinder */
11430386Smckusick int	trackspares = -1;	/* spare sectors per track */
11530386Smckusick int	cylspares = -1;		/* spare sectors per cylinder */
11610762Ssam int	sectorsize;		/* bytes/sector */
11730691Skarels #ifdef tahoe
11830691Skarels int	realsectorsize;		/* bytes/sector in hardware */
11930691Skarels #endif
12011069Ssam int	rpm;			/* revolutions/minute of drive */
12130386Smckusick int	interleave;		/* hardware sector interleave */
12230386Smckusick int	trackskew = -1;		/* sector 0 skew, per track */
12330386Smckusick int	headswitch;		/* head switch time, usec */
12430386Smckusick int	trackseek;		/* track-to-track seek, usec */
12530862Skarels int	fsize = 0;		/* fragment size */
12630862Skarels int	bsize = 0;		/* block size */
12730380Smckusick int	cpg = DESCPG;		/* cylinders/cylinder group */
12832119Smckusick int	cpgflg;			/* cylinders/cylinder group flag was given */
12930380Smckusick int	minfree = MINFREE;	/* free space threshold */
13030380Smckusick int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
13139049Smckusick int	density;		/* number of bytes per inode */
13230380Smckusick int	maxcontig = MAXCONTIG;	/* max contiguous blocks to allocate */
13330380Smckusick int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
13432309Smckusick int	maxbpg;			/* maximum blocks per file in a cyl group */
13534137Smckusick int	nrpos = NRPOS;		/* # of distinguished rotational positions */
13630691Skarels int	bbsize = BBSIZE;	/* boot block size */
13730691Skarels int	sbsize = SBSIZE;	/* superblock size */
13839325Smckusick int	mntflags;		/* flags to be passed to mount */
13939049Smckusick u_long	memleft;		/* virtual memory available */
14039049Smckusick caddr_t	membase;		/* start address of memory based filesystem */
14131680Skarels #ifdef COMPAT
142*43314Smckusick char	*disktype;
14331680Skarels int	unlabelled;
14431680Skarels #endif
14510762Ssam 
14610762Ssam char	device[MAXPATHLEN];
14739049Smckusick char	*progname;
14810762Ssam 
14930380Smckusick extern	int errno;
15010762Ssam char	*index();
15110762Ssam char	*rindex();
15210762Ssam 
15310762Ssam main(argc, argv)
15414064Smckusick 	int argc;
15510762Ssam 	char *argv[];
15610762Ssam {
15739049Smckusick 	char *cp, *special, *rindex();
15810762Ssam 	register struct partition *pp;
15930380Smckusick 	register struct disklabel *lp;
16030380Smckusick 	struct disklabel *getdisklabel();
16130380Smckusick 	struct partition oldpartition;
16239049Smckusick 	struct mfs_args args;
16310762Ssam 	struct stat st;
16430380Smckusick 	int fsi, fso;
16510762Ssam 	register int i;
16610762Ssam 	int status;
16739049Smckusick 	char buf[BUFSIZ];
16810762Ssam 
16939049Smckusick 	if ((progname = rindex(*argv, '/') + 1) == (char *)1)
17039049Smckusick 		progname = *argv;
17139325Smckusick 	if (!strcmp(progname, "mfs")) {
17239049Smckusick 		Nflag++;
17339325Smckusick 		mfs++;
17439049Smckusick 	}
17510762Ssam 	argc--, argv++;
17610762Ssam 	while (argc > 0 && argv[0][0] == '-') {
17710762Ssam 		for (cp = &argv[0][1]; *cp; cp++)
17810762Ssam 			switch (*cp) {
17910762Ssam 
18039325Smckusick 			case 'F':
18139325Smckusick 				if (!mfs)
18239325Smckusick 					fatal("-F: unknown flag");
18339325Smckusick 				if (argc < 1)
18439325Smckusick 					fatal("-F: mount flags");
18539325Smckusick 				argc--, argv++;
18639325Smckusick 				mntflags = atoi(*argv);
18739325Smckusick 				if (mntflags == 0)
18839325Smckusick 					fatal("%s: bad mount flags", *argv);
18939325Smckusick 				goto next;
19039325Smckusick 
19116945Smckusick 			case 'N':
19216945Smckusick 				Nflag++;
19312334Shelge 				break;
19412334Shelge 
19530380Smckusick 			case 'S':
19610762Ssam 				if (argc < 1)
19730380Smckusick 					fatal("-S: missing sector size");
19810762Ssam 				argc--, argv++;
19930380Smckusick 				sectorsize = atoi(*argv);
20030380Smckusick 				if (sectorsize <= 0)
20130380Smckusick 					fatal("%s: bad sector size", *argv);
20210762Ssam 				goto next;
20310762Ssam 
204*43314Smckusick #ifdef COMPAT
205*43314Smckusick 			case 'T':
206*43314Smckusick 				if (argc < 1)
207*43314Smckusick 					fatal("-T: missing disk type");
208*43314Smckusick 				argc--, argv++;
209*43314Smckusick 				disktype = *argv;
210*43314Smckusick 				goto next;
211*43314Smckusick #endif
212*43314Smckusick 
21330380Smckusick 			case 'a':
21410762Ssam 				if (argc < 1)
21532309Smckusick 					fatal("-a: missing max contiguous blocks\n");
21610762Ssam 				argc--, argv++;
21732309Smckusick 				maxcontig = atoi(*argv);
21832309Smckusick 				if (maxcontig <= 0)
21932309Smckusick 					fatal("%s: bad max contiguous blocks\n",
22032309Smckusick 						*argv);
22110762Ssam 				goto next;
22210762Ssam 
22310762Ssam 			case 'b':
22410762Ssam 				if (argc < 1)
22510762Ssam 					fatal("-b: missing block size");
22610762Ssam 				argc--, argv++;
22710762Ssam 				bsize = atoi(*argv);
22830380Smckusick 				if (bsize < MINBSIZE)
22910762Ssam 					fatal("%s: bad block size", *argv);
23010762Ssam 				goto next;
23110762Ssam 
23230380Smckusick 			case 'c':
23330380Smckusick 				if (argc < 1)
23430380Smckusick 					fatal("-c: missing cylinders/group");
23530380Smckusick 				argc--, argv++;
23630380Smckusick 				cpg = atoi(*argv);
23730380Smckusick 				if (cpg <= 0)
23830380Smckusick 					fatal("%s: bad cylinders/group", *argv);
23932119Smckusick 				cpgflg++;
24030380Smckusick 				goto next;
24130380Smckusick 
24230380Smckusick 			case 'd':
24330380Smckusick 				if (argc < 1)
24432309Smckusick 					fatal("-d: missing rotational delay\n");
24530380Smckusick 				argc--, argv++;
24632309Smckusick 				rotdelay = atoi(*argv);
24732309Smckusick 				if (rotdelay < 0)
24832309Smckusick 					fatal("%s: bad rotational delay\n",
24932309Smckusick 						*argv);
25030380Smckusick 				goto next;
25130380Smckusick 
25232309Smckusick 			case 'e':
25332309Smckusick 				if (argc < 1)
25432309Smckusick 					fatal("-e: missing blocks pre file in a cyl group\n");
25532309Smckusick 				argc--, argv++;
25632309Smckusick 				maxbpg = atoi(*argv);
25732309Smckusick 				if (maxbpg <= 0)
25832309Smckusick 					fatal("%s: bad blocks per file in a cyl group\n",
25932309Smckusick 						*argv);
26032309Smckusick 				goto next;
26132309Smckusick 
26210762Ssam 			case 'f':
26310762Ssam 				if (argc < 1)
26410762Ssam 					fatal("-f: missing frag size");
26510762Ssam 				argc--, argv++;
26610762Ssam 				fsize = atoi(*argv);
26730380Smckusick 				if (fsize <= 0)
26810762Ssam 					fatal("%s: bad frag size", *argv);
26910762Ssam 				goto next;
27010762Ssam 
27130380Smckusick 			case 'i':
27210762Ssam 				if (argc < 1)
27330380Smckusick 					fatal("-i: missing bytes per inode\n");
27410762Ssam 				argc--, argv++;
27530380Smckusick 				density = atoi(*argv);
27630380Smckusick 				if (density <= 0)
27730380Smckusick 					fatal("%s: bad bytes per inode\n",
27830380Smckusick 						*argv);
27910762Ssam 				goto next;
28010762Ssam 
28130386Smckusick 			case 'k':
28230386Smckusick 				if (argc < 1)
28330386Smckusick 					fatal("-k: track skew");
28430386Smckusick 				argc--, argv++;
28530386Smckusick 				trackskew = atoi(*argv);
28630386Smckusick 				if (trackskew < 0)
28730386Smckusick 					fatal("%s: bad track skew", *argv);
28830386Smckusick 				goto next;
28930386Smckusick 
29030386Smckusick 			case 'l':
29130386Smckusick 				if (argc < 1)
29230386Smckusick 					fatal("-l: interleave");
29330386Smckusick 				argc--, argv++;
29430386Smckusick 				interleave = atoi(*argv);
29530386Smckusick 				if (interleave <= 0)
29630386Smckusick 					fatal("%s: bad interleave", *argv);
29730386Smckusick 				goto next;
29830386Smckusick 
29911069Ssam 			case 'm':
30011069Ssam 				if (argc < 1)
30111069Ssam 					fatal("-m: missing free space %%\n");
30211069Ssam 				argc--, argv++;
30311069Ssam 				minfree = atoi(*argv);
30411069Ssam 				if (minfree < 0 || minfree > 99)
30511069Ssam 					fatal("%s: bad free space %%\n",
30611069Ssam 						*argv);
30711069Ssam 				goto next;
30811069Ssam 
30934137Smckusick 			case 'n':
31034137Smckusick 				if (argc < 1)
31134137Smckusick 					fatal("-n: missing rotational layout count\n");
31234137Smckusick 				argc--, argv++;
31334137Smckusick 				nrpos = atoi(*argv);
31434137Smckusick 				if (nrpos <= 0)
31534137Smckusick 					fatal("%s: bad rotational layout count\n",
31634137Smckusick 						*argv);
31734137Smckusick 				goto next;
31834137Smckusick 
31930380Smckusick 			case 'o':
32030380Smckusick 				if (argc < 1)
32130380Smckusick 					fatal("-o: missing optimization preference");
32230380Smckusick 				argc--, argv++;
32330380Smckusick 				if (strcmp(*argv, "space") == 0)
32430380Smckusick 					opt = FS_OPTSPACE;
32530380Smckusick 				else if (strcmp(*argv, "time") == 0)
32630380Smckusick 					opt = FS_OPTTIME;
32730380Smckusick 				else
32830380Smckusick 					fatal("%s: bad optimization preference %s",
32930380Smckusick 					    *argv,
33030380Smckusick 					    "(options are `space' or `time')");
33130380Smckusick 				goto next;
33230380Smckusick 
33330386Smckusick 			case 'p':
33430386Smckusick 				if (argc < 1)
33530386Smckusick 					fatal("-p: spare sectors per track");
33630386Smckusick 				argc--, argv++;
33730386Smckusick 				trackspares = atoi(*argv);
33830386Smckusick 				if (trackspares < 0)
33930386Smckusick 					fatal("%s: bad spare sectors per track", *argv);
34030386Smckusick 				goto next;
34130386Smckusick 
34211069Ssam 			case 'r':
34311069Ssam 				if (argc < 1)
34411069Ssam 					fatal("-r: missing revs/minute\n");
34511069Ssam 				argc--, argv++;
34611069Ssam 				rpm = atoi(*argv);
34730380Smckusick 				if (rpm <= 0)
34811069Ssam 					fatal("%s: bad revs/minute\n", *argv);
34911069Ssam 				goto next;
35011069Ssam 
35130380Smckusick 			case 's':
35214884Smckusick 				if (argc < 1)
35330380Smckusick 					fatal("-s: missing file system size");
35414884Smckusick 				argc--, argv++;
35530380Smckusick 				fssize = atoi(*argv);
35630380Smckusick 				if (fssize <= 0)
35730380Smckusick 					fatal("%s: bad file system size",
35814884Smckusick 						*argv);
35914884Smckusick 				goto next;
36014884Smckusick 
36130380Smckusick 			case 't':
36230380Smckusick 				if (argc < 1)
36330380Smckusick 					fatal("-t: missing track total");
36430380Smckusick 				argc--, argv++;
36530380Smckusick 				ntracks = atoi(*argv);
36630380Smckusick 				if (ntracks <= 0)
36730380Smckusick 					fatal("%s: bad total tracks", *argv);
36830380Smckusick 				goto next;
36930380Smckusick 
37032309Smckusick 			case 'u':
37132309Smckusick 				if (argc < 1)
37232309Smckusick 					fatal("-u: missing sectors/track");
37332309Smckusick 				argc--, argv++;
37432309Smckusick 				nsectors = atoi(*argv);
37532309Smckusick 				if (nsectors <= 0)
37632309Smckusick 					fatal("%s: bad sectors/track", *argv);
37732309Smckusick 				goto next;
37832309Smckusick 
37932309Smckusick 			case 'x':
38032309Smckusick 				if (argc < 1)
38132309Smckusick 					fatal("-x: spare sectors per cylinder");
38232309Smckusick 				argc--, argv++;
38332309Smckusick 				cylspares = atoi(*argv);
38432309Smckusick 				if (cylspares < 0)
38532309Smckusick 					fatal("%s: bad spare sectors per cylinder", *argv);
38632309Smckusick 				goto next;
38732309Smckusick 
38810762Ssam 			default:
38932320Sbostic 				fatal("-%c: unknown flag", *cp);
39010762Ssam 			}
39110762Ssam next:
39210762Ssam 		argc--, argv++;
39310762Ssam 	}
39430380Smckusick 	if (argc < 1) {
39539325Smckusick 		if (mfs)
39639049Smckusick 			fprintf(stderr,
39739325Smckusick 			    "usage: mfs [ fsoptions ] special-device %s\n",
39839049Smckusick 			    "mount-point");
39939049Smckusick 		else
40031680Skarels #ifdef COMPAT
40139049Smckusick 			fprintf(stderr, "usage: %s\n",
40239049Smckusick 			    "newfs [ fsoptions ] special-device [device-type]");
40331680Skarels #else
40439049Smckusick 			fprintf(stderr,
40539049Smckusick 			    "usage: newfs [ fsoptions ] special-device\n");
40631680Skarels #endif
40730380Smckusick 		fprintf(stderr, "where fsoptions are:\n");
40816945Smckusick 		fprintf(stderr, "\t-N do not create file system, %s\n",
40916945Smckusick 			"just print out parameters");
410*43314Smckusick #ifdef COMPAT
411*43314Smckusick 		fprintf(stderr, "\t-T disktype\n");
412*43314Smckusick #endif
41311057Ssam 		fprintf(stderr, "\t-b block size\n");
41411057Ssam 		fprintf(stderr, "\t-f frag size\n");
41511069Ssam 		fprintf(stderr, "\t-m minimum free space %%\n");
41624702Smckusick 		fprintf(stderr, "\t-o optimization preference %s\n",
41724702Smckusick 			"(`space' or `time')");
41832309Smckusick 		fprintf(stderr, "\t-a maximum contiguous blocks\n");
41932309Smckusick 		fprintf(stderr, "\t-d rotational delay between %s\n",
42032309Smckusick 			"contiguous blocks");
42132309Smckusick 		fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
42232309Smckusick 			"cylinder group");
42330398Smckusick 		fprintf(stderr, "\t-i number of bytes per inode\n");
42430398Smckusick 		fprintf(stderr, "\t-c cylinders/group\n");
42534137Smckusick 		fprintf(stderr, "\t-n number of distinguished %s\n",
42634137Smckusick 			"rotational positions");
42730398Smckusick 		fprintf(stderr, "\t-s file system size (sectors)\n");
42811069Ssam 		fprintf(stderr, "\t-r revolutions/minute\n");
42911057Ssam 		fprintf(stderr, "\t-S sector size\n");
43032309Smckusick 		fprintf(stderr, "\t-u sectors/track\n");
43130398Smckusick 		fprintf(stderr, "\t-t tracks/cylinder\n");
43230398Smckusick 		fprintf(stderr, "\t-p spare sectors per track\n");
43332309Smckusick 		fprintf(stderr, "\t-x spare sectors per cylinder\n");
43430386Smckusick 		fprintf(stderr, "\t-l hardware sector interleave\n");
43530386Smckusick 		fprintf(stderr, "\t-k sector 0 skew, per track\n");
43610762Ssam 		exit(1);
43710762Ssam 	}
43810762Ssam 	special = argv[0];
43914064Smckusick 	cp = rindex(special, '/');
44014064Smckusick 	if (cp != 0)
44114064Smckusick 		special = cp + 1;
442*43314Smckusick 	if (*special == 'r'
443*43314Smckusick #if defined(vax) || defined(tahoe)
444*43314Smckusick 	    && special[1] != 'a' && special[1] != 'b'
445*43314Smckusick #endif
446*43314Smckusick #if defined(hp300)
447*43314Smckusick 	    && special[1] != 'd'
448*43314Smckusick #endif
449*43314Smckusick 	   )
45014064Smckusick 		special++;
45137951Sbostic 	(void)sprintf(device, "%s/r%s", _PATH_DEV, special);
45232463Sbostic 	special = device;
45330380Smckusick 	if (!Nflag) {
45430380Smckusick 		fso = open(special, O_WRONLY);
45530380Smckusick 		if (fso < 0) {
45630380Smckusick 			perror(special);
45739049Smckusick 			exit(2);
45830380Smckusick 		}
45930380Smckusick 	} else
46030380Smckusick 		fso = -1;
46130380Smckusick 	fsi = open(special, O_RDONLY);
46230380Smckusick 	if (fsi < 0) {
46330380Smckusick 		perror(special);
46439049Smckusick 		exit(3);
46530380Smckusick 	}
46630380Smckusick 	if (fstat(fsi, &st) < 0) {
46739049Smckusick 		fprintf(stderr, "%s: ", progname); perror(special);
46839049Smckusick 		exit(4);
46910762Ssam 	}
47014064Smckusick 	if ((st.st_mode & S_IFMT) != S_IFCHR)
47114064Smckusick 		fatal("%s: not a character device", special);
47210762Ssam 	cp = index(argv[0], '\0') - 1;
47330380Smckusick 	if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
47410762Ssam 		fatal("%s: can't figure out file system partition", argv[0]);
47531680Skarels #ifdef COMPAT
476*43314Smckusick 	if (!mfs && disktype == NULL)
477*43314Smckusick 		disktype = argv[1];
478*43314Smckusick #endif
47930380Smckusick 	lp = getdisklabel(special, fsi);
48030380Smckusick 	if (isdigit(*cp))
48130380Smckusick 		pp = &lp->d_partitions[0];
48230380Smckusick 	else
48330380Smckusick 		pp = &lp->d_partitions[*cp - 'a'];
48430380Smckusick 	if (pp->p_size == 0)
48530380Smckusick 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
48630380Smckusick 	if (fssize == 0)
48710762Ssam 		fssize = pp->p_size;
48839325Smckusick 	if (fssize > pp->p_size && !mfs)
48930380Smckusick 	       fatal("%s: maximum file system size on the `%c' partition is %d",
49030380Smckusick 			argv[0], *cp, pp->p_size);
49130380Smckusick 	if (rpm == 0) {
49230380Smckusick 		rpm = lp->d_rpm;
49330380Smckusick 		if (rpm <= 0)
49430743Skarels 			rpm = 3600;
49510762Ssam 	}
49630380Smckusick 	if (ntracks == 0) {
49730380Smckusick 		ntracks = lp->d_ntracks;
49830380Smckusick 		if (ntracks <= 0)
49930743Skarels 			fatal("%s: no default #tracks", argv[0]);
50030380Smckusick 	}
50110762Ssam 	if (nsectors == 0) {
50230380Smckusick 		nsectors = lp->d_nsectors;
50330380Smckusick 		if (nsectors <= 0)
50430743Skarels 			fatal("%s: no default #sectors/track", argv[0]);
50510762Ssam 	}
50610762Ssam 	if (sectorsize == 0) {
50730380Smckusick 		sectorsize = lp->d_secsize;
50830380Smckusick 		if (sectorsize <= 0)
50930743Skarels 			fatal("%s: no default sector size", argv[0]);
51010762Ssam 	}
51130386Smckusick 	if (trackskew == -1) {
51230386Smckusick 		trackskew = lp->d_trackskew;
51330386Smckusick 		if (trackskew < 0)
51430743Skarels 			trackskew = 0;
51530386Smckusick 	}
51630386Smckusick 	if (interleave == 0) {
51730386Smckusick 		interleave = lp->d_interleave;
51830386Smckusick 		if (interleave <= 0)
51930743Skarels 			interleave = 1;
52030386Smckusick 	}
52110762Ssam 	if (fsize == 0) {
52210762Ssam 		fsize = pp->p_fsize;
52330380Smckusick 		if (fsize <= 0)
52430380Smckusick 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
52510762Ssam 	}
52630380Smckusick 	if (bsize == 0) {
52730380Smckusick 		bsize = pp->p_frag * pp->p_fsize;
52830380Smckusick 		if (bsize <= 0)
52930380Smckusick 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
53011069Ssam 	}
53139049Smckusick 	if (density == 0)
53239049Smckusick 		density = NFPI * fsize;
53324702Smckusick 	if (minfree < 10 && opt != FS_OPTSPACE) {
53430380Smckusick 		fprintf(stderr, "Warning: changing optimization to space ");
53530380Smckusick 		fprintf(stderr, "because minfree is less than 10%%\n");
53624702Smckusick 		opt = FS_OPTSPACE;
53724702Smckusick 	}
53830386Smckusick 	if (trackspares == -1) {
53930386Smckusick 		trackspares = lp->d_sparespertrack;
54030386Smckusick 		if (trackspares < 0)
54130743Skarels 			trackspares = 0;
54230386Smckusick 	}
54330386Smckusick 	nphyssectors = nsectors + trackspares;
54430386Smckusick 	if (cylspares == -1) {
54530386Smckusick 		cylspares = lp->d_sparespercyl;
54630386Smckusick 		if (cylspares < 0)
54730743Skarels 			cylspares = 0;
54830386Smckusick 	}
54930386Smckusick 	secpercyl = nsectors * ntracks - cylspares;
55030380Smckusick 	if (secpercyl != lp->d_secpercyl)
55130380Smckusick 		fprintf(stderr, "%s (%d) %s (%d)\n",
55230380Smckusick 			"Warning: calculated sectors per cylinder", secpercyl,
55330380Smckusick 			"disagrees with disk label", lp->d_secpercyl);
55432321Smckusick 	if (maxbpg == 0)
55532321Smckusick 		maxbpg = MAXBLKPG(bsize);
55630386Smckusick 	headswitch = lp->d_headswitch;
55730386Smckusick 	trackseek = lp->d_trkseek;
55830691Skarels 	bbsize = lp->d_bbsize;
55930691Skarels 	sbsize = lp->d_sbsize;
56030380Smckusick 	oldpartition = *pp;
56130691Skarels #ifdef tahoe
56230691Skarels 	realsectorsize = sectorsize;
56330862Skarels 	if (sectorsize != DEV_BSIZE) {		/* XXX */
56430691Skarels 		int secperblk = DEV_BSIZE / sectorsize;
56530691Skarels 
56630691Skarels 		sectorsize = DEV_BSIZE;
56730691Skarels 		nsectors /= secperblk;
56830691Skarels 		nphyssectors /= secperblk;
56930691Skarels 		secpercyl /= secperblk;
57030691Skarels 		fssize /= secperblk;
57130691Skarels 		pp->p_size /= secperblk;
57230691Skarels 	}
57330691Skarels #endif
57430380Smckusick 	mkfs(pp, special, fsi, fso);
57530691Skarels #ifdef tahoe
57630691Skarels 	if (realsectorsize != DEV_BSIZE)
57730691Skarels 		pp->p_size *= DEV_BSIZE / realsectorsize;
57830691Skarels #endif
57930380Smckusick 	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
58030380Smckusick 		rewritelabel(special, fso, lp);
58139049Smckusick 	if (!Nflag)
58239049Smckusick 		close(fso);
58339049Smckusick 	close(fsi);
58439325Smckusick 	if (mfs) {
58539325Smckusick 		sprintf(buf, "mfs:%d", getpid());
58639049Smckusick 		args.name = buf;
58739049Smckusick 		args.base = membase;
58839049Smckusick 		args.size = fssize * sectorsize;
58939325Smckusick 		if (mount(MOUNT_MFS, argv[1], mntflags, &args) < 0) {
59039325Smckusick 			perror("mfs: mount");
59139049Smckusick 			exit(5);
59239049Smckusick 		}
59339049Smckusick 	}
59430380Smckusick 	exit(0);
59530380Smckusick }
59630380Smckusick 
59731680Skarels #ifdef COMPAT
598*43314Smckusick char lmsg[] = "%s: can't read disk label; disk type must be specified";
599*43314Smckusick #else
600*43314Smckusick char lmsg[] = "%s: can't read disk label";
601*43314Smckusick #endif
60231680Skarels 
60331680Skarels struct disklabel *
60430380Smckusick getdisklabel(s, fd)
60530380Smckusick 	char *s;
60631680Skarels 	int fd;
60730380Smckusick {
60830380Smckusick 	static struct disklabel lab;
60930380Smckusick 
61030380Smckusick 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
611*43314Smckusick #ifdef COMPAT
612*43314Smckusick 		if (disktype) {
613*43314Smckusick 			struct disklabel *getdiskbyname();
614*43314Smckusick 
615*43314Smckusick 			unlabelled++;
616*43314Smckusick 			return (getdiskbyname(disktype));
617*43314Smckusick 		}
618*43314Smckusick #endif
61930380Smckusick 		perror("ioctl (GDINFO)");
620*43314Smckusick 		fatal(lmsg, s);
62110762Ssam 	}
62230380Smckusick 	return (&lab);
62330380Smckusick }
62410762Ssam 
62530380Smckusick rewritelabel(s, fd, lp)
62630380Smckusick 	char *s;
62730380Smckusick 	int fd;
62830380Smckusick 	register struct disklabel *lp;
62930380Smckusick {
63030380Smckusick 
63131680Skarels #ifdef COMPAT
63231680Skarels 	if (unlabelled)
63331680Skarels 		return;
63431680Skarels #endif
63530380Smckusick 	lp->d_checksum = 0;
63630380Smckusick 	lp->d_checksum = dkcksum(lp);
63730380Smckusick 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
63832786Smckusick 		perror("ioctl (WDINFO)");
63930380Smckusick 		fatal("%s: can't rewrite disk label", s);
64010762Ssam 	}
64130446Skarels #if vax
64230446Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
64330446Skarels 		register i;
64430691Skarels 		int cfd;
64530446Skarels 		daddr_t alt;
64630691Skarels 		char specname[64];
64730691Skarels 		char blk[1024];
64831045Ssam 		char *cp;
64930446Skarels 
65030691Skarels 		/*
65130691Skarels 		 * Make name for 'c' partition.
65230691Skarels 		 */
65330691Skarels 		strcpy(specname, s);
65430691Skarels 		cp = specname + strlen(specname) - 1;
65530691Skarels 		if (!isdigit(*cp))
65630691Skarels 			*cp = 'c';
65730691Skarels 		cfd = open(specname, O_WRONLY);
65830691Skarels 		if (cfd < 0) {
65930691Skarels 			perror(specname);
66039049Smckusick 			exit(6);
66130691Skarels 		}
66230691Skarels 		bzero(blk, sizeof(blk));
66330691Skarels 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
66430446Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
66530446Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
66631680Skarels 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
66731680Skarels 				perror("lseek to badsector area");
66839049Smckusick 				exit(7);
66931680Skarels 			}
67030691Skarels 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
67130446Skarels 				int oerrno = errno;
67230446Skarels 				fprintf(stderr, "alternate label %d ", i/2);
67330446Skarels 				errno = oerrno;
67430446Skarels 				perror("write");
67530446Skarels 			}
67630380Smckusick 		}
67739049Smckusick 		close(cfd);
67830380Smckusick 	}
67930446Skarels #endif
68010762Ssam }
68110762Ssam 
68210762Ssam /*VARARGS*/
68310762Ssam fatal(fmt, arg1, arg2)
68410762Ssam 	char *fmt;
68510762Ssam {
68610762Ssam 
68739049Smckusick 	fprintf(stderr, "%s: ", progname);
68810762Ssam 	fprintf(stderr, fmt, arg1, arg2);
68910762Ssam 	putc('\n', stderr);
69039049Smckusick 	exit(8);
69110762Ssam }
692