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. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * @(#) Copyright (c) 1983, 1988, 1993 The Regents of the University of California. All rights reserved.
34 * @(#)diskpart.c 8.3 (Berkeley) 11/30/94
35 * $FreeBSD: src/usr.sbin/diskpart/diskpart.c,v 1.11.2.2 2002/12/04 16:24:08 roam Exp $
36 * $DragonFly: src/usr.sbin/diskpart/Attic/diskpart.c,v 1.7 2005/03/16 17:54:59 y0netan1 Exp $
40 * Program to calculate standard disk partition sizes.
42 #include <sys/param.h>
44 #include <sys/disklabel.h>
51 #define for_now /* show all of `c' partition for disklabel */
53 #define PART(x) (x - 'a')
56 * Default partition sizes, where they exist.
59 int defpart
[NDEFAULTS
][NPARTITIONS
] = {
60 { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */
61 { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */
62 { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */
63 { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */
67 * Each array defines a layout for a disk;
68 * that is, the collection of partitions totally
69 * covers the physical space on a disk.
72 char layouts
[NLAYOUTS
][NPARTITIONS
] = {
73 { 'a', 'b', 'h', 'g' },
74 { 'a', 'b', 'h', 'd', 'e', 'f' },
79 * Default disk block and disk block fragment
80 * sizes for each file system. Those file systems
81 * with zero block and frag sizes are special cases
82 * (e.g. swap areas or for access to the entire device).
84 struct partition defparam
[NPARTITIONS
] = {
85 { 0, 0, 1024, FS_UNUSED
, 8, 0 }, /* a */
86 { 0, 0, 1024, FS_SWAP
, 8, 0 }, /* b */
87 { 0, 0, 1024, FS_UNUSED
, 8, 0 }, /* c */
88 { 0, 0, 512, FS_UNUSED
, 8, 0 }, /* d */
89 { 0, 0, 1024, FS_UNUSED
, 8, 0 }, /* e */
90 { 0, 0, 1024, FS_UNUSED
, 8, 0 }, /* f */
91 { 0, 0, 1024, FS_UNUSED
, 8, 0 }, /* g */
92 { 0, 0, 1024, FS_UNUSED
, 8, 0 } /* h */
96 * Each disk has some space reserved for a bad sector
97 * forwarding table. DEC standard 144 uses the first
98 * 5 even numbered sectors in the last track of the
99 * last cylinder for replicated storage of the bad sector
100 * table; another 126 sectors past this is needed as a
101 * pool of replacement sectors.
103 int badsecttable
= 126; /* # sectors */
105 int pflag
; /* print device driver partition tables */
106 int dflag
; /* print disktab entry */
108 struct disklabel
*promptfordisk();
109 static void usage(void);
112 main(int argc
, char **argv
)
114 struct disklabel
*dp
;
115 int curcyl
, spc
, def
, part
, layout
, j
;
116 int threshhold
, numcyls
[NPARTITIONS
], startcyl
[NPARTITIONS
];
121 while ((ch
= getopt(argc
, argv
, "dps:")) != EOF
)
132 totsize
= atoi(optarg
);
142 dp
= getdiskbyname(*argv
);
145 dp
= promptfordisk(*argv
);
147 errx(2, "%s: unknown disk type", *argv
);
149 if (dp
->d_flags
& D_REMOVABLE
)
150 tyname
= "removable";
151 else if (dp
->d_flags
& D_RAMDISK
)
152 tyname
= "simulated";
154 tyname
= "winchester";
156 spc
= dp
->d_secpercyl
;
158 * Bad sector table contains one track for the replicated
159 * copies of the table and enough full tracks preceding
160 * the last track to hold the pool of free blocks to which
161 * bad sectors are mapped.
162 * If disk size was specified explicitly, use specified size.
164 if (dp
->d_type
== DTYPE_SMD
&& dp
->d_flags
& D_BADSECT
&&
166 badsecttable
= dp
->d_nsectors
+
167 roundup(badsecttable
, dp
->d_nsectors
);
168 threshhold
= howmany(spc
, badsecttable
);
174 * If disk size was specified, recompute number of cylinders
175 * that may be used, and set badsecttable to any remaining
176 * fraction of the last cylinder.
179 dp
->d_ncylinders
= howmany(totsize
, spc
);
180 badsecttable
= spc
* dp
->d_ncylinders
- totsize
;
184 * Figure out if disk is large enough for
185 * expanded swap area and 'd', 'e', and 'f'
186 * partitions. Otherwise, use smaller defaults
189 for (def
= 0; def
< NDEFAULTS
; def
++) {
191 for (part
= PART('a'); part
< NPARTITIONS
; part
++)
192 curcyl
+= howmany(defpart
[def
][part
], spc
);
193 if (curcyl
< dp
->d_ncylinders
- threshhold
)
196 if (def
>= NDEFAULTS
)
197 errx(3, "%s: disk too small, calculate by hand", *argv
);
200 * Calculate number of cylinders allocated to each disk
201 * partition. We may waste a bit of space here, but it's
202 * in the interest of (very backward) compatibility
203 * (for mixed disk systems).
205 for (curcyl
= 0, part
= PART('a'); part
< NPARTITIONS
; part
++) {
207 if (defpart
[def
][part
] != 0) {
208 numcyls
[part
] = howmany(defpart
[def
][part
], spc
);
209 curcyl
+= numcyls
[part
];
212 numcyls
[PART('f')] = dp
->d_ncylinders
- curcyl
;
214 numcyls
[PART('d')] + numcyls
[PART('e')] + numcyls
[PART('f')];
215 numcyls
[PART('c')] = dp
->d_ncylinders
;
216 defpart
[def
][PART('f')] = numcyls
[PART('f')] * spc
- badsecttable
;
217 defpart
[def
][PART('g')] = numcyls
[PART('g')] * spc
- badsecttable
;
218 defpart
[def
][PART('c')] = numcyls
[PART('c')] * spc
;
220 if (totsize
|| !pflag
)
224 defpart
[def
][PART('c')] -= badsecttable
;
227 * Calculate starting cylinder number for each partition.
228 * Note the 'h' partition is physically located before the
229 * 'g' or 'd' partition. This is reflected in the layout
230 * arrays defined above.
232 for (layout
= 0; layout
< NLAYOUTS
; layout
++) {
234 for (lp
= layouts
[layout
]; *lp
!= 0; lp
++) {
235 startcyl
[PART(*lp
)] = curcyl
;
236 curcyl
+= numcyls
[PART(*lp
)];
241 printf("}, %s_sizes[%d] = {\n", dp
->d_typename
, NPARTITIONS
);
242 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
243 if (numcyls
[part
] == 0) {
244 printf("\t0,\t0,\n");
247 if (dp
->d_type
!= DTYPE_MSCP
) {
248 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
249 defpart
[def
][part
], startcyl
[part
],
250 'A' + part
, startcyl
[part
],
251 startcyl
[part
] + numcyls
[part
] - 1);
254 printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
255 defpart
[def
][part
], spc
* startcyl
[part
],
256 'A' + part
, spc
* startcyl
[part
],
257 spc
* startcyl
[part
] + defpart
[def
][part
] - 1);
265 * In case the disk is in the ``in-between'' range
266 * where the 'g' partition is smaller than the 'h'
267 * partition, reverse the frag sizes so the /usr partition
268 * is always set up with a frag size larger than the
271 if (defpart
[def
][PART('g')] < defpart
[def
][PART('h')]) {
274 temp
= defparam
[PART('h')].p_fsize
;
275 defparam
[PART('h')].p_fsize
=
276 defparam
[PART('g')].p_fsize
;
277 defparam
[PART('g')].p_fsize
= temp
;
279 printf("%s:\\\n", dp
->d_typename
);
280 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname
,
281 dp
->d_nsectors
, dp
->d_ntracks
, dp
->d_ncylinders
);
282 if (dp
->d_secpercyl
!= dp
->d_nsectors
* dp
->d_ntracks
)
283 printf("sc#%d:", dp
->d_secpercyl
);
284 if (dp
->d_type
== DTYPE_SMD
&& dp
->d_flags
& D_BADSECT
)
286 printf("\\\n\t:dt=%s:", dktypenames
[dp
->d_type
]);
287 for (part
= NDDATA
- 1; part
>= 0; part
--)
288 if (dp
->d_drivedata
[part
])
290 for (j
= 0; j
<= part
; j
++)
291 printf("d%d#%d:", j
, dp
->d_drivedata
[j
]);
293 for (nparts
= 0, part
= PART('a'); part
< NPARTITIONS
; part
++)
294 if (defpart
[def
][part
] != 0)
296 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
297 if (defpart
[def
][part
] == 0)
299 printf("\t:p%c#%d:", 'a' + part
, defpart
[def
][part
]);
300 printf("o%c#%d:b%c#%d:f%c#%d:",
301 'a' + part
, spc
* startcyl
[part
],
303 defparam
[part
].p_frag
* defparam
[part
].p_fsize
,
304 'a' + part
, defparam
[part
].p_fsize
);
305 if (defparam
[part
].p_fstype
== FS_SWAP
)
306 printf("t%c=swap:", 'a' + part
);
308 printf("%s\n", nparts
> 0 ? "\\" : "");
311 defpart
[def
][PART('c')] -= badsecttable
;
313 printf("#\t:p%c#%d:", 'a' + part
, defpart
[def
][part
]);
314 printf("o%c#%d:b%c#%d:f%c#%d:\n",
315 'a' + part
, spc
* startcyl
[part
],
317 defparam
[part
].p_frag
* defparam
[part
].p_fsize
,
318 'a' + part
, defparam
[part
].p_fsize
);
322 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
323 dp
->d_typename
, dp
->d_nsectors
, dp
->d_ntracks
,
325 printf("\n Partition\t Size\t Offset\t Range\n");
326 for (part
= PART('a'); part
< NPARTITIONS
; part
++) {
327 printf("\t%c\t", 'a' + part
);
328 if (numcyls
[part
] == 0) {
332 printf("%7d\t%7d\t%4d - %d%s\n",
333 defpart
[def
][part
], startcyl
[part
] * spc
,
334 startcyl
[part
], startcyl
[part
] + numcyls
[part
] - 1,
335 defpart
[def
][part
] % spc
? "*" : "");
342 fprintf(stderr
, "usage: diskpart [-p] [-d] [-s size] disk-type\n");
346 struct disklabel disk
;
351 u_int32_t
*f_location
;
353 { "sector size", "512", &disk
.d_secsize
},
354 { "#sectors/track", 0, &disk
.d_nsectors
},
355 { "#tracks/cylinder", 0, &disk
.d_ntracks
},
356 { "#cylinders", 0, &disk
.d_ncylinders
},
365 if (fgets(buf
, BUFSIZ
, stdin
) == NULL
)
368 if (len
!= 0 && buf
[len
- 1] == '\n')
374 promptfordisk(char *name
)
376 struct disklabel
*dp
= &disk
;
379 char buf
[BUFSIZ
], *cp
;
382 strncpy(dp
->d_typename
, name
, sizeof(dp
->d_typename
));
384 "%s: unknown disk type, want to supply parameters (y/n)? ",
388 return ((struct disklabel
*)0);
390 fprintf(stderr
, "Disk/controller type (%s)? ", dktypenames
[1]);
396 if ((i
= gettype(buf
, dktypenames
)) >= 0) {
400 fprintf(stderr
, "%s: unrecognized controller type\n", buf
);
401 fprintf(stderr
, "use one of:\n");
402 for (tp
= dktypenames
; *tp
; tp
++)
403 if (strchr(*tp
, ' ') == 0)
404 fprintf(stderr
, "\t%s\n", *tp
);
408 fprintf(stderr
, "type (winchester|removable|simulated)? ");
410 if (strcmp(buf
, "removable") == 0)
411 dp
->d_flags
= D_REMOVABLE
;
412 else if (strcmp(buf
, "simulated") == 0)
413 dp
->d_flags
= D_RAMDISK
;
414 else if (strcmp(buf
, "winchester")) {
415 fprintf(stderr
, "%s: bad disk type\n", buf
);
418 strncpy(dp
->d_typename
, buf
, sizeof(dp
->d_typename
));
419 fprintf(stderr
, "(type <cr> to get default value, if only one)\n");
420 if (dp
->d_type
== DTYPE_SMD
)
421 fprintf(stderr
, "Do %ss support bad144 bad block forwarding (yes)? ",
425 dp
->d_flags
|= D_BADSECT
;
426 for (fp
= fields
; fp
->f_name
!= NULL
; fp
++) {
428 fprintf(stderr
, "%s ", fp
->f_name
);
429 if (fp
->f_defaults
!= NULL
)
430 fprintf(stderr
, "(%s)", fp
->f_defaults
);
431 fprintf(stderr
, "? ");
434 if (fp
->f_defaults
== NULL
) {
435 fprintf(stderr
, "no default value\n");
440 *fp
->f_location
= atol(cp
);
441 if (*fp
->f_location
== 0) {
442 fprintf(stderr
, "%s: bad value\n", cp
);
446 fprintf(stderr
, "sectors/cylinder (%d)? ",
447 dp
->d_nsectors
* dp
->d_ntracks
);
450 dp
->d_secpercyl
= dp
->d_nsectors
* dp
->d_ntracks
;
452 dp
->d_secpercyl
= atol(buf
);
453 fprintf(stderr
, "Drive-type-specific parameters, <cr> to terminate:\n");
454 for (i
= 0; i
< NDDATA
; i
++) {
455 fprintf(stderr
, "d%d? ", i
);
459 dp
->d_drivedata
[i
] = atol(buf
);
465 gettype(const char *t
, const char **names
)
469 for (nm
= names
; *nm
; nm
++)
470 if (ustrcmp(t
, *nm
) == 0)
477 ustrcmp(char *s1
, char *s2
)
479 #define lower(c) (islower(c) ? (c) : tolower(c))
481 for (; *s1
; s1
++, s2
++) {
484 if (isalpha(*s1
) && isalpha(*s2
) &&
485 lower(*s1
) == lower(*s2
))