use fgets(), not gets()
[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 *
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
19char 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 25static 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
46int 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
59char 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
71struct 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 90int badsecttable = 126; /* # sectors */
11236beb
SL
91
92int pflag; /* print device driver partition tables */
93int dflag; /* print disktab entry */
94
969d2ba6 95struct disklabel *promptfordisk();
11236beb
SL
96
97main(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 327struct disklabel disk;
11236beb
SL
328
329struct 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 341struct disklabel *
11236beb
SL
342promptfordisk(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 372gettype:
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++) {
393again:
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
430gettype(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
444ustrcmp(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}