fix sccsid to use keywords and modern initialization syntax
[unix-history] / usr / src / usr.sbin / diskpart / diskpart.c
CommitLineData
54cf7c29
DF
1/*
2 * Copyright (c) 1983 Regents of the University of California.
3 * All rights reserved. The Berkeley software License Agreement
4 * specifies the terms and conditions for redistribution.
5 */
6
7#ifndef lint
8char copyright[] =
9"@(#) Copyright (c) 1983 Regents of the University of California.\n\
10 All rights reserved.\n";
11#endif not lint
12
11236beb 13#ifndef lint
24bb4240 14static char sccsid[] = "@(#)diskpart.c 5.5 (Berkeley) %G%";
54cf7c29 15#endif not lint
11236beb
SL
16
17/*
18 * Program to calculate standard disk partition sizes.
19 */
20#include <sys/param.h>
21
22#include <stdio.h>
23#include <disktab.h>
24
25#define NPARTITIONS 8
26#define PART(x) (x - 'a')
27
28/*
29 * Default partition sizes, where they exist.
30 */
31#define NDEFAULTS 4
32int defpart[NDEFAULTS][NPARTITIONS] = {
33 { 15884, 66880, 0, 15884, 307200, 0, 0, 291346 }, /* ~ 356+ Mbytes */
34 { 15884, 33440, 0, 15884, 55936, 0, 0, 291346 }, /* ~ 206-355 Mbytes */
35 { 15884, 33440, 0, 15884, 55936, 0, 0, 0 }, /* ~ 61-205 Mbytes */
36 { 15884, 10032, 0, 15884, 0, 0, 0, 0 }, /* ~ 20-60 Mbytes */
37};
38
39/*
40 * Each array defines a layout for a disk;
41 * that is, the collection of partitions totally
42 * covers the physical space on a disk.
43 */
44#define NLAYOUTS 3
45char layouts[NLAYOUTS][NPARTITIONS] = {
46 { 'a', 'b', 'h', 'g' },
47 { 'a', 'b', 'h', 'd', 'e', 'f' },
48 { 'c' },
49};
50
51/*
52 * Default disk block and disk block fragment
53 * sizes for each file system. Those file systems
54 * with zero block and frag sizes are special cases
55 * (e.g. swap areas or for access to the entire device).
56 */
57struct defparam {
58 int p_bsize; /* block size */
59 int p_fsize; /* frag size */
60} defparam[NPARTITIONS] = {
61 { 8192, 1024 }, /* a */
24bb4240
MK
62 { 8192, 1024 }, /* b */
63 { 8192, 1024 }, /* c */
64 { 4096, 512 }, /* d */
65 { 8192, 1024 }, /* e */
66 { 8192, 1024 }, /* f */
67 { 8192, 1024 }, /* g */
68 { 8192, 1024 } /* h */
11236beb
SL
69};
70
71/*
72 * Each disk has some space reserved for a bad sector
6a034b04
SL
73 * forwarding table. DEC standard 144 uses the first
74 * 5 even numbered sectors in the last track of the
75 * last cylinder for replicated storage of the bad sector
76 * table; another 126 sectors past this is needed as a
77 * pool of replacement sectors.
11236beb 78 */
6a034b04 79int badsecttable = 126; /* # sectors */
11236beb
SL
80
81int pflag; /* print device driver partition tables */
82int dflag; /* print disktab entry */
83
84struct disktab *promptfordisk();
85
86main(argc, argv)
87 int argc;
88 char *argv[];
89{
90 struct disktab *dp;
91 register int curcyl, spc, def, part, layout;
92 int threshhold, numcyls[NPARTITIONS], startcyl[NPARTITIONS];
93 char *lp;
94
95 argc--, argv++;
96 if (argc < 1) {
97 fprintf(stderr, "usage: disktab [ -p ] [ -d ] disk-type\n");
98 exit(1);
99 }
100 if (argc > 0 && strcmp(*argv, "-p") == 0) {
101 pflag++;
102 argc--, argv++;
103 }
104 if (argc > 0 && strcmp(*argv, "-d") == 0) {
105 dflag++;
106 argc--, argv++;
107 }
108 dp = getdiskbyname(*argv);
109 if (dp == NULL) {
110 if (isatty(0))
111 dp = promptfordisk(*argv);
112 if (dp == NULL) {
113 fprintf(stderr, "%s: unknown disk type\n", *argv);
114 exit(2);
115 }
116 }
117 spc = dp->d_nsectors * dp->d_ntracks;
6a034b04
SL
118 /*
119 * Bad sector table contains one track for the replicated
120 * copies of the table and enough full tracks preceding
121 * the last track to hold the pool of free blocks to which
122 * bad sectors are mapped.
123 */
124 badsecttable = dp->d_nsectors + roundup(badsecttable, dp->d_nsectors);
11236beb 125 threshhold = howmany(spc, badsecttable);
f0a5197a
KM
126 if (dp->d_badsectforw == 0) {
127 badsecttable = 0;
128 threshhold = 0;
129 }
11236beb
SL
130
131 /*
132 * Figure out if disk is large enough for
133 * expanded swap area and 'd', 'e', and 'f'
134 * partitions. Otherwise, use smaller defaults
135 * based on RK07.
136 */
137 for (def = 0; def < NDEFAULTS; def++) {
138 curcyl = 0;
139 for (part = PART('a'); part < NPARTITIONS; part++)
140 curcyl += howmany(defpart[def][part], spc);
141 if (curcyl < dp->d_ncylinders - threshhold)
142 break;
143 }
144 if (def >= NDEFAULTS) {
145 fprintf(stderr, "%s: disk too small, calculate by hand\n",
146 *argv);
147 exit(3);
148 }
149
150 /*
151 * Calculate number of cylinders allocated to each disk
152 * partition. We may waste a bit of space here, but it's
153 * in the interest of compatibility (for mixed disk systems).
154 */
155 for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) {
156 numcyls[part] = 0;
157 if (defpart[def][part] != 0) {
158 numcyls[part] = howmany(defpart[def][part], spc);
159 curcyl += numcyls[part];
160 }
161 }
162 numcyls[PART('f')] = dp->d_ncylinders - curcyl;
163 numcyls[PART('g')] =
164 numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')];
165 numcyls[PART('c')] = dp->d_ncylinders;
166 defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable;
167 defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable;
168 defpart[def][PART('c')] = numcyls[PART('c')] * spc;
24bb4240
MK
169 if (!pflag)
170 defpart[def][PART('c')] -= badsecttable;
11236beb
SL
171
172 /*
173 * Calculate starting cylinder number for each partition.
174 * Note the 'h' partition is physically located before the
175 * 'g' or 'd' partition. This is reflected in the layout
176 * arrays defined above.
177 */
178 for (layout = 0; layout < NLAYOUTS; layout++) {
179 curcyl = 0;
180 for (lp = layouts[layout]; *lp != 0; lp++) {
181 startcyl[PART(*lp)] = curcyl;
182 curcyl += numcyls[PART(*lp)];
183 }
184 }
185
186 if (pflag) {
187 printf("}, %s_sizes[%d] = {\n", dp->d_name, NPARTITIONS);
188 for (part = PART('a'); part < NPARTITIONS; part++) {
189 if (numcyls[part] == 0) {
190 printf("\t0,\t0,\n");
191 continue;
192 }
f0a5197a
KM
193 if (dp->d_sectoffset == 0) {
194 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
195 defpart[def][part], startcyl[part],
196 'A' + part, startcyl[part],
197 startcyl[part] + numcyls[part] - 1);
198 continue;
199 }
200 printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
201 defpart[def][part], spc * startcyl[part],
202 'A' + part, spc * startcyl[part],
203 spc * startcyl[part] + defpart[def][part] - 1);
11236beb
SL
204 }
205 exit(0);
206 }
207 if (dflag) {
510f89e2
SL
208 int nparts;
209
11236beb
SL
210 /*
211 * In case the disk is in the ``in-between'' range
212 * where the 'g' partition is smaller than the 'h'
213 * partition, reverse the frag sizes so the /usr partition
214 * is always set up with a frag size larger than the
215 * user's partition.
216 */
217 if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
218 int temp;
219
220 temp = defparam[PART('h')].p_fsize;
221 defparam[PART('h')].p_fsize =
222 defparam[PART('g')].p_fsize;
223 defparam[PART('g')].p_fsize = temp;
224 }
225 printf("%s:\\\n", dp->d_name);
f0a5197a
KM
226 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:%s%s\\\n", dp->d_type,
227 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders,
228 dp->d_badsectforw ? "sf:" : "",
229 dp->d_sectoffset ? "so:" : "");
510f89e2
SL
230 for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
231 if (defpart[def][part] != 0)
232 nparts++;
11236beb
SL
233 for (part = PART('a'); part < NPARTITIONS; part++) {
234 if (defpart[def][part] == 0)
235 continue;
236 printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
510f89e2 237 if (defparam[part].p_bsize != 0) {
11236beb
SL
238 printf("b%c#%d:f%c#%d:",
239 'a' + part, defparam[part].p_bsize,
240 'a' + part, defparam[part].p_fsize);
510f89e2
SL
241 }
242 nparts--;
243 printf("%s\n", nparts > 0 ? "\\" : "");
11236beb
SL
244 }
245 exit(0);
246 }
247 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
248 dp->d_name, dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
249 printf("\n Partition\t Size\t Range\n");
250 for (part = PART('a'); part < NPARTITIONS; part++) {
251 printf("\t%c\t", 'a' + part);
252 if (numcyls[part] == 0) {
253 printf(" unused\n");
254 continue;
255 }
256 printf("%7d\t%4d - %d\n", defpart[def][part], startcyl[part],
257 startcyl[part] + numcyls[part] - 1);
258 }
259}
260
261struct disktab disk;
262
263struct field {
264 char *f_name;
265 char *f_defaults;
266 int *f_location;
267} fields[] = {
268 { "sector size", "512", &disk.d_secsize },
269 { "#sectors/track", 0, &disk.d_nsectors },
270 { "#tracks/cylinder", 0, &disk.d_ntracks },
271 { "#cylinders", 0, &disk.d_ncylinders },
272 { "revolutions/minute", "3600", &disk.d_rpm },
273 { 0, 0, 0 },
274};
275
276struct disktab *
277promptfordisk(name)
278 char *name;
279{
280 register struct disktab *dp = &disk;
281 register struct field *fp;
282 static char type[BUFSIZ];
283 char buf[BUFSIZ], *cp, *gets();
284
285 dp->d_name = name;
286 fprintf(stderr,
287 "%s: unknown disk type, want to supply parameters (y/n)? ",
288 name);
289 (void) gets(buf);
290 if (*buf != 'y')
291 return ((struct disktab *)0);
292gettype:
293 fprintf(stderr, "type (winchester|removable|simulated)? ");
294 (void) gets(type);
295 if (strcmp(type, "winchester") && strcmp(type, "removable") &&
296 strcmp(type, "simulated")) {
297 fprintf(stderr, "%s: bad disk type\n", type);
298 goto gettype;
299 }
300 dp->d_type = type;
301 fprintf(stderr, "(type <cr> to get default value, if only one)\n");
f0a5197a
KM
302 fprintf(stderr, "Do %ss require sector or cylinder offsets (%s)? ",
303 dp->d_name, "cylinder");
304 (void) gets(buf);
305 if (*buf == 's')
306 dp->d_sectoffset = 1;
307 else
308 dp->d_sectoffset = 0;
309 fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ",
310 dp->d_name);
311 (void) gets(buf);
312 if (*buf != 'n')
313 dp->d_badsectforw = 1;
314 else
315 dp->d_badsectforw = 0;
11236beb
SL
316 for (fp = fields; fp->f_name != NULL; fp++) {
317again:
318 fprintf(stderr, "%s ", fp->f_name);
319 if (fp->f_defaults != NULL)
320 fprintf(stderr, "(%s)", fp->f_defaults);
321 fprintf(stderr, "? ");
322 cp = gets(buf);
323 if (*cp == '\0') {
324 if (fp->f_defaults == NULL) {
325 fprintf(stderr, "no default value\n");
326 goto again;
327 }
328 cp = fp->f_defaults;
329 }
330 *fp->f_location = atoi(cp);
331 if (*fp->f_location == 0) {
332 fprintf(stderr, "%s: bad value\n", cp);
333 goto again;
334 }
335 }
336 return (dp);
337}