|
|
1.1 root 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 are permitted
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.
16: */
17:
18: #ifndef lint
19: char copyright[] =
20: "@(#) Copyright (c) 1983, 1988 Regents of the University of California.\n\
21: All rights reserved.\n";
22: #endif /* not lint */
23:
24: #ifndef lint
25: static char sccsid[] = "@(#)diskpart.c 5.10 (Berkeley) 7/12/88";
26: #endif /* not lint */
27:
28: /*
29: * Program to calculate standard disk partition sizes.
30: */
31: #include <sys/param.h>
32: #define DKTYPENAMES
33: #include <sys/disklabel.h>
34:
35: #include <stdio.h>
36: #include <ctype.h>
37:
38: #define for_now /* show all of `c' partition for disklabel */
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: */
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 */
80: };
81:
82: /*
83: * Each disk has some space reserved for a bad sector
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.
89: */
90: int badsecttable = 126; /* # sectors */
91:
92: int pflag; /* print device driver partition tables */
93: int dflag; /* print disktab entry */
94:
95: struct disklabel *promptfordisk();
96:
97: main(argc, argv)
98: int argc;
99: char *argv[];
100: {
101: struct disklabel *dp;
102: register int curcyl, spc, def, part, layout, j;
103: int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS];
104: int totsize = 0;
105: char *lp, *tyname;
106:
107: argc--, argv++;
108: if (argc < 1) {
109: fprintf(stderr,
110: "usage: disktab [ -p ] [ -d ] [ -s size ] disk-type\n");
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: }
121: if (argc > 1 && strcmp(*argv, "-s") == 0) {
122: totsize = atoi(argv[1]);
123: argc += 2, argv += 2;
124: }
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: }
133: } else {
134: if (dp->d_flags & D_REMOVABLE)
135: tyname = "removable";
136: else if (dp->d_flags & D_RAMDISK)
137: tyname = "simulated";
138: else
139: tyname = "winchester";
140: }
141: spc = dp->d_secpercyl;
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.
147: * If disk size was specified explicitly, use specified size.
148: */
149: if (dp->d_type == DTYPE_SMD && dp->d_flags & D_BADSECT &&
150: totsize == 0) {
151: badsecttable = dp->d_nsectors +
152: roundup(badsecttable, dp->d_nsectors);
153: threshhold = howmany(spc, badsecttable);
154: } else {
155: badsecttable = 0;
156: threshhold = 0;
157: }
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: }
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
190: * in the interest of (very backward) compatibility
191: * (for mixed disk systems).
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;
207: #ifndef for_now
208: if (totsize || !pflag)
209: #else
210: if (totsize)
211: #endif
212: defpart[def][PART('c')] -= badsecttable;
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) {
229: printf("}, %s_sizes[%d] = {\n", dp->d_typename, NPARTITIONS);
230: for (part = PART('a'); part < NPARTITIONS; part++) {
231: if (numcyls[part] == 0) {
232: printf("\t0,\t0,\n");
233: continue;
234: }
235: if (dp->d_type != DTYPE_MSCP) {
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);
246: }
247: exit(0);
248: }
249: if (dflag) {
250: int nparts;
251:
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: }
267: printf("%s:\\\n", dp->d_typename);
268: printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:", tyname,
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:");
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");
281: for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
282: if (defpart[def][part] != 0)
283: nparts++;
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]);
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);
295: nparts--;
296: printf("%s\n", nparts > 0 ? "\\" : "");
297: }
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
308: exit(0);
309: }
310: printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
311: dp->d_typename, dp->d_nsectors, dp->d_ntracks,
312: dp->d_ncylinders);
313: printf("\n Partition\t Size\t Offset\t Range\n");
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: }
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 ? "*" : "");
324: }
325: }
326:
327: struct disklabel disk;
328:
329: struct field {
330: char *f_name;
331: char *f_defaults;
332: u_long *f_location;
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 },
338: { 0, 0, 0 },
339: };
340:
341: struct disklabel *
342: promptfordisk(name)
343: char *name;
344: {
345: register struct disklabel *dp = &disk;
346: register struct field *fp;
347: register i;
348: char buf[BUFSIZ], **tp, *cp, *gets();
349:
350: strncpy(dp->d_typename, name, sizeof(dp->d_typename));
351: fprintf(stderr,
352: "%s: unknown disk type, want to supply parameters (y/n)? ",
353: name);
354: (void) gets(buf);
355: if (*buf != 'y')
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: }
372: gettype:
373: dp->d_flags = 0;
374: fprintf(stderr, "type (winchester|removable|simulated)? ");
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);
382: goto gettype;
383: }
384: strncpy(dp->d_typename, buf, sizeof(dp->d_typename));
385: fprintf(stderr, "(type <cr> to get default value, if only one)\n");
386: if (dp->d_type == DTYPE_SMD)
387: fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ",
388: dp->d_typename);
389: (void) gets(buf);
390: if (*buf != 'n')
391: dp->d_flags |= D_BADSECT;
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: }
406: *fp->f_location = atol(cp);
407: if (*fp->f_location == 0) {
408: fprintf(stderr, "%s: bad value\n", cp);
409: goto again;
410: }
411: }
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: }
427: return (dp);
428: }
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: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.