Home | History | Annotate | Line # | Download | only in diskpart
diskpart.c revision 1.15.24.1
      1        1.1       cgd /*
      2        1.7     mikel  * Copyright (c) 1983, 1988, 1993
      3        1.7     mikel  *	The Regents of the University of California.  All rights reserved.
      4        1.1       cgd  *
      5        1.1       cgd  * Redistribution and use in source and binary forms, with or without
      6        1.1       cgd  * modification, are permitted provided that the following conditions
      7        1.1       cgd  * are met:
      8        1.1       cgd  * 1. Redistributions of source code must retain the above copyright
      9        1.1       cgd  *    notice, this list of conditions and the following disclaimer.
     10        1.1       cgd  * 2. Redistributions in binary form must reproduce the above copyright
     11        1.1       cgd  *    notice, this list of conditions and the following disclaimer in the
     12        1.1       cgd  *    documentation and/or other materials provided with the distribution.
     13       1.13       agc  * 3. Neither the name of the University nor the names of its contributors
     14        1.1       cgd  *    may be used to endorse or promote products derived from this software
     15        1.1       cgd  *    without specific prior written permission.
     16        1.1       cgd  *
     17        1.1       cgd  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     18        1.1       cgd  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     19        1.1       cgd  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     20        1.1       cgd  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     21        1.1       cgd  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     22        1.1       cgd  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     23        1.1       cgd  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     24        1.1       cgd  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     25        1.1       cgd  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     26        1.1       cgd  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     27        1.1       cgd  * SUCH DAMAGE.
     28        1.1       cgd  */
     29        1.1       cgd 
     30        1.9     lukem #include <sys/cdefs.h>
     31        1.1       cgd #ifndef lint
     32        1.9     lukem __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\n\
     33        1.9     lukem 	The Regents of the University of California.  All rights reserved.\n");
     34        1.1       cgd #endif /* not lint */
     35        1.1       cgd 
     36        1.1       cgd #ifndef lint
     37        1.9     lukem #if 0
     38        1.9     lukem static char sccsid[] = "from: @(#)diskpart.c	8.3 (Berkeley) 11/30/94";
     39        1.9     lukem #else
     40  1.15.24.1      yamt __RCSID("$NetBSD: diskpart.c,v 1.15.24.1 2008/05/18 12:36:15 yamt Exp $");
     41        1.9     lukem #endif
     42        1.1       cgd #endif /* not lint */
     43        1.1       cgd 
     44        1.1       cgd /*
     45        1.1       cgd  * Program to calculate standard disk partition sizes.
     46        1.1       cgd  */
     47        1.1       cgd #include <sys/param.h>
     48        1.1       cgd #define DKTYPENAMES
     49        1.1       cgd #include <sys/disklabel.h>
     50        1.1       cgd 
     51        1.8     lukem #include <ctype.h>
     52       1.11      tron #include <disktab.h>
     53        1.8     lukem #include <limits.h>
     54        1.1       cgd #include <stdio.h>
     55        1.8     lukem #include <stdlib.h>
     56        1.7     mikel #include <string.h>
     57        1.8     lukem #include <unistd.h>
     58        1.1       cgd 
     59        1.1       cgd #define	for_now			/* show all of `c' partition for disklabel */
     60        1.1       cgd #define	NPARTITIONS	8
     61        1.1       cgd #define	PART(x)		(x - 'a')
     62        1.1       cgd 
     63        1.1       cgd /*
     64        1.1       cgd  * Default partition sizes, where they exist.
     65        1.1       cgd  */
     66        1.1       cgd #define	NDEFAULTS	4
     67        1.1       cgd int	defpart[NDEFAULTS][NPARTITIONS] = {
     68        1.1       cgd    { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 },	/* ~ 356+ Mbytes */
     69        1.1       cgd    { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 },	/* ~ 206-355 Mbytes */
     70        1.1       cgd    { 15884, 33440, 0, 15884, 55936, 0, 0, 0 },		/* ~ 61-205 Mbytes */
     71        1.1       cgd    { 15884, 10032, 0, 15884, 0, 0, 0, 0 },		/* ~ 20-60 Mbytes */
     72        1.1       cgd };
     73        1.1       cgd 
     74        1.1       cgd /*
     75        1.1       cgd  * Each array defines a layout for a disk;
     76        1.1       cgd  * that is, the collection of partitions totally
     77        1.1       cgd  * covers the physical space on a disk.
     78        1.1       cgd  */
     79        1.1       cgd #define	NLAYOUTS	3
     80        1.1       cgd char	layouts[NLAYOUTS][NPARTITIONS] = {
     81        1.1       cgd    { 'a', 'b', 'h', 'g' },
     82        1.1       cgd    { 'a', 'b', 'h', 'd', 'e', 'f' },
     83        1.1       cgd    { 'c' },
     84        1.1       cgd };
     85        1.1       cgd 
     86        1.1       cgd /*
     87        1.1       cgd  * Default disk block and disk block fragment
     88        1.1       cgd  * sizes for each file system.  Those file systems
     89        1.1       cgd  * with zero block and frag sizes are special cases
     90        1.1       cgd  * (e.g. swap areas or for access to the entire device).
     91        1.1       cgd  */
     92        1.1       cgd struct	partition defparam[NPARTITIONS] = {
     93       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, },		/* a */
     94       1.12  drochner 	{ 0, 0, { 1024 }, FS_SWAP,   8, { 0 }, },		/* b */
     95       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, },		/* c */
     96       1.12  drochner 	{ 0, 0, {  512 }, FS_UNUSED, 8, { 0 }, },		/* d */
     97       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, },		/* e */
     98       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, },		/* f */
     99       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, },		/* g */
    100       1.12  drochner 	{ 0, 0, { 1024 }, FS_UNUSED, 8, { 0 }, }		/* h */
    101        1.1       cgd };
    102        1.1       cgd 
    103        1.1       cgd /*
    104        1.1       cgd  * Each disk has some space reserved for a bad sector
    105        1.1       cgd  * forwarding table.  DEC standard 144 uses the first
    106        1.1       cgd  * 5 even numbered sectors in the last track of the
    107        1.1       cgd  * last cylinder for replicated storage of the bad sector
    108        1.1       cgd  * table; another 126 sectors past this is needed as a
    109        1.1       cgd  * pool of replacement sectors.
    110        1.1       cgd  */
    111        1.1       cgd int	badsecttable = 126;	/* # sectors */
    112        1.1       cgd 
    113        1.1       cgd int	pflag;			/* print device driver partition tables */
    114        1.1       cgd int	dflag;			/* print disktab entry */
    115        1.1       cgd 
    116       1.10   mycroft int	gettype __P((const char *, const char *const *));
    117        1.9     lukem int	main __P((int, char **));
    118        1.8     lukem struct disklabel *promptfordisk __P((const char *));
    119        1.8     lukem void	usage __P((void));
    120        1.1       cgd 
    121        1.8     lukem int
    122        1.1       cgd main(argc, argv)
    123        1.1       cgd 	int argc;
    124        1.1       cgd 	char *argv[];
    125        1.1       cgd {
    126        1.8     lukem 
    127        1.1       cgd 	struct disklabel *dp;
    128        1.8     lukem 	int curcyl, spc, def, part, layout, j, ch;
    129        1.1       cgd 	int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS];
    130        1.8     lukem 	off_t totsize = 0;
    131  1.15.24.1      yamt 	const char *tyname;
    132  1.15.24.1      yamt 	char *lp;
    133        1.1       cgd 
    134        1.8     lukem 	while ((ch = getopt(argc, argv, "pds:")) != -1) {
    135        1.8     lukem 		switch (ch) {
    136        1.8     lukem 		case 'd':
    137        1.8     lukem 			dflag++;
    138        1.8     lukem 			break;
    139        1.8     lukem 
    140        1.8     lukem 		case 'p':
    141        1.8     lukem 			pflag++;
    142        1.8     lukem 			break;
    143        1.8     lukem 
    144        1.8     lukem 		case 's':
    145        1.8     lukem 			totsize = strtoul(optarg, &lp, 10);
    146        1.8     lukem 			if (*lp != '\0')
    147        1.8     lukem 				usage();
    148        1.8     lukem 			break;
    149        1.8     lukem 
    150        1.8     lukem 		case '?':
    151        1.8     lukem 		default:
    152        1.8     lukem 			usage();
    153        1.8     lukem 			/* NOTREACHED */
    154        1.8     lukem 		}
    155        1.1       cgd 	}
    156        1.8     lukem 	argc -= optind;
    157        1.8     lukem 	argv += optind;
    158        1.8     lukem 
    159        1.8     lukem 	if (argc != 1) {
    160        1.8     lukem 		usage();
    161        1.8     lukem 		/* NOTREACHED */
    162        1.1       cgd 	}
    163        1.8     lukem 
    164        1.1       cgd 	dp = getdiskbyname(*argv);
    165        1.1       cgd 	if (dp == NULL) {
    166        1.1       cgd 		if (isatty(0))
    167        1.1       cgd 			dp = promptfordisk(*argv);
    168        1.1       cgd 		if (dp == NULL) {
    169        1.1       cgd 			fprintf(stderr, "%s: unknown disk type\n", *argv);
    170        1.8     lukem 			exit(1);
    171        1.1       cgd 		}
    172        1.1       cgd 	}
    173        1.8     lukem 	if (dp->d_flags & D_REMOVABLE)
    174        1.8     lukem 		tyname = "removable";
    175        1.8     lukem 	else if (dp->d_flags & D_RAMDISK)
    176        1.8     lukem 		tyname = "simulated";
    177        1.8     lukem 	else
    178        1.8     lukem 		tyname = "winchester";
    179        1.1       cgd 	spc = dp->d_secpercyl;
    180        1.1       cgd 	/*
    181        1.1       cgd 	 * Bad sector table contains one track for the replicated
    182        1.1       cgd 	 * copies of the table and enough full tracks preceding
    183        1.1       cgd 	 * the last track to hold the pool of free blocks to which
    184        1.1       cgd 	 * bad sectors are mapped.
    185        1.1       cgd 	 * If disk size was specified explicitly, use specified size.
    186        1.1       cgd 	 */
    187        1.1       cgd 	if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT &&
    188        1.1       cgd 	    totsize == 0) {
    189        1.1       cgd 		badsecttable = dp->d_nsectors +
    190        1.1       cgd 		    roundup(badsecttable, dp->d_nsectors);
    191        1.1       cgd 		threshhold = howmany(spc, badsecttable);
    192        1.1       cgd 	} else {
    193        1.1       cgd 		badsecttable = 0;
    194        1.1       cgd 		threshhold = 0;
    195        1.1       cgd 	}
    196        1.1       cgd 	/*
    197        1.1       cgd 	 * If disk size was specified, recompute number of cylinders
    198        1.1       cgd 	 * that may be used, and set badsecttable to any remaining
    199        1.1       cgd 	 * fraction of the last cylinder.
    200        1.1       cgd 	 */
    201        1.1       cgd 	if (totsize != 0) {
    202        1.1       cgd 		dp->d_ncylinders = howmany(totsize, spc);
    203        1.1       cgd 		badsecttable = spc * dp->d_ncylinders - totsize;
    204        1.1       cgd 	}
    205        1.1       cgd 
    206        1.1       cgd 	/*
    207        1.1       cgd 	 * Figure out if disk is large enough for
    208        1.1       cgd 	 * expanded swap area and 'd', 'e', and 'f'
    209        1.1       cgd 	 * partitions.  Otherwise, use smaller defaults
    210        1.1       cgd 	 * based on RK07.
    211        1.1       cgd 	 */
    212        1.1       cgd 	for (def = 0; def < NDEFAULTS; def++) {
    213        1.1       cgd 		curcyl = 0;
    214        1.1       cgd 		for (part = PART('a'); part < NPARTITIONS; part++)
    215        1.1       cgd 			curcyl += howmany(defpart[def][part], spc);
    216        1.1       cgd 		if (curcyl < dp->d_ncylinders - threshhold)
    217        1.1       cgd 			break;
    218        1.1       cgd 	}
    219        1.1       cgd 	if (def >= NDEFAULTS) {
    220        1.1       cgd 		fprintf(stderr, "%s: disk too small, calculate by hand\n",
    221        1.1       cgd 			*argv);
    222        1.8     lukem 		exit(1);
    223        1.1       cgd 	}
    224        1.1       cgd 
    225        1.1       cgd 	/*
    226        1.1       cgd 	 * Calculate number of cylinders allocated to each disk
    227        1.1       cgd 	 * partition.  We may waste a bit of space here, but it's
    228        1.1       cgd 	 * in the interest of (very backward) compatibility
    229        1.1       cgd 	 * (for mixed disk systems).
    230        1.1       cgd 	 */
    231        1.1       cgd 	for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) {
    232        1.1       cgd 		numcyls[part] = 0;
    233        1.1       cgd 		if (defpart[def][part] != 0) {
    234        1.1       cgd 			numcyls[part] = howmany(defpart[def][part], spc);
    235        1.1       cgd 			curcyl += numcyls[part];
    236        1.1       cgd 		}
    237        1.1       cgd 	}
    238        1.1       cgd 	numcyls[PART('f')] = dp->d_ncylinders - curcyl;
    239        1.1       cgd 	numcyls[PART('g')] =
    240        1.1       cgd 		numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')];
    241        1.1       cgd 	numcyls[PART('c')] = dp->d_ncylinders;
    242        1.1       cgd 	defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable;
    243        1.1       cgd 	defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable;
    244        1.1       cgd 	defpart[def][PART('c')] = numcyls[PART('c')] * spc;
    245        1.1       cgd #ifndef for_now
    246        1.1       cgd 	if (totsize || !pflag)
    247        1.1       cgd #else
    248        1.1       cgd 	if (totsize)
    249        1.1       cgd #endif
    250        1.1       cgd 		defpart[def][PART('c')] -= badsecttable;
    251        1.1       cgd 
    252        1.1       cgd 	/*
    253        1.1       cgd 	 * Calculate starting cylinder number for each partition.
    254        1.1       cgd 	 * Note the 'h' partition is physically located before the
    255        1.1       cgd 	 * 'g' or 'd' partition.  This is reflected in the layout
    256        1.1       cgd 	 * arrays defined above.
    257        1.1       cgd 	 */
    258        1.1       cgd 	for (layout = 0; layout < NLAYOUTS; layout++) {
    259        1.1       cgd 		curcyl = 0;
    260        1.1       cgd 		for (lp = layouts[layout]; *lp != 0; lp++) {
    261        1.1       cgd 			startcyl[PART(*lp)] = curcyl;
    262        1.1       cgd 			curcyl += numcyls[PART(*lp)];
    263        1.1       cgd 		}
    264        1.1       cgd 	}
    265        1.1       cgd 
    266        1.1       cgd 	if (pflag) {
    267        1.1       cgd 		printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS);
    268        1.1       cgd 		for (part = PART('a'); part < NPARTITIONS; part++) {
    269        1.1       cgd 			if (numcyls[part] == 0) {
    270        1.1       cgd 				printf("\t0,\t0,\n");
    271        1.1       cgd 				continue;
    272        1.1       cgd 			}
    273        1.1       cgd 			if (dp->d_type != DTYPE_MSCP) {
    274        1.1       cgd 			       printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
    275        1.1       cgd 					defpart[def][part], startcyl[part],
    276        1.1       cgd 					'A' + part, startcyl[part],
    277        1.1       cgd 					startcyl[part] + numcyls[part] - 1);
    278        1.1       cgd 				continue;
    279        1.1       cgd 			}
    280        1.1       cgd 			printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
    281        1.1       cgd 				defpart[def][part], spc * startcyl[part],
    282        1.1       cgd 				'A' + part, spc * startcyl[part],
    283        1.1       cgd 				spc * startcyl[part] + defpart[def][part] - 1);
    284        1.1       cgd 		}
    285        1.1       cgd 		exit(0);
    286        1.1       cgd 	}
    287        1.1       cgd 	if (dflag) {
    288        1.1       cgd 		int nparts;
    289        1.1       cgd 
    290        1.1       cgd 		/*
    291        1.1       cgd 		 * In case the disk is in the ``in-between'' range
    292        1.1       cgd 		 * where the 'g' partition is smaller than the 'h'
    293        1.1       cgd 		 * partition, reverse the frag sizes so the /usr partition
    294        1.1       cgd 		 * is always set up with a frag size larger than the
    295        1.1       cgd 		 * user's partition.
    296        1.1       cgd 		 */
    297        1.1       cgd 		if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
    298        1.1       cgd 			int temp;
    299        1.1       cgd 
    300        1.1       cgd 			temp = defparam[PART('h')].p_fsize;
    301        1.1       cgd 			defparam[PART('h')].p_fsize =
    302        1.1       cgd 				defparam[PART('g')].p_fsize;
    303        1.1       cgd 			defparam[PART('g')].p_fsize = temp;
    304        1.1       cgd 		}
    305        1.1       cgd 		printf("%s:\\\n", dp->d_typename);
    306        1.1       cgd 		printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname,
    307        1.1       cgd 			dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
    308        1.1       cgd 		if (dp->d_secpercyl != dp->d_nsectors * dp->d_ntracks)
    309        1.1       cgd 			printf("sc#%d:", dp->d_secpercyl);
    310        1.1       cgd 		if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT)
    311        1.1       cgd 			printf("sf:");
    312        1.1       cgd 		printf("\\\n\t:dt=%s:", dktypenames[dp->d_type]);
    313        1.1       cgd 		for (part = NDDATA - 1; part >= 0; part--)
    314        1.1       cgd 			if (dp->d_drivedata[part])
    315        1.1       cgd 				break;
    316        1.1       cgd 		for (j = 0; j <= part; j++)
    317        1.1       cgd 			printf("d%d#%d:", j, dp->d_drivedata[j]);
    318        1.1       cgd 		printf("\\\n");
    319        1.1       cgd 		for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
    320        1.1       cgd 			if (defpart[def][part] != 0)
    321        1.1       cgd 				nparts++;
    322        1.1       cgd 		for (part = PART('a'); part < NPARTITIONS; part++) {
    323        1.1       cgd 			if (defpart[def][part] == 0)
    324        1.1       cgd 				continue;
    325        1.1       cgd 			printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
    326        1.1       cgd 			printf("o%c#%d:b%c#%d:f%c#%d:",
    327        1.1       cgd 			    'a' + part, spc * startcyl[part],
    328        1.1       cgd 			    'a' + part,
    329        1.1       cgd 			    defparam[part].p_frag * defparam[part].p_fsize,
    330        1.1       cgd 			    'a' + part, defparam[part].p_fsize);
    331        1.1       cgd 			if (defparam[part].p_fstype == FS_SWAP)
    332        1.1       cgd 				printf("t%c=swap:", 'a' + part);
    333        1.1       cgd 			nparts--;
    334        1.1       cgd 			printf("%s\n", nparts > 0 ? "\\" : "");
    335        1.1       cgd 		}
    336        1.1       cgd #ifdef for_now
    337        1.1       cgd 		defpart[def][PART('c')] -= badsecttable;
    338        1.1       cgd 		part = PART('c');
    339        1.1       cgd 		printf("#\t:p%c#%d:", 'a' + part, defpart[def][part]);
    340        1.1       cgd 		printf("o%c#%d:b%c#%d:f%c#%d:\n",
    341        1.1       cgd 		    'a' + part, spc * startcyl[part],
    342        1.1       cgd 		    'a' + part,
    343        1.1       cgd 		    defparam[part].p_frag * defparam[part].p_fsize,
    344        1.1       cgd 		    'a' + part, defparam[part].p_fsize);
    345        1.1       cgd #endif
    346        1.1       cgd 		exit(0);
    347        1.1       cgd 	}
    348        1.1       cgd 	printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
    349        1.1       cgd 		dp->d_typename, dp->d_nsectors, dp->d_ntracks,
    350        1.1       cgd 		dp->d_ncylinders);
    351        1.1       cgd 	printf("\n    Partition\t   Size\t Offset\t   Range\n");
    352        1.1       cgd 	for (part = PART('a'); part < NPARTITIONS; part++) {
    353        1.1       cgd 		printf("\t%c\t", 'a' + part);
    354        1.1       cgd 		if (numcyls[part] == 0) {
    355        1.1       cgd 			printf(" unused\n");
    356        1.1       cgd 			continue;
    357        1.1       cgd 		}
    358        1.1       cgd 		printf("%7d\t%7d\t%4d - %d%s\n",
    359        1.1       cgd 			defpart[def][part], startcyl[part] * spc,
    360        1.1       cgd 			startcyl[part], startcyl[part] + numcyls[part] - 1,
    361        1.1       cgd 			defpart[def][part] % spc ? "*" : "");
    362        1.1       cgd 	}
    363        1.8     lukem 	exit(0);
    364        1.1       cgd }
    365        1.1       cgd 
    366        1.1       cgd struct disklabel disk;
    367        1.1       cgd 
    368        1.1       cgd struct	field {
    369  1.15.24.1      yamt 	const char	*f_name;
    370  1.15.24.1      yamt 	const char	*f_defaults;
    371        1.7     mikel 	u_int32_t	*f_location;
    372        1.1       cgd } fields[] = {
    373        1.1       cgd 	{ "sector size",		"512",	&disk.d_secsize },
    374  1.15.24.1      yamt 	{ "#sectors/track",		NULL,	&disk.d_nsectors },
    375  1.15.24.1      yamt 	{ "#tracks/cylinder",		NULL,	&disk.d_ntracks },
    376  1.15.24.1      yamt 	{ "#cylinders",			NULL,	&disk.d_ncylinders },
    377  1.15.24.1      yamt 	{ NULL, NULL, 0 },
    378        1.1       cgd };
    379        1.1       cgd 
    380        1.1       cgd struct disklabel *
    381        1.1       cgd promptfordisk(name)
    382        1.8     lukem 	const char *name;
    383        1.1       cgd {
    384        1.8     lukem 	struct disklabel *dp = &disk;
    385        1.8     lukem 	struct field *fp;
    386        1.8     lukem 	int i;
    387       1.10   mycroft 	const char *const *tp;
    388       1.10   mycroft 	char buf[BUFSIZ], *cp;
    389        1.1       cgd 
    390        1.1       cgd 	strncpy(dp->d_typename, name, sizeof(dp->d_typename));
    391        1.1       cgd 	fprintf(stderr,
    392        1.1       cgd 		"%s: unknown disk type, want to supply parameters (y/n)? ",
    393        1.1       cgd 		name);
    394        1.8     lukem 	if ((fgets(buf, BUFSIZ, stdin) == NULL) || buf[0] != 'y')
    395        1.1       cgd 		return ((struct disklabel *)0);
    396        1.1       cgd 	for (;;) {
    397        1.1       cgd 		fprintf(stderr, "Disk/controller type (%s)? ", dktypenames[1]);
    398        1.8     lukem 		if (fgets(buf, BUFSIZ, stdin) == NULL)
    399        1.8     lukem 			return ((struct disklabel *)0);
    400        1.8     lukem 		if ((cp = strchr(buf, '\n')) != NULL)
    401        1.8     lukem 			*cp = '\0';
    402        1.8     lukem 		if (buf[0] == '\0') {
    403        1.1       cgd 			dp->d_type = 1;
    404        1.1       cgd 			break;
    405        1.7     mikel 		}
    406        1.7     mikel 		if ((i = gettype(buf, dktypenames)) >= 0) {
    407        1.7     mikel 			dp->d_type = i;
    408        1.7     mikel 			break;
    409        1.7     mikel 		}
    410        1.1       cgd 		fprintf(stderr, "%s: unrecognized controller type\n", buf);
    411        1.8     lukem 		fprintf(stderr, "use one of:\n");
    412        1.1       cgd 		for (tp = dktypenames; *tp; tp++)
    413        1.7     mikel 			if (strchr(*tp, ' ') == 0)
    414        1.1       cgd 				fprintf(stderr, "\t%s\n", *tp);
    415        1.1       cgd 	}
    416        1.1       cgd gettype:
    417        1.1       cgd 	dp->d_flags = 0;
    418        1.1       cgd 	fprintf(stderr, "type (winchester|removable|simulated)? ");
    419        1.8     lukem 	if (fgets(buf, BUFSIZ, stdin) == NULL)
    420        1.8     lukem 		return ((struct disklabel *)0);
    421        1.8     lukem 	if ((cp = strchr(buf, '\n')) != NULL)
    422        1.8     lukem 		*cp = '\0';
    423        1.8     lukem 	if (buf[0] == '\0')
    424        1.8     lukem 		goto gettype;
    425        1.8     lukem 	switch (buf[0]) {
    426        1.8     lukem 	case 'r':
    427        1.1       cgd 		dp->d_flags = D_REMOVABLE;
    428        1.8     lukem 		break;
    429        1.8     lukem 	case 's':
    430        1.1       cgd 		dp->d_flags = D_RAMDISK;
    431        1.8     lukem 		break;
    432        1.8     lukem 	case 'w':
    433        1.8     lukem 		break;
    434        1.8     lukem 	default:
    435        1.1       cgd 		fprintf(stderr, "%s: bad disk type\n", buf);
    436        1.8     lukem 		/* FALLTHROUGH */
    437        1.8     lukem 	case '\0':
    438        1.1       cgd 		goto gettype;
    439        1.1       cgd 	}
    440        1.1       cgd 	fprintf(stderr, "(type <cr> to get default value, if only one)\n");
    441        1.8     lukem 	if (dp->d_type == DTYPE_SMD) {
    442        1.8     lukem 		fprintf(stderr,
    443        1.8     lukem 		    "Do '%s' disks support bad144 bad block forwarding (yes)? ",
    444        1.8     lukem 		    dp->d_typename);
    445        1.8     lukem 		if (fgets(buf, BUFSIZ, stdin) == NULL)
    446        1.8     lukem 			return ((struct disklabel *)0);
    447        1.8     lukem 		if (buf[0] != 'n')
    448        1.8     lukem 			dp->d_flags |= D_BADSECT;
    449        1.8     lukem 	}
    450        1.1       cgd 	for (fp = fields; fp->f_name != NULL; fp++) {
    451        1.1       cgd again:
    452        1.1       cgd 		fprintf(stderr, "%s ", fp->f_name);
    453        1.1       cgd 		if (fp->f_defaults != NULL)
    454        1.1       cgd 			fprintf(stderr, "(%s)", fp->f_defaults);
    455        1.1       cgd 		fprintf(stderr, "? ");
    456        1.8     lukem 		if (fgets(buf, BUFSIZ, stdin) == NULL)
    457        1.8     lukem 			return ((struct disklabel *)0);
    458        1.8     lukem 		if ((cp = strchr(buf, '\n')) != NULL)
    459        1.8     lukem 			*cp = '\0';
    460        1.8     lukem 		cp = buf;
    461        1.1       cgd 		if (*cp == '\0') {
    462        1.1       cgd 			if (fp->f_defaults == NULL) {
    463        1.1       cgd 				fprintf(stderr, "no default value\n");
    464        1.1       cgd 				goto again;
    465        1.1       cgd 			}
    466  1.15.24.1      yamt 			/* XXX __UNCONST */
    467  1.15.24.1      yamt 			cp = __UNCONST(fp->f_defaults);
    468        1.1       cgd 		}
    469        1.1       cgd 		*fp->f_location = atol(cp);
    470        1.1       cgd 		if (*fp->f_location == 0) {
    471        1.1       cgd 			fprintf(stderr, "%s: bad value\n", cp);
    472        1.1       cgd 			goto again;
    473        1.1       cgd 		}
    474        1.1       cgd 	}
    475        1.1       cgd 	fprintf(stderr, "sectors/cylinder (%d)? ",
    476        1.1       cgd 	    dp->d_nsectors * dp->d_ntracks);
    477        1.8     lukem 	if (fgets(buf, BUFSIZ, stdin) == NULL)
    478        1.8     lukem 		return ((struct disklabel *)0);
    479        1.8     lukem 	if ((cp = strchr(buf, '\n')) != NULL)
    480        1.8     lukem 		*cp = '\0';
    481        1.1       cgd 	if (buf[0] == 0)
    482        1.1       cgd 		dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks;
    483        1.1       cgd 	else
    484        1.1       cgd 		dp->d_secpercyl = atol(buf);
    485        1.1       cgd 	fprintf(stderr, "Drive-type-specific parameters, <cr> to terminate:\n");
    486        1.1       cgd 	for (i = 0; i < NDDATA; i++) {
    487        1.1       cgd 		fprintf(stderr, "d%d? ", i);
    488        1.8     lukem 		if (fgets(buf, BUFSIZ, stdin) == NULL)
    489        1.8     lukem 			return ((struct disklabel *)0);
    490        1.8     lukem 		if ((cp = strchr(buf, '\n')) != NULL)
    491        1.8     lukem 			*cp = '\0';
    492        1.1       cgd 		if (buf[0] == 0)
    493        1.1       cgd 			break;
    494        1.1       cgd 		dp->d_drivedata[i] = atol(buf);
    495        1.1       cgd 	}
    496        1.1       cgd 	return (dp);
    497        1.1       cgd }
    498        1.1       cgd 
    499        1.8     lukem int
    500        1.1       cgd gettype(t, names)
    501        1.8     lukem 	const char *t;
    502       1.10   mycroft 	const char *const *names;
    503        1.1       cgd {
    504       1.10   mycroft 	const char *const *nm;
    505        1.1       cgd 
    506        1.1       cgd 	for (nm = names; *nm; nm++)
    507        1.8     lukem 		if (strcasecmp(t, *nm) == 0)
    508        1.1       cgd 			return (nm - names);
    509       1.15       dsl 	if (isdigit((unsigned char)*t))
    510        1.1       cgd 		return (atoi(t));
    511        1.1       cgd 	return (-1);
    512        1.1       cgd }
    513        1.1       cgd 
    514        1.8     lukem void
    515        1.8     lukem usage(void)
    516        1.1       cgd {
    517       1.14      jmmv 	(void)fprintf(stderr, "usage: diskpart [-dp] [-s size] disk-type\n");
    518        1.8     lukem 	exit(1);
    519        1.1       cgd }
    520