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