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