xref: /csrg-svn/sbin/newfs/newfs.c (revision 32320)
121159Sdist /*
221159Sdist  * Copyright (c) 1983 Regents of the University of California.
321159Sdist  * All rights reserved.  The Berkeley software License Agreement
421159Sdist  * specifies the terms and conditions for redistribution.
521159Sdist  */
621159Sdist 
710762Ssam #ifndef lint
821159Sdist char copyright[] =
921159Sdist "@(#) Copyright (c) 1983 Regents of the University of California.\n\
1021159Sdist  All rights reserved.\n";
1121159Sdist #endif not lint
1210762Ssam 
1321159Sdist #ifndef lint
14*32320Sbostic static char sccsid[] = "@(#)newfs.c	6.12 (Berkeley) 10/01/87";
1521159Sdist #endif not lint
1621159Sdist 
1710762Ssam /*
1811069Ssam  * newfs: friendly front end to mkfs
1910762Ssam  */
2010762Ssam #include <sys/param.h>
2110762Ssam #include <sys/stat.h>
2210762Ssam #include <sys/fs.h>
2313603Ssam #include <sys/dir.h>
2430380Smckusick #include <sys/ioctl.h>
2530380Smckusick #include <sys/disklabel.h>
2630380Smckusick #include <sys/file.h>
2710762Ssam 
2810762Ssam #include <stdio.h>
2930380Smckusick #include <ctype.h>
3010762Ssam 
3131680Skarels #define COMPAT			/* allow non-labeled disks */
3231680Skarels 
3330380Smckusick /*
3430380Smckusick  * The following two constants set the default block and fragment sizes.
3530380Smckusick  * Both constants must be a power of 2 and meet the following constraints:
3630380Smckusick  *	MINBSIZE <= DESBLKSIZE <= MAXBSIZE
3730380Smckusick  *	sectorsize <= DESFRAGSIZE <= DESBLKSIZE
3830380Smckusick  *	DESBLKSIZE / DESFRAGSIZE <= 8
3930380Smckusick  */
4030380Smckusick #define	DFL_FRAGSIZE	1024
4130380Smckusick #define	DFL_BLKSIZE	8192
4211183Ssam 
4330380Smckusick /*
4430380Smckusick  * Cylinder groups may have up to MAXCPG cylinders. The actual
4530380Smckusick  * number used depends upon how much information can be stored
4630380Smckusick  * on a single cylinder. The default is to used 16 cylinders
4730380Smckusick  * per group.
4830380Smckusick  */
4930380Smckusick #define	DESCPG		16	/* desired fs_cpg */
5030380Smckusick 
5130380Smckusick /*
5230380Smckusick  * MINFREE gives the minimum acceptable percentage of file system
5330380Smckusick  * blocks which may be free. If the freelist drops below this level
5430380Smckusick  * only the superuser may continue to allocate blocks. This may
5530380Smckusick  * be set to 0 if no reserve of free blocks is deemed necessary,
5630380Smckusick  * however throughput drops by fifty percent if the file system
5730380Smckusick  * is run at between 90% and 100% full; thus the default value of
5830380Smckusick  * fs_minfree is 10%. With 10% free space, fragmentation is not a
5930380Smckusick  * problem, so we choose to optimize for time.
6030380Smckusick  */
6130380Smckusick #define MINFREE		10
6230380Smckusick #define DEFAULTOPT	FS_OPTTIME
6330380Smckusick 
6430380Smckusick /*
6530380Smckusick  * ROTDELAY gives the minimum number of milliseconds to initiate
6630380Smckusick  * another disk transfer on the same cylinder. It is used in
6730380Smckusick  * determining the rotationally optimal layout for disk blocks
6830380Smckusick  * within a file; the default of fs_rotdelay is 4ms.
6930380Smckusick  */
7030380Smckusick #define ROTDELAY	4
7130380Smckusick 
7230380Smckusick /*
7330380Smckusick  * MAXCONTIG sets the default for the maximum number of blocks
7430380Smckusick  * that may be allocated sequentially. Since UNIX drivers are
7530380Smckusick  * not capable of scheduling multi-block transfers, this defaults
7630380Smckusick  * to 1 (ie no contiguous blocks are allocated).
7730380Smckusick  */
7830380Smckusick #define MAXCONTIG	1
7930380Smckusick 
8030380Smckusick /*
8132309Smckusick  * MAXBLKPG determines the maximum number of data blocks which are
8232309Smckusick  * placed in a single cylinder group. The default is one indirect
8332309Smckusick  * block worth of data blocks.
8432309Smckusick  */
8532309Smckusick #define MAXBLKPG(bsize)	((bsize) / sizeof(daddr_t))
8632309Smckusick 
8732309Smckusick /*
8830380Smckusick  * Each file system has a number of inodes statically allocated.
8930380Smckusick  * We allocate one inode slot per NBPI bytes, expecting this
9030380Smckusick  * to be far more than we will ever need.
9130380Smckusick  */
9230380Smckusick #define	NBPI		2048
9330380Smckusick 
9430380Smckusick int	Nflag;			/* run without writing file system */
9510762Ssam int	fssize;			/* file system size */
9610762Ssam int	ntracks;		/* # tracks/cylinder */
9710762Ssam int	nsectors;		/* # sectors/track */
9830386Smckusick int	nphyssectors;		/* # sectors/track including spares */
9930380Smckusick int	secpercyl;		/* sectors per cylinder */
10030386Smckusick int	trackspares = -1;	/* spare sectors per track */
10130386Smckusick int	cylspares = -1;		/* spare sectors per cylinder */
10210762Ssam int	sectorsize;		/* bytes/sector */
10330691Skarels #ifdef tahoe
10430691Skarels int	realsectorsize;		/* bytes/sector in hardware */
10530691Skarels #endif
10611069Ssam int	rpm;			/* revolutions/minute of drive */
10730386Smckusick int	interleave;		/* hardware sector interleave */
10830386Smckusick int	trackskew = -1;		/* sector 0 skew, per track */
10930386Smckusick int	headswitch;		/* head switch time, usec */
11030386Smckusick int	trackseek;		/* track-to-track seek, usec */
11130862Skarels int	fsize = 0;		/* fragment size */
11230862Skarels int	bsize = 0;		/* block size */
11330380Smckusick int	cpg = DESCPG;		/* cylinders/cylinder group */
11432119Smckusick int	cpgflg;			/* cylinders/cylinder group flag was given */
11530380Smckusick int	minfree = MINFREE;	/* free space threshold */
11630380Smckusick int	opt = DEFAULTOPT;	/* optimization preference (space or time) */
11730380Smckusick int	density = NBPI;		/* number of bytes per inode */
11830380Smckusick int	maxcontig = MAXCONTIG;	/* max contiguous blocks to allocate */
11930380Smckusick int	rotdelay = ROTDELAY;	/* rotational delay between blocks */
12032309Smckusick int	maxbpg;			/* maximum blocks per file in a cyl group */
12130691Skarels int	bbsize = BBSIZE;	/* boot block size */
12230691Skarels int	sbsize = SBSIZE;	/* superblock size */
12331680Skarels #ifdef COMPAT
12431680Skarels int	unlabelled;
12531680Skarels #endif
12610762Ssam 
12710762Ssam char	device[MAXPATHLEN];
12810762Ssam 
12930380Smckusick extern	int errno;
13010762Ssam char	*index();
13110762Ssam char	*rindex();
13210762Ssam char	*sprintf();
13310762Ssam 
13410762Ssam main(argc, argv)
13514064Smckusick 	int argc;
13610762Ssam 	char *argv[];
13710762Ssam {
13810762Ssam 	char *cp, *special;
13910762Ssam 	register struct partition *pp;
14030380Smckusick 	register struct disklabel *lp;
14130380Smckusick 	struct disklabel *getdisklabel();
14230380Smckusick 	struct partition oldpartition;
14310762Ssam 	struct stat st;
14430380Smckusick 	int fsi, fso;
14510762Ssam 	register int i;
14610762Ssam 	int status;
14710762Ssam 
14810762Ssam 	argc--, argv++;
14910762Ssam 	while (argc > 0 && argv[0][0] == '-') {
15010762Ssam 		for (cp = &argv[0][1]; *cp; cp++)
15110762Ssam 			switch (*cp) {
15210762Ssam 
15316945Smckusick 			case 'N':
15416945Smckusick 				Nflag++;
15512334Shelge 				break;
15612334Shelge 
15730380Smckusick 			case 'S':
15810762Ssam 				if (argc < 1)
15930380Smckusick 					fatal("-S: missing sector size");
16010762Ssam 				argc--, argv++;
16130380Smckusick 				sectorsize = atoi(*argv);
16230380Smckusick 				if (sectorsize <= 0)
16330380Smckusick 					fatal("%s: bad sector size", *argv);
16410762Ssam 				goto next;
16510762Ssam 
16630380Smckusick 			case 'a':
16710762Ssam 				if (argc < 1)
16832309Smckusick 					fatal("-a: missing max contiguous blocks\n");
16910762Ssam 				argc--, argv++;
17032309Smckusick 				maxcontig = atoi(*argv);
17132309Smckusick 				if (maxcontig <= 0)
17232309Smckusick 					fatal("%s: bad max contiguous blocks\n",
17332309Smckusick 						*argv);
17410762Ssam 				goto next;
17510762Ssam 
17610762Ssam 			case 'b':
17710762Ssam 				if (argc < 1)
17810762Ssam 					fatal("-b: missing block size");
17910762Ssam 				argc--, argv++;
18010762Ssam 				bsize = atoi(*argv);
18130380Smckusick 				if (bsize < MINBSIZE)
18210762Ssam 					fatal("%s: bad block size", *argv);
18310762Ssam 				goto next;
18410762Ssam 
18530380Smckusick 			case 'c':
18630380Smckusick 				if (argc < 1)
18730380Smckusick 					fatal("-c: missing cylinders/group");
18830380Smckusick 				argc--, argv++;
18930380Smckusick 				cpg = atoi(*argv);
19030380Smckusick 				if (cpg <= 0)
19130380Smckusick 					fatal("%s: bad cylinders/group", *argv);
19232119Smckusick 				cpgflg++;
19330380Smckusick 				goto next;
19430380Smckusick 
19530380Smckusick 			case 'd':
19630380Smckusick 				if (argc < 1)
19732309Smckusick 					fatal("-d: missing rotational delay\n");
19830380Smckusick 				argc--, argv++;
19932309Smckusick 				rotdelay = atoi(*argv);
20032309Smckusick 				if (rotdelay < 0)
20132309Smckusick 					fatal("%s: bad rotational delay\n",
20232309Smckusick 						*argv);
20330380Smckusick 				goto next;
20430380Smckusick 
20532309Smckusick 			case 'e':
20632309Smckusick 				if (argc < 1)
20732309Smckusick 					fatal("-e: missing blocks pre file in a cyl group\n");
20832309Smckusick 				argc--, argv++;
20932309Smckusick 				maxbpg = atoi(*argv);
21032309Smckusick 				if (maxbpg <= 0)
21132309Smckusick 					fatal("%s: bad blocks per file in a cyl group\n",
21232309Smckusick 						*argv);
21332309Smckusick 				goto next;
21432309Smckusick 
21510762Ssam 			case 'f':
21610762Ssam 				if (argc < 1)
21710762Ssam 					fatal("-f: missing frag size");
21810762Ssam 				argc--, argv++;
21910762Ssam 				fsize = atoi(*argv);
22030380Smckusick 				if (fsize <= 0)
22110762Ssam 					fatal("%s: bad frag size", *argv);
22210762Ssam 				goto next;
22310762Ssam 
22430380Smckusick 			case 'i':
22510762Ssam 				if (argc < 1)
22630380Smckusick 					fatal("-i: missing bytes per inode\n");
22710762Ssam 				argc--, argv++;
22830380Smckusick 				density = atoi(*argv);
22930380Smckusick 				if (density <= 0)
23030380Smckusick 					fatal("%s: bad bytes per inode\n",
23130380Smckusick 						*argv);
23210762Ssam 				goto next;
23310762Ssam 
23430386Smckusick 			case 'k':
23530386Smckusick 				if (argc < 1)
23630386Smckusick 					fatal("-k: track skew");
23730386Smckusick 				argc--, argv++;
23830386Smckusick 				trackskew = atoi(*argv);
23930386Smckusick 				if (trackskew < 0)
24030386Smckusick 					fatal("%s: bad track skew", *argv);
24130386Smckusick 				goto next;
24230386Smckusick 
24330386Smckusick 			case 'l':
24430386Smckusick 				if (argc < 1)
24530386Smckusick 					fatal("-l: interleave");
24630386Smckusick 				argc--, argv++;
24730386Smckusick 				interleave = atoi(*argv);
24830386Smckusick 				if (interleave <= 0)
24930386Smckusick 					fatal("%s: bad interleave", *argv);
25030386Smckusick 				goto next;
25130386Smckusick 
25211069Ssam 			case 'm':
25311069Ssam 				if (argc < 1)
25411069Ssam 					fatal("-m: missing free space %%\n");
25511069Ssam 				argc--, argv++;
25611069Ssam 				minfree = atoi(*argv);
25711069Ssam 				if (minfree < 0 || minfree > 99)
25811069Ssam 					fatal("%s: bad free space %%\n",
25911069Ssam 						*argv);
26011069Ssam 				goto next;
26111069Ssam 
26230380Smckusick 			case 'o':
26330380Smckusick 				if (argc < 1)
26430380Smckusick 					fatal("-o: missing optimization preference");
26530380Smckusick 				argc--, argv++;
26630380Smckusick 				if (strcmp(*argv, "space") == 0)
26730380Smckusick 					opt = FS_OPTSPACE;
26830380Smckusick 				else if (strcmp(*argv, "time") == 0)
26930380Smckusick 					opt = FS_OPTTIME;
27030380Smckusick 				else
27130380Smckusick 					fatal("%s: bad optimization preference %s",
27230380Smckusick 					    *argv,
27330380Smckusick 					    "(options are `space' or `time')");
27430380Smckusick 				goto next;
27530380Smckusick 
27630386Smckusick 			case 'p':
27730386Smckusick 				if (argc < 1)
27830386Smckusick 					fatal("-p: spare sectors per track");
27930386Smckusick 				argc--, argv++;
28030386Smckusick 				trackspares = atoi(*argv);
28130386Smckusick 				if (trackspares < 0)
28230386Smckusick 					fatal("%s: bad spare sectors per track", *argv);
28330386Smckusick 				goto next;
28430386Smckusick 
28511069Ssam 			case 'r':
28611069Ssam 				if (argc < 1)
28711069Ssam 					fatal("-r: missing revs/minute\n");
28811069Ssam 				argc--, argv++;
28911069Ssam 				rpm = atoi(*argv);
29030380Smckusick 				if (rpm <= 0)
29111069Ssam 					fatal("%s: bad revs/minute\n", *argv);
29211069Ssam 				goto next;
29311069Ssam 
29430380Smckusick 			case 's':
29514884Smckusick 				if (argc < 1)
29630380Smckusick 					fatal("-s: missing file system size");
29714884Smckusick 				argc--, argv++;
29830380Smckusick 				fssize = atoi(*argv);
29930380Smckusick 				if (fssize <= 0)
30030380Smckusick 					fatal("%s: bad file system size",
30114884Smckusick 						*argv);
30214884Smckusick 				goto next;
30314884Smckusick 
30430380Smckusick 			case 't':
30530380Smckusick 				if (argc < 1)
30630380Smckusick 					fatal("-t: missing track total");
30730380Smckusick 				argc--, argv++;
30830380Smckusick 				ntracks = atoi(*argv);
30930380Smckusick 				if (ntracks <= 0)
31030380Smckusick 					fatal("%s: bad total tracks", *argv);
31130380Smckusick 				goto next;
31230380Smckusick 
31332309Smckusick 			case 'u':
31432309Smckusick 				if (argc < 1)
31532309Smckusick 					fatal("-u: missing sectors/track");
31632309Smckusick 				argc--, argv++;
31732309Smckusick 				nsectors = atoi(*argv);
31832309Smckusick 				if (nsectors <= 0)
31932309Smckusick 					fatal("%s: bad sectors/track", *argv);
32032309Smckusick 				goto next;
32132309Smckusick 
32232309Smckusick 			case 'x':
32332309Smckusick 				if (argc < 1)
32432309Smckusick 					fatal("-x: spare sectors per cylinder");
32532309Smckusick 				argc--, argv++;
32632309Smckusick 				cylspares = atoi(*argv);
32732309Smckusick 				if (cylspares < 0)
32832309Smckusick 					fatal("%s: bad spare sectors per cylinder", *argv);
32932309Smckusick 				goto next;
33032309Smckusick 
33110762Ssam 			default:
332*32320Sbostic 				fatal("-%c: unknown flag", *cp);
33310762Ssam 			}
33410762Ssam next:
33510762Ssam 		argc--, argv++;
33610762Ssam 	}
33730380Smckusick 	if (argc < 1) {
33831680Skarels #ifdef COMPAT
33931680Skarels 		fprintf(stderr,
34031680Skarels 		"usage: newfs [ fsoptions ] special-device [device-type]\n");
34131680Skarels #else
34230380Smckusick 		fprintf(stderr, "usage: newfs [ fsoptions ] special-device\n");
34331680Skarels #endif
34430380Smckusick 		fprintf(stderr, "where fsoptions are:\n");
34516945Smckusick 		fprintf(stderr, "\t-N do not create file system, %s\n",
34616945Smckusick 			"just print out parameters");
34711057Ssam 		fprintf(stderr, "\t-b block size\n");
34811057Ssam 		fprintf(stderr, "\t-f frag size\n");
34911069Ssam 		fprintf(stderr, "\t-m minimum free space %%\n");
35024702Smckusick 		fprintf(stderr, "\t-o optimization preference %s\n",
35124702Smckusick 			"(`space' or `time')");
35232309Smckusick 		fprintf(stderr, "\t-a maximum contiguous blocks\n");
35332309Smckusick 		fprintf(stderr, "\t-d rotational delay between %s\n",
35432309Smckusick 			"contiguous blocks");
35532309Smckusick 		fprintf(stderr, "\t-e maximum blocks per file in a %s\n",
35632309Smckusick 			"cylinder group");
35730398Smckusick 		fprintf(stderr, "\t-i number of bytes per inode\n");
35830398Smckusick 		fprintf(stderr, "\t-c cylinders/group\n");
35930398Smckusick 		fprintf(stderr, "\t-s file system size (sectors)\n");
36011069Ssam 		fprintf(stderr, "\t-r revolutions/minute\n");
36111057Ssam 		fprintf(stderr, "\t-S sector size\n");
36232309Smckusick 		fprintf(stderr, "\t-u sectors/track\n");
36330398Smckusick 		fprintf(stderr, "\t-t tracks/cylinder\n");
36430398Smckusick 		fprintf(stderr, "\t-p spare sectors per track\n");
36532309Smckusick 		fprintf(stderr, "\t-x spare sectors per cylinder\n");
36630386Smckusick 		fprintf(stderr, "\t-l hardware sector interleave\n");
36730386Smckusick 		fprintf(stderr, "\t-k sector 0 skew, per track\n");
36810762Ssam 		exit(1);
36910762Ssam 	}
37032309Smckusick 	if (maxbpg == 0)
37132309Smckusick 		maxbpg = MAXBLKPG(bsize);
37210762Ssam 	special = argv[0];
37314064Smckusick 	cp = rindex(special, '/');
37414064Smckusick 	if (cp != 0)
37514064Smckusick 		special = cp + 1;
37614321Ssam 	if (*special == 'r' && special[1] != 'a' && special[1] != 'b')
37714064Smckusick 		special++;
37814064Smckusick 	special = sprintf(device, "/dev/r%s", special);
37930380Smckusick 	if (!Nflag) {
38030380Smckusick 		fso = open(special, O_WRONLY);
38130380Smckusick 		if (fso < 0) {
38230380Smckusick 			perror(special);
38330380Smckusick 			exit(1);
38430380Smckusick 		}
38530380Smckusick 	} else
38630380Smckusick 		fso = -1;
38730380Smckusick 	fsi = open(special, O_RDONLY);
38830380Smckusick 	if (fsi < 0) {
38930380Smckusick 		perror(special);
39030380Smckusick 		exit(1);
39130380Smckusick 	}
39230380Smckusick 	if (fstat(fsi, &st) < 0) {
39311069Ssam 		fprintf(stderr, "newfs: "); perror(special);
39410762Ssam 		exit(2);
39510762Ssam 	}
39614064Smckusick 	if ((st.st_mode & S_IFMT) != S_IFCHR)
39714064Smckusick 		fatal("%s: not a character device", special);
39810762Ssam 	cp = index(argv[0], '\0') - 1;
39930380Smckusick 	if (cp == 0 || (*cp < 'a' || *cp > 'h') && !isdigit(*cp))
40010762Ssam 		fatal("%s: can't figure out file system partition", argv[0]);
40131680Skarels #ifdef COMPAT
40231680Skarels 	lp = getdisklabel(special, fsi, argv[1]);
40331680Skarels #else
40430380Smckusick 	lp = getdisklabel(special, fsi);
40531680Skarels #endif
40630380Smckusick 	if (isdigit(*cp))
40730380Smckusick 		pp = &lp->d_partitions[0];
40830380Smckusick 	else
40930380Smckusick 		pp = &lp->d_partitions[*cp - 'a'];
41030380Smckusick 	if (pp->p_size == 0)
41130380Smckusick 		fatal("%s: `%c' partition is unavailable", argv[0], *cp);
41230380Smckusick 	if (fssize == 0)
41310762Ssam 		fssize = pp->p_size;
41430380Smckusick 	if (fssize > pp->p_size)
41530380Smckusick 	       fatal("%s: maximum file system size on the `%c' partition is %d",
41630380Smckusick 			argv[0], *cp, pp->p_size);
41730380Smckusick 	if (rpm == 0) {
41830380Smckusick 		rpm = lp->d_rpm;
41930380Smckusick 		if (rpm <= 0)
42030743Skarels 			rpm = 3600;
42110762Ssam 	}
42230380Smckusick 	if (ntracks == 0) {
42330380Smckusick 		ntracks = lp->d_ntracks;
42430380Smckusick 		if (ntracks <= 0)
42530743Skarels 			fatal("%s: no default #tracks", argv[0]);
42630380Smckusick 	}
42710762Ssam 	if (nsectors == 0) {
42830380Smckusick 		nsectors = lp->d_nsectors;
42930380Smckusick 		if (nsectors <= 0)
43030743Skarels 			fatal("%s: no default #sectors/track", argv[0]);
43110762Ssam 	}
43210762Ssam 	if (sectorsize == 0) {
43330380Smckusick 		sectorsize = lp->d_secsize;
43430380Smckusick 		if (sectorsize <= 0)
43530743Skarels 			fatal("%s: no default sector size", argv[0]);
43610762Ssam 	}
43730386Smckusick 	if (trackskew == -1) {
43830386Smckusick 		trackskew = lp->d_trackskew;
43930386Smckusick 		if (trackskew < 0)
44030743Skarels 			trackskew = 0;
44130386Smckusick 	}
44230386Smckusick 	if (interleave == 0) {
44330386Smckusick 		interleave = lp->d_interleave;
44430386Smckusick 		if (interleave <= 0)
44530743Skarels 			interleave = 1;
44630386Smckusick 	}
44710762Ssam 	if (fsize == 0) {
44810762Ssam 		fsize = pp->p_fsize;
44930380Smckusick 		if (fsize <= 0)
45030380Smckusick 			fsize = MAX(DFL_FRAGSIZE, lp->d_secsize);
45110762Ssam 	}
45230380Smckusick 	if (bsize == 0) {
45330380Smckusick 		bsize = pp->p_frag * pp->p_fsize;
45430380Smckusick 		if (bsize <= 0)
45530380Smckusick 			bsize = MIN(DFL_BLKSIZE, 8 * fsize);
45611069Ssam 	}
45724702Smckusick 	if (minfree < 10 && opt != FS_OPTSPACE) {
45830380Smckusick 		fprintf(stderr, "Warning: changing optimization to space ");
45930380Smckusick 		fprintf(stderr, "because minfree is less than 10%%\n");
46024702Smckusick 		opt = FS_OPTSPACE;
46124702Smckusick 	}
46230386Smckusick 	if (trackspares == -1) {
46330386Smckusick 		trackspares = lp->d_sparespertrack;
46430386Smckusick 		if (trackspares < 0)
46530743Skarels 			trackspares = 0;
46630386Smckusick 	}
46730386Smckusick 	nphyssectors = nsectors + trackspares;
46830386Smckusick 	if (cylspares == -1) {
46930386Smckusick 		cylspares = lp->d_sparespercyl;
47030386Smckusick 		if (cylspares < 0)
47130743Skarels 			cylspares = 0;
47230386Smckusick 	}
47330386Smckusick 	secpercyl = nsectors * ntracks - cylspares;
47430380Smckusick 	if (secpercyl != lp->d_secpercyl)
47530380Smckusick 		fprintf(stderr, "%s (%d) %s (%d)\n",
47630380Smckusick 			"Warning: calculated sectors per cylinder", secpercyl,
47730380Smckusick 			"disagrees with disk label", lp->d_secpercyl);
47830386Smckusick 	headswitch = lp->d_headswitch;
47930386Smckusick 	trackseek = lp->d_trkseek;
48030691Skarels 	bbsize = lp->d_bbsize;
48130691Skarels 	sbsize = lp->d_sbsize;
48230380Smckusick 	oldpartition = *pp;
48330691Skarels #ifdef tahoe
48430691Skarels 	realsectorsize = sectorsize;
48530862Skarels 	if (sectorsize != DEV_BSIZE) {		/* XXX */
48630691Skarels 		int secperblk = DEV_BSIZE / sectorsize;
48730691Skarels 
48830691Skarels 		sectorsize = DEV_BSIZE;
48930691Skarels 		nsectors /= secperblk;
49030691Skarels 		nphyssectors /= secperblk;
49130691Skarels 		secpercyl /= secperblk;
49230691Skarels 		fssize /= secperblk;
49330691Skarels 		pp->p_size /= secperblk;
49430691Skarels 	}
49530691Skarels #endif
49630380Smckusick 	mkfs(pp, special, fsi, fso);
49730691Skarels #ifdef tahoe
49830691Skarels 	if (realsectorsize != DEV_BSIZE)
49930691Skarels 		pp->p_size *= DEV_BSIZE / realsectorsize;
50030691Skarels #endif
50130380Smckusick 	if (!Nflag && bcmp(pp, &oldpartition, sizeof(oldpartition)))
50230380Smckusick 		rewritelabel(special, fso, lp);
50330380Smckusick 	exit(0);
50430380Smckusick }
50530380Smckusick 
50631680Skarels #ifdef COMPAT
50730380Smckusick struct disklabel *
50831680Skarels getdisklabel(s, fd, type)
50931680Skarels 	char *s, *type;
51031680Skarels 	int fd;
51131680Skarels {
51231680Skarels 	static struct disklabel lab;
51331680Skarels 	struct disklabel *getdiskbyname();
51431680Skarels 
51531680Skarels 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
51631680Skarels 		if (type == NULL) {
51731680Skarels 			perror("ioctl (GDINFO)");
51831680Skarels 			fatal(
51931680Skarels 		   "%s: can't read disk label; disk type must be specified", s);
52031680Skarels 		}
52131680Skarels 		unlabelled++;
52231680Skarels 		return (getdiskbyname(type));
52331680Skarels 	}
52431680Skarels 	return (&lab);
52531680Skarels }
52631680Skarels #else
52731680Skarels struct disklabel *
52830380Smckusick getdisklabel(s, fd)
52930380Smckusick 	char *s;
53031680Skarels 	int fd;
53130380Smckusick {
53230380Smckusick 	static struct disklabel lab;
53330380Smckusick 
53430380Smckusick 	if (ioctl(fd, DIOCGDINFO, (char *)&lab) < 0) {
53530380Smckusick 		perror("ioctl (GDINFO)");
53630380Smckusick 		fatal("%s: can't read disk label", s);
53710762Ssam 	}
53830380Smckusick 	return (&lab);
53930380Smckusick }
54031680Skarels #endif
54110762Ssam 
54230380Smckusick rewritelabel(s, fd, lp)
54330380Smckusick 	char *s;
54430380Smckusick 	int fd;
54530380Smckusick 	register struct disklabel *lp;
54630380Smckusick {
54730380Smckusick 
54831680Skarels #ifdef COMPAT
54931680Skarels 	if (unlabelled)
55031680Skarels 		return;
55131680Skarels #endif
55230380Smckusick 	lp->d_checksum = 0;
55330380Smckusick 	lp->d_checksum = dkcksum(lp);
55430380Smckusick 	if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) {
55530380Smckusick 		perror("ioctl (GWINFO)");
55630380Smckusick 		fatal("%s: can't rewrite disk label", s);
55710762Ssam 	}
55830446Skarels #if vax
55930446Skarels 	if (lp->d_type == DTYPE_SMD && lp->d_flags & D_BADSECT) {
56030446Skarels 		register i;
56130691Skarels 		int cfd;
56230446Skarels 		daddr_t alt;
56330691Skarels 		char specname[64];
56430691Skarels 		char blk[1024];
56531045Ssam 		char *cp;
56630446Skarels 
56730691Skarels 		/*
56830691Skarels 		 * Make name for 'c' partition.
56930691Skarels 		 */
57030691Skarels 		strcpy(specname, s);
57130691Skarels 		cp = specname + strlen(specname) - 1;
57230691Skarels 		if (!isdigit(*cp))
57330691Skarels 			*cp = 'c';
57430691Skarels 		cfd = open(specname, O_WRONLY);
57530691Skarels 		if (cfd < 0) {
57630691Skarels 			perror(specname);
57730691Skarels 			exit(2);
57830691Skarels 		}
57930691Skarels 		bzero(blk, sizeof(blk));
58030691Skarels 		*(struct disklabel *)(blk + LABELOFFSET) = *lp;
58130446Skarels 		alt = lp->d_ncylinders * lp->d_secpercyl - lp->d_nsectors;
58230446Skarels 		for (i = 1; i < 11 && i < lp->d_nsectors; i += 2) {
58331680Skarels 			if (lseek(cfd, (off_t)(alt + i) * lp->d_secsize, L_SET) == -1) {
58431680Skarels 				perror("lseek to badsector area");
58531680Skarels 				exit(30);
58631680Skarels 			}
58730691Skarels 			if (write(cfd, blk, lp->d_secsize) < lp->d_secsize) {
58830446Skarels 				int oerrno = errno;
58930446Skarels 				fprintf(stderr, "alternate label %d ", i/2);
59030446Skarels 				errno = oerrno;
59130446Skarels 				perror("write");
59230446Skarels 			}
59330380Smckusick 		}
59430380Smckusick 	}
59530446Skarels #endif
59610762Ssam }
59710762Ssam 
59810762Ssam /*VARARGS*/
59910762Ssam fatal(fmt, arg1, arg2)
60010762Ssam 	char *fmt;
60110762Ssam {
60210762Ssam 
60311069Ssam 	fprintf(stderr, "newfs: ");
60410762Ssam 	fprintf(stderr, fmt, arg1, arg2);
60510762Ssam 	putc('\n', stderr);
60610762Ssam 	exit(10);
60710762Ssam }
608