fixes for range locking
[unix-history] / usr / src / usr.sbin / diskpart / diskpart.c
CommitLineData
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
9char 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 15static 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
36int 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
49char 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
61struct 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 80int badsecttable = 126; /* # sectors */
11236beb
SL
81
82int pflag; /* print device driver partition tables */
83int dflag; /* print disktab entry */
84
969d2ba6 85struct disklabel *promptfordisk();
11236beb
SL
86
87main(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 317struct disklabel disk;
11236beb
SL
318
319struct 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 331struct disklabel *
11236beb
SL
332promptfordisk(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 362gettype:
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++) {
383again:
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
420gettype(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
434ustrcmp(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}