2 * Copyright (c) 1983, 1988, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 #include <sys/cdefs.h>
32 __COPYRIGHT("@(#) Copyright (c) 1983, 1988, 1993\
33 The Regents of the University of California. All rights reserved.");
38 static char sccsid
[] = "from: @(#)diskpart.c 8.3 (Berkeley) 11/30/94";
40 __RCSID("$NetBSD: diskpart.c,v 1.17 2008/07/21 13:36:58 lukem Exp $");
45 * Program to calculate standard disk partition sizes.
47 #include <sys/param.h>
49 #include <sys/disklabel.h>
59 #define for_now /* show all of `c' partition for disklabel */
61 #define PART(x) (x - 'a')
64 * Default partition sizes, where they exist.
67 int defpart
[NDEFAULTS
][NPARTITIONS
] = {
68 { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */
69 { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */
70 { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */
71 { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */
75 * Each array defines a layout for a disk;
76 * that is, the collection of partitions totally
77 * covers the physical space on a disk.
80 char layouts
[NLAYOUTS
][NPARTITIONS
] = {
81 { 'a', 'b', 'h', 'g' },
82 { 'a', 'b', 'h', 'd', 'e', 'f' },
87 * Default disk block and disk block fragment
88 * sizes for each file system. Those file systems
89 * with zero block and frag sizes are special cases
90 * (e.g. swap areas or for access to the entire device).
92 struct partition defparam
[NPARTITIONS
] = {
93 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, }, /* a */
94 { 0, 0, { 1024 }, FS_SWAP
, 8, { 0 }, }, /* b */
95 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, }, /* c */
96 { 0, 0, { 512 }, FS_UNUSED
, 8, { 0 }, }, /* d */
97 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, }, /* e */
98 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, }, /* f */
99 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, }, /* g */
100 { 0, 0, { 1024 }, FS_UNUSED
, 8, { 0 }, } /* h */
104 * Each disk has some space reserved for a bad sector
105 * forwarding table. DEC standard 144 uses the first
106 * 5 even numbered sectors in the last track of the
107 * last cylinder for replicated storage of the bad sector
108 * table; another 126 sectors past this is needed as a
109 * pool of replacement sectors.
111 int badsecttable
= 126; /* # sectors */
113 int pflag
; /* print device driver partition tables */
114 int dflag
; /* print disktab entry */
116 int gettype
__P((const char *, const char *const *));
117 int main
__P((int, char **));
118 struct disklabel
*promptfordisk
__P((const char *));
119 void usage
__P((void));
126 struct disklabel
*dp
;
127 int spc
, def
, part
, layout
, j
, ch
;
129 int threshhold
, numcyls
[NPARTITIONS
], startcyl
[NPARTITIONS
];
134 while ((ch
= getopt(argc
, argv
, "pds:")) != -1) {
145 totsize
= strtoul(optarg
, &lp
, 10);
164 dp
= getdiskbyname(*argv
);
167 dp
= promptfordisk(*argv
);
169 fprintf(stderr
, "%s: unknown disk type\n", *argv
);
173 if (dp
->d_flags
& D_REMOVABLE
)
174 tyname
= "removable";
175 else if (dp
->d_flags
& D_RAMDISK
)
176 tyname
= "simulated";
178 tyname
= "winchester";
179 spc
= dp
->d_secpercyl
;
181 * Bad sector table contains one track for the replicated
182 * copies of the table and enough full tracks preceding
183 * the last track to hold the pool of free blocks to which
184 * bad sectors are mapped.
185 * If disk size was specified explicitly, use specified size.
187 if (dp
->d_type
== DTYPE_SMD
&& dp
->d_flags
& D_BADSECT
&&
189 badsecttable
= dp
->d_nsectors
+
190 roundup(badsecttable
, dp
->d_nsectors
);
191 threshhold
= howmany(spc
, badsecttable
);
197 * If disk size was specified, recompute number of cylinders
198 * that may be used, and set badsecttable to any remaining
199 * fraction of the last cylinder.
202 dp
->d_ncylinders
= howmany(totsize
, spc
);
203 badsecttable
= spc
* dp
->d_ncylinders
- totsize
;
207 * Figure out if disk is large enough for
208 * expanded swap area and 'd', 'e', and 'f'
209 * partitions. Otherwise, use smaller defaults
212 for (def
= 0; def
< NDEFAULTS
; def
++) {
214 for (part
= PART('a'); part
< NPARTITIONS
; part
++)
215 curcyl
+= howmany(defpart
[def
][part
], spc
);
216 if (curcyl
< dp
->d_ncylinders
- threshhold
)
219 if (def
>= NDEFAULTS
) {
220 fprintf(stderr
, "%s: disk too small, calculate by hand\n",
226 * Calculate number of cylinders allocated to each disk
227 * partition. We may waste a bit of space here, but it's
228 * in the interest of (very backward) compatibility
229 * (for mixed disk systems).
231 for (curcyl
= 0, part
= PART('a'); part
< NPARTITIONS
; part
++) {
233 if (defpart
[def
][part
] != 0) {
234 numcyls
[part
] = howmany(defpart
[def
][part
], spc
);
235 curcyl
+= numcyls
[part
];
238 numcyls
[PART('f')] = dp
->d_ncylinders
- curcyl
;
240 numcyls
[PART('d')] + numcyls
[PART('e')] + numcyls
[PART('f')];
241 numcyls
[PART('c')] = dp
->d_ncylinders
;
242 defpart
[def
][PART('f')] = numcyls
[PART('f')] * spc
- badsecttable
;
243 defpart
[def
][PART('g')] = numcyls
[PART('g')] * spc
- badsecttable
;
244 defpart
[def
][PART('c')] = numcyls
[PART('c')] * spc
;
246 if (totsize
|| !pflag
)
250 defpart
[def
][PART('c')] -= badsecttable
;
253 * Calculate starting cylinder number for each partition.
254 * Note the 'h' partition is physically located before the
255 * 'g' or 'd' partition. This is reflected in the layout
256 * arrays defined above.
258 for (layout
= 0; layout
< NLAYOUTS
; layout
++) {
260 for (lp
= layouts
[layout
]; *lp
!= 0; lp
++) {
261 startcyl
[PART(*lp
)] = curcyl
;
262 curcyl
+= numcyls
[PART(*lp
)];
267 printf("}, %s_sizes[%d] = {\n", dp
->d_typename
, NPARTITIONS
);
268 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
269 if (numcyls
[part
] == 0) {
270 printf("\t0,\t0,\n");
273 if (dp
->d_type
!= DTYPE_MSCP
) {
274 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
275 defpart
[def
][part
], startcyl
[part
],
276 'A' + part
, startcyl
[part
],
277 startcyl
[part
] + numcyls
[part
] - 1);
280 printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
281 defpart
[def
][part
], spc
* startcyl
[part
],
282 'A' + part
, spc
* startcyl
[part
],
283 spc
* startcyl
[part
] + defpart
[def
][part
] - 1);
291 * In case the disk is in the ``in-between'' range
292 * where the 'g' partition is smaller than the 'h'
293 * partition, reverse the frag sizes so the /usr partition
294 * is always set up with a frag size larger than the
297 if (defpart
[def
][PART('g')] < defpart
[def
][PART('h')]) {
300 temp
= defparam
[PART('h')].p_fsize
;
301 defparam
[PART('h')].p_fsize
=
302 defparam
[PART('g')].p_fsize
;
303 defparam
[PART('g')].p_fsize
= temp
;
305 printf("%s:\\\n", dp
->d_typename
);
306 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname
,
307 dp
->d_nsectors
, dp
->d_ntracks
, dp
->d_ncylinders
);
308 if (dp
->d_secpercyl
!= dp
->d_nsectors
* dp
->d_ntracks
)
309 printf("sc#%d:", dp
->d_secpercyl
);
310 if (dp
->d_type
== DTYPE_SMD
&& dp
->d_flags
& D_BADSECT
)
312 printf("\\\n\t:dt=%s:", dktypenames
[dp
->d_type
]);
313 for (part
= NDDATA
- 1; part
>= 0; part
--)
314 if (dp
->d_drivedata
[part
])
316 for (j
= 0; j
<= part
; j
++)
317 printf("d%d#%d:", j
, dp
->d_drivedata
[j
]);
319 for (nparts
= 0, part
= PART('a'); part
< NPARTITIONS
; part
++)
320 if (defpart
[def
][part
] != 0)
322 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
323 if (defpart
[def
][part
] == 0)
325 printf("\t:p%c#%d:", 'a' + part
, defpart
[def
][part
]);
326 printf("o%c#%d:b%c#%d:f%c#%d:",
327 'a' + part
, spc
* startcyl
[part
],
329 defparam
[part
].p_frag
* defparam
[part
].p_fsize
,
330 'a' + part
, defparam
[part
].p_fsize
);
331 if (defparam
[part
].p_fstype
== FS_SWAP
)
332 printf("t%c=swap:", 'a' + part
);
334 printf("%s\n", nparts
> 0 ? "\\" : "");
337 defpart
[def
][PART('c')] -= badsecttable
;
339 printf("#\t:p%c#%d:", 'a' + part
, defpart
[def
][part
]);
340 printf("o%c#%d:b%c#%d:f%c#%d:\n",
341 'a' + part
, spc
* startcyl
[part
],
343 defparam
[part
].p_frag
* defparam
[part
].p_fsize
,
344 'a' + part
, defparam
[part
].p_fsize
);
348 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
349 dp
->d_typename
, dp
->d_nsectors
, dp
->d_ntracks
,
351 printf("\n Partition\t Size\t Offset\t Range\n");
352 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
353 printf("\t%c\t", 'a' + part
);
354 if (numcyls
[part
] == 0) {
358 printf("%7d\t%7d\t%4d - %d%s\n",
359 defpart
[def
][part
], startcyl
[part
] * spc
,
360 startcyl
[part
], startcyl
[part
] + numcyls
[part
] - 1,
361 defpart
[def
][part
] % spc
? "*" : "");
366 struct disklabel disk
;
370 const char *f_defaults
;
371 u_int32_t
*f_location
;
373 { "sector size", "512", &disk
.d_secsize
},
374 { "#sectors/track", NULL
, &disk
.d_nsectors
},
375 { "#tracks/cylinder", NULL
, &disk
.d_ntracks
},
376 { "#cylinders", NULL
, &disk
.d_ncylinders
},
384 struct disklabel
*dp
= &disk
;
387 const char *const *tp
;
388 char buf
[BUFSIZ
], *cp
;
390 strncpy(dp
->d_typename
, name
, sizeof(dp
->d_typename
));
392 "%s: unknown disk type, want to supply parameters (y/n)? ",
394 if ((fgets(buf
, BUFSIZ
, stdin
) == NULL
) || buf
[0] != 'y')
395 return ((struct disklabel
*)0);
397 fprintf(stderr
, "Disk/controller type (%s)? ", dktypenames
[1]);
398 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
399 return ((struct disklabel
*)0);
400 if ((cp
= strchr(buf
, '\n')) != NULL
)
402 if (buf
[0] == '\0') {
406 if ((i
= gettype(buf
, dktypenames
)) >= 0) {
410 fprintf(stderr
, "%s: unrecognized controller type\n", buf
);
411 fprintf(stderr
, "use one of:\n");
412 for (tp
= dktypenames
; *tp
; tp
++)
413 if (strchr(*tp
, ' ') == 0)
414 fprintf(stderr
, "\t%s\n", *tp
);
418 fprintf(stderr
, "type (winchester|removable|simulated)? ");
419 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
420 return ((struct disklabel
*)0);
421 if ((cp
= strchr(buf
, '\n')) != NULL
)
427 dp
->d_flags
= D_REMOVABLE
;
430 dp
->d_flags
= D_RAMDISK
;
435 fprintf(stderr
, "%s: bad disk type\n", buf
);
440 fprintf(stderr
, "(type <cr> to get default value, if only one)\n");
441 if (dp
->d_type
== DTYPE_SMD
) {
443 "Do '%s' disks support bad144 bad block forwarding (yes)? ",
445 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
446 return ((struct disklabel
*)0);
448 dp
->d_flags
|= D_BADSECT
;
450 for (fp
= fields
; fp
->f_name
!= NULL
; fp
++) {
452 fprintf(stderr
, "%s ", fp
->f_name
);
453 if (fp
->f_defaults
!= NULL
)
454 fprintf(stderr
, "(%s)", fp
->f_defaults
);
455 fprintf(stderr
, "? ");
456 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
457 return ((struct disklabel
*)0);
458 if ((cp
= strchr(buf
, '\n')) != NULL
)
462 if (fp
->f_defaults
== NULL
) {
463 fprintf(stderr
, "no default value\n");
467 cp
= __UNCONST(fp
->f_defaults
);
469 *fp
->f_location
= atol(cp
);
470 if (*fp
->f_location
== 0) {
471 fprintf(stderr
, "%s: bad value\n", cp
);
475 fprintf(stderr
, "sectors/cylinder (%d)? ",
476 dp
->d_nsectors
* dp
->d_ntracks
);
477 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
478 return ((struct disklabel
*)0);
479 if ((cp
= strchr(buf
, '\n')) != NULL
)
482 dp
->d_secpercyl
= dp
->d_nsectors
* dp
->d_ntracks
;
484 dp
->d_secpercyl
= atol(buf
);
485 fprintf(stderr
, "Drive-type-specific parameters, <cr> to terminate:\n");
486 for (i
= 0; i
< NDDATA
; i
++) {
487 fprintf(stderr
, "d%d? ", i
);
488 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
489 return ((struct disklabel
*)0);
490 if ((cp
= strchr(buf
, '\n')) != NULL
)
494 dp
->d_drivedata
[i
] = atol(buf
);
502 const char *const *names
;
504 const char *const *nm
;
506 for (nm
= names
; *nm
; nm
++)
507 if (strcasecmp(t
, *nm
) == 0)
509 if (isdigit((unsigned char)*t
))
517 (void)fprintf(stderr
, "usage: diskpart [-dp] [-s size] disk-type\n");