Commit | Line | Data |
---|---|---|
54cf7c29 | 1 | /* |
d78d7d97 | 2 | * Copyright (c) 1983, 1988 Regents of the University of California. |
fbca346b KB |
3 | * All rights reserved. |
4 | * | |
5 | * Redistribution and use in source and binary forms are permitted | |
b8c620d6 KB |
6 | * provided that the above copyright notice and this paragraph are |
7 | * duplicated in all such forms and that any documentation, | |
8 | * advertising materials, and other materials related to such | |
9 | * distribution and use acknowledge that the software was developed | |
10 | * by the University of California, Berkeley. The name of the | |
11 | * University may not be used to endorse or promote products derived | |
12 | * from this software without specific prior written permission. | |
13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR | |
14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED | |
15 | * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. | |
54cf7c29 DF |
16 | */ |
17 | ||
18 | #ifndef lint | |
19 | char copyright[] = | |
d78d7d97 | 20 | "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\ |
54cf7c29 | 21 | All rights reserved.\n"; |
fbca346b | 22 | #endif /* not lint */ |
54cf7c29 | 23 | |
11236beb | 24 | #ifndef lint |
8ed74d59 | 25 | static char sccsid[] = "@(#)diskpart.c 5.10 (Berkeley) %G%"; |
fbca346b | 26 | #endif /* not lint */ |
11236beb SL |
27 | |
28 | /* | |
29 | * Program to calculate standard disk partition sizes. | |
30 | */ | |
31 | #include <sys/param.h> | |
969d2ba6 MK |
32 | #define DKTYPENAMES |
33 | #include <sys/disklabel.h> | |
11236beb SL |
34 | |
35 | #include <stdio.h> | |
969d2ba6 | 36 | #include <ctype.h> |
11236beb | 37 | |
fd2bf741 | 38 | #define for_now /* show all of `c' partition for disklabel */ |
11236beb SL |
39 | #define NPARTITIONS 8 |
40 | #define PART(x) (x - 'a') | |
41 | ||
42 | /* | |
43 | * Default partition sizes, where they exist. | |
44 | */ | |
45 | #define NDEFAULTS 4 | |
46 | int defpart[NDEFAULTS][NPARTITIONS] = { | |
47 | { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */ | |
48 | { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */ | |
49 | { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */ | |
50 | { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */ | |
51 | }; | |
52 | ||
53 | /* | |
54 | * Each array defines a layout for a disk; | |
55 | * that is, the collection of partitions totally | |
56 | * covers the physical space on a disk. | |
57 | */ | |
58 | #define NLAYOUTS 3 | |
59 | char layouts[NLAYOUTS][NPARTITIONS] = { | |
60 | { 'a', 'b', 'h', 'g' }, | |
61 | { 'a', 'b', 'h', 'd', 'e', 'f' }, | |
62 | { 'c' }, | |
63 | }; | |
64 | ||
65 | /* | |
66 | * Default disk block and disk block fragment | |
67 | * sizes for each file system. Those file systems | |
68 | * with zero block and frag sizes are special cases | |
69 | * (e.g. swap areas or for access to the entire device). | |
70 | */ | |
969d2ba6 MK |
71 | struct partition defparam[NPARTITIONS] = { |
72 | { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* a */ | |
73 | { 0, 0, 1024, FS_SWAP, 8, 0 }, /* b */ | |
74 | { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* c */ | |
75 | { 0, 0, 512, FS_UNUSED, 8, 0 }, /* d */ | |
76 | { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* e */ | |
77 | { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* f */ | |
78 | { 0, 0, 1024, FS_UNUSED, 8, 0 }, /* g */ | |
79 | { 0, 0, 1024, FS_UNUSED, 8, 0 } /* h */ | |
11236beb SL |
80 | }; |
81 | ||
82 | /* | |
83 | * Each disk has some space reserved for a bad sector | |
6a034b04 SL |
84 | * forwarding table. DEC standard 144 uses the first |
85 | * 5 even numbered sectors in the last track of the | |
86 | * last cylinder for replicated storage of the bad sector | |
87 | * table; another 126 sectors past this is needed as a | |
88 | * pool of replacement sectors. | |
11236beb | 89 | */ |
6a034b04 | 90 | int badsecttable = 126; /* # sectors */ |
11236beb SL |
91 | |
92 | int pflag; /* print device driver partition tables */ | |
93 | int dflag; /* print disktab entry */ | |
94 | ||
969d2ba6 | 95 | struct disklabel *promptfordisk(); |
11236beb SL |
96 | |
97 | main(argc, argv) | |
98 | int argc; | |
99 | char *argv[]; | |
100 | { | |
969d2ba6 MK |
101 | struct disklabel *dp; |
102 | register int curcyl, spc, def, part, layout, j; | |
11236beb | 103 | int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS]; |
d78d7d97 MK |
104 | int totsize = 0; |
105 | char *lp, *tyname; | |
11236beb SL |
106 | |
107 | argc--, argv++; | |
108 | if (argc < 1) { | |
d78d7d97 MK |
109 | fprintf(stderr, |
110 | "usage: disktab [ -p ] [ -d ] [ -s size ] disk-type\n"); | |
11236beb SL |
111 | exit(1); |
112 | } | |
113 | if (argc > 0 && strcmp(*argv, "-p") == 0) { | |
114 | pflag++; | |
115 | argc--, argv++; | |
116 | } | |
117 | if (argc > 0 && strcmp(*argv, "-d") == 0) { | |
118 | dflag++; | |
119 | argc--, argv++; | |
120 | } | |
d78d7d97 MK |
121 | if (argc > 1 && strcmp(*argv, "-s") == 0) { |
122 | totsize = atoi(argv[1]); | |
123 | argc += 2, argv += 2; | |
124 | } | |
11236beb SL |
125 | dp = getdiskbyname(*argv); |
126 | if (dp == NULL) { | |
127 | if (isatty(0)) | |
128 | dp = promptfordisk(*argv); | |
129 | if (dp == NULL) { | |
130 | fprintf(stderr, "%s: unknown disk type\n", *argv); | |
131 | exit(2); | |
132 | } | |
969d2ba6 MK |
133 | } else { |
134 | if (dp->d_flags & D_REMOVABLE) | |
d78d7d97 | 135 | tyname = "removable"; |
969d2ba6 | 136 | else if (dp->d_flags & D_RAMDISK) |
d78d7d97 | 137 | tyname = "simulated"; |
969d2ba6 | 138 | else |
d78d7d97 | 139 | tyname = "winchester"; |
11236beb | 140 | } |
969d2ba6 | 141 | spc = dp->d_secpercyl; |
6a034b04 SL |
142 | /* |
143 | * Bad sector table contains one track for the replicated | |
144 | * copies of the table and enough full tracks preceding | |
145 | * the last track to hold the pool of free blocks to which | |
146 | * bad sectors are mapped. | |
d78d7d97 | 147 | * If disk size was specified explicitly, use specified size. |
6a034b04 | 148 | */ |
d78d7d97 MK |
149 | if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT && |
150 | totsize == 0) { | |
969d2ba6 MK |
151 | badsecttable = dp->d_nsectors + |
152 | roundup(badsecttable, dp->d_nsectors); | |
153 | threshhold = howmany(spc, badsecttable); | |
154 | } else { | |
f0a5197a KM |
155 | badsecttable = 0; |
156 | threshhold = 0; | |
157 | } | |
d78d7d97 MK |
158 | /* |
159 | * If disk size was specified, recompute number of cylinders | |
160 | * that may be used, and set badsecttable to any remaining | |
161 | * fraction of the last cylinder. | |
162 | */ | |
163 | if (totsize != 0) { | |
164 | dp->d_ncylinders = howmany(totsize, spc); | |
165 | badsecttable = spc * dp->d_ncylinders - totsize; | |
166 | } | |
11236beb SL |
167 | |
168 | /* | |
169 | * Figure out if disk is large enough for | |
170 | * expanded swap area and 'd', 'e', and 'f' | |
171 | * partitions. Otherwise, use smaller defaults | |
172 | * based on RK07. | |
173 | */ | |
174 | for (def = 0; def < NDEFAULTS; def++) { | |
175 | curcyl = 0; | |
176 | for (part = PART('a'); part < NPARTITIONS; part++) | |
177 | curcyl += howmany(defpart[def][part], spc); | |
178 | if (curcyl < dp->d_ncylinders - threshhold) | |
179 | break; | |
180 | } | |
181 | if (def >= NDEFAULTS) { | |
182 | fprintf(stderr, "%s: disk too small, calculate by hand\n", | |
183 | *argv); | |
184 | exit(3); | |
185 | } | |
186 | ||
187 | /* | |
188 | * Calculate number of cylinders allocated to each disk | |
189 | * partition. We may waste a bit of space here, but it's | |
d78d7d97 MK |
190 | * in the interest of (very backward) compatibility |
191 | * (for mixed disk systems). | |
11236beb SL |
192 | */ |
193 | for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) { | |
194 | numcyls[part] = 0; | |
195 | if (defpart[def][part] != 0) { | |
196 | numcyls[part] = howmany(defpart[def][part], spc); | |
197 | curcyl += numcyls[part]; | |
198 | } | |
199 | } | |
200 | numcyls[PART('f')] = dp->d_ncylinders - curcyl; | |
201 | numcyls[PART('g')] = | |
202 | numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')]; | |
203 | numcyls[PART('c')] = dp->d_ncylinders; | |
204 | defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable; | |
205 | defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable; | |
206 | defpart[def][PART('c')] = numcyls[PART('c')] * spc; | |
fd2bf741 | 207 | #ifndef for_now |
d78d7d97 MK |
208 | if (totsize || !pflag) |
209 | #else | |
210 | if (totsize) | |
fd2bf741 | 211 | #endif |
d78d7d97 | 212 | defpart[def][PART('c')] -= badsecttable; |
11236beb SL |
213 | |
214 | /* | |
215 | * Calculate starting cylinder number for each partition. | |
216 | * Note the 'h' partition is physically located before the | |
217 | * 'g' or 'd' partition. This is reflected in the layout | |
218 | * arrays defined above. | |
219 | */ | |
220 | for (layout = 0; layout < NLAYOUTS; layout++) { | |
221 | curcyl = 0; | |
222 | for (lp = layouts[layout]; *lp != 0; lp++) { | |
223 | startcyl[PART(*lp)] = curcyl; | |
224 | curcyl += numcyls[PART(*lp)]; | |
225 | } | |
226 | } | |
227 | ||
228 | if (pflag) { | |
969d2ba6 | 229 | printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS); |
11236beb SL |
230 | for (part = PART('a'); part < NPARTITIONS; part++) { |
231 | if (numcyls[part] == 0) { | |
232 | printf("\t0,\t0,\n"); | |
233 | continue; | |
234 | } | |
969d2ba6 | 235 | if (dp->d_type != DTYPE_MSCP) { |
f0a5197a KM |
236 | printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n", |
237 | defpart[def][part], startcyl[part], | |
238 | 'A' + part, startcyl[part], | |
239 | startcyl[part] + numcyls[part] - 1); | |
240 | continue; | |
241 | } | |
242 | printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n", | |
243 | defpart[def][part], spc * startcyl[part], | |
244 | 'A' + part, spc * startcyl[part], | |
245 | spc * startcyl[part] + defpart[def][part] - 1); | |
11236beb SL |
246 | } |
247 | exit(0); | |
248 | } | |
249 | if (dflag) { | |
510f89e2 SL |
250 | int nparts; |
251 | ||
11236beb SL |
252 | /* |
253 | * In case the disk is in the ``in-between'' range | |
254 | * where the 'g' partition is smaller than the 'h' | |
255 | * partition, reverse the frag sizes so the /usr partition | |
256 | * is always set up with a frag size larger than the | |
257 | * user's partition. | |
258 | */ | |
259 | if (defpart[def][PART('g')] < defpart[def][PART('h')]) { | |
260 | int temp; | |
261 | ||
262 | temp = defparam[PART('h')].p_fsize; | |
263 | defparam[PART('h')].p_fsize = | |
264 | defparam[PART('g')].p_fsize; | |
265 | defparam[PART('g')].p_fsize = temp; | |
266 | } | |
969d2ba6 | 267 | printf("%s:\\\n", dp->d_typename); |
d78d7d97 | 268 | printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname, |
969d2ba6 MK |
269 | dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders); |
270 | if (dp->d_secpercyl != dp->d_nsectors * dp->d_ntracks) | |
271 | printf("sc#%d:", dp->d_secpercyl); | |
272 | if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT) | |
273 | printf("sf:"); | |
969d2ba6 MK |
274 | printf("\\\n\t:dt=%s:", dktypenames[dp->d_type]); |
275 | for (part = NDDATA - 1; part >= 0; part--) | |
276 | if (dp->d_drivedata[part]) | |
277 | break; | |
278 | for (j = 0; j <= part; j++) | |
279 | printf("d%d#%d:", j, dp->d_drivedata[j]); | |
280 | printf("\\\n"); | |
510f89e2 SL |
281 | for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++) |
282 | if (defpart[def][part] != 0) | |
283 | nparts++; | |
11236beb SL |
284 | for (part = PART('a'); part < NPARTITIONS; part++) { |
285 | if (defpart[def][part] == 0) | |
286 | continue; | |
287 | printf("\t:p%c#%d:", 'a' + part, defpart[def][part]); | |
969d2ba6 MK |
288 | printf("o%c#%d:b%c#%d:f%c#%d:", |
289 | 'a' + part, spc * startcyl[part], | |
290 | 'a' + part, | |
291 | defparam[part].p_frag * defparam[part].p_fsize, | |
292 | 'a' + part, defparam[part].p_fsize); | |
293 | if (defparam[part].p_fstype == FS_SWAP) | |
294 | printf("t%c=swap:", 'a' + part); | |
510f89e2 SL |
295 | nparts--; |
296 | printf("%s\n", nparts > 0 ? "\\" : ""); | |
11236beb | 297 | } |
fd2bf741 MK |
298 | #ifdef for_now |
299 | defpart[def][PART('c')] -= badsecttable; | |
300 | part = PART('c'); | |
301 | printf("#\t:p%c#%d:", 'a' + part, defpart[def][part]); | |
302 | printf("o%c#%d:b%c#%d:f%c#%d:\n", | |
303 | 'a' + part, spc * startcyl[part], | |
304 | 'a' + part, | |
305 | defparam[part].p_frag * defparam[part].p_fsize, | |
306 | 'a' + part, defparam[part].p_fsize); | |
307 | #endif | |
11236beb SL |
308 | exit(0); |
309 | } | |
310 | printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n", | |
969d2ba6 MK |
311 | dp->d_typename, dp->d_nsectors, dp->d_ntracks, |
312 | dp->d_ncylinders); | |
d78d7d97 | 313 | printf("\n Partition\t Size\t Offset\t Range\n"); |
11236beb SL |
314 | for (part = PART('a'); part < NPARTITIONS; part++) { |
315 | printf("\t%c\t", 'a' + part); | |
316 | if (numcyls[part] == 0) { | |
317 | printf(" unused\n"); | |
318 | continue; | |
319 | } | |
d78d7d97 MK |
320 | printf("%7d\t%7d\t%4d - %d%s\n", |
321 | defpart[def][part], startcyl[part] * spc, | |
322 | startcyl[part], startcyl[part] + numcyls[part] - 1, | |
323 | defpart[def][part] % spc ? "*" : ""); | |
11236beb SL |
324 | } |
325 | } | |
326 | ||
969d2ba6 | 327 | struct disklabel disk; |
11236beb SL |
328 | |
329 | struct field { | |
330 | char *f_name; | |
331 | char *f_defaults; | |
969d2ba6 | 332 | u_long *f_location; |
11236beb SL |
333 | } fields[] = { |
334 | { "sector size", "512", &disk.d_secsize }, | |
335 | { "#sectors/track", 0, &disk.d_nsectors }, | |
336 | { "#tracks/cylinder", 0, &disk.d_ntracks }, | |
337 | { "#cylinders", 0, &disk.d_ncylinders }, | |
11236beb SL |
338 | { 0, 0, 0 }, |
339 | }; | |
340 | ||
969d2ba6 | 341 | struct disklabel * |
11236beb SL |
342 | promptfordisk(name) |
343 | char *name; | |
344 | { | |
969d2ba6 | 345 | register struct disklabel *dp = &disk; |
11236beb | 346 | register struct field *fp; |
969d2ba6 MK |
347 | register i; |
348 | char buf[BUFSIZ], **tp, *cp, *gets(); | |
11236beb | 349 | |
969d2ba6 | 350 | strncpy(dp->d_typename, name, sizeof(dp->d_typename)); |
11236beb SL |
351 | fprintf(stderr, |
352 | "%s: unknown disk type, want to supply parameters (y/n)? ", | |
353 | name); | |
354 | (void) gets(buf); | |
355 | if (*buf != 'y') | |
969d2ba6 MK |
356 | return ((struct disklabel *)0); |
357 | for (;;) { | |
358 | fprintf(stderr, "Disk/controller type (%s)? ", dktypenames[1]); | |
359 | (void) gets(buf); | |
360 | if (buf[0] == 0) | |
361 | dp->d_type = 1; | |
362 | else | |
363 | dp->d_type = gettype(buf, dktypenames); | |
364 | if (dp->d_type >= 0) | |
365 | break; | |
366 | fprintf(stderr, "%s: unrecognized controller type\n", buf); | |
367 | fprintf(stderr, "use one of:\n", buf); | |
368 | for (tp = dktypenames; *tp; tp++) | |
369 | if (index(*tp, ' ') == 0) | |
370 | fprintf(stderr, "\t%s\n", *tp); | |
371 | } | |
11236beb | 372 | gettype: |
969d2ba6 | 373 | dp->d_flags = 0; |
11236beb | 374 | fprintf(stderr, "type (winchester|removable|simulated)? "); |
969d2ba6 MK |
375 | (void) gets(buf); |
376 | if (strcmp(buf, "removable") == 0) | |
377 | dp->d_flags = D_REMOVABLE; | |
378 | else if (strcmp(buf, "simulated") == 0) | |
379 | dp->d_flags = D_RAMDISK; | |
380 | else if (strcmp(buf, "winchester")) { | |
381 | fprintf(stderr, "%s: bad disk type\n", buf); | |
11236beb SL |
382 | goto gettype; |
383 | } | |
fbca346b | 384 | strncpy(dp->d_typename, buf, sizeof(dp->d_typename)); |
11236beb | 385 | fprintf(stderr, "(type <cr> to get default value, if only one)\n"); |
969d2ba6 MK |
386 | if (dp->d_type == DTYPE_SMD) |
387 | fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ", | |
fbca346b | 388 | dp->d_typename); |
f0a5197a KM |
389 | (void) gets(buf); |
390 | if (*buf != 'n') | |
969d2ba6 | 391 | dp->d_flags |= D_BADSECT; |
11236beb SL |
392 | for (fp = fields; fp->f_name != NULL; fp++) { |
393 | again: | |
394 | fprintf(stderr, "%s ", fp->f_name); | |
395 | if (fp->f_defaults != NULL) | |
396 | fprintf(stderr, "(%s)", fp->f_defaults); | |
397 | fprintf(stderr, "? "); | |
398 | cp = gets(buf); | |
399 | if (*cp == '\0') { | |
400 | if (fp->f_defaults == NULL) { | |
401 | fprintf(stderr, "no default value\n"); | |
402 | goto again; | |
403 | } | |
404 | cp = fp->f_defaults; | |
405 | } | |
969d2ba6 | 406 | *fp->f_location = atol(cp); |
11236beb SL |
407 | if (*fp->f_location == 0) { |
408 | fprintf(stderr, "%s: bad value\n", cp); | |
409 | goto again; | |
410 | } | |
411 | } | |
969d2ba6 MK |
412 | fprintf(stderr, "sectors/cylinder (%d)? ", |
413 | dp->d_nsectors * dp->d_ntracks); | |
414 | (void) gets(buf); | |
415 | if (buf[0] == 0) | |
416 | dp->d_secpercyl = dp->d_nsectors * dp->d_ntracks; | |
417 | else | |
418 | dp->d_secpercyl = atol(buf); | |
419 | fprintf(stderr, "Drive-type-specific parameters, <cr> to terminate:\n"); | |
420 | for (i = 0; i < NDDATA; i++) { | |
421 | fprintf(stderr, "d%d? ", i); | |
422 | (void) gets(buf); | |
423 | if (buf[0] == 0) | |
424 | break; | |
425 | dp->d_drivedata[i] = atol(buf); | |
426 | } | |
11236beb SL |
427 | return (dp); |
428 | } | |
969d2ba6 MK |
429 | |
430 | gettype(t, names) | |
431 | char *t; | |
432 | char **names; | |
433 | { | |
434 | register char **nm; | |
435 | ||
436 | for (nm = names; *nm; nm++) | |
437 | if (ustrcmp(t, *nm) == 0) | |
438 | return (nm - names); | |
439 | if (isdigit(*t)) | |
440 | return (atoi(t)); | |
441 | return (-1); | |
442 | } | |
443 | ||
444 | ustrcmp(s1, s2) | |
445 | register char *s1, *s2; | |
446 | { | |
447 | #define lower(c) (islower(c) ? (c) : tolower(c)) | |
448 | ||
449 | for (; *s1; s1++, s2++) { | |
450 | if (*s1 == *s2) | |
451 | continue; | |
452 | if (isalpha(*s1) && isalpha(*s2) && | |
453 | lower(*s1) == lower(*s2)) | |
454 | continue; | |
455 | return (*s2 - *s1); | |
456 | } | |
457 | return (0); | |
458 | } |