format for 4.3 documentation
[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
f0a5197a 14static char sccsid[] = "@(#)diskpart.c 5.4 (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 */
62 { 0 }, /* b */
63 { 0 }, /* c */
64 { 8192, 1024 }, /* d */
65 { 4096, 512 }, /* e */
66 { 4096, 1024 }, /* f */
67 { 4096, 1024 }, /* g */
68 { 4096, 512 } /* h */
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;
169
170 /*
171 * Calculate starting cylinder number for each partition.
172 * Note the 'h' partition is physically located before the
173 * 'g' or 'd' partition. This is reflected in the layout
174 * arrays defined above.
175 */
176 for (layout = 0; layout < NLAYOUTS; layout++) {
177 curcyl = 0;
178 for (lp = layouts[layout]; *lp != 0; lp++) {
179 startcyl[PART(*lp)] = curcyl;
180 curcyl += numcyls[PART(*lp)];
181 }
182 }
183
184 if (pflag) {
185 printf("}, %s_sizes[%d] = {\n", dp->d_name, NPARTITIONS);
186 for (part = PART('a'); part < NPARTITIONS; part++) {
187 if (numcyls[part] == 0) {
188 printf("\t0,\t0,\n");
189 continue;
190 }
f0a5197a
KM
191 if (dp->d_sectoffset == 0) {
192 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
193 defpart[def][part], startcyl[part],
194 'A' + part, startcyl[part],
195 startcyl[part] + numcyls[part] - 1);
196 continue;
197 }
198 printf("\t%d,\t%d,\t\t/* %c=sectors %d thru %d */\n",
199 defpart[def][part], spc * startcyl[part],
200 'A' + part, spc * startcyl[part],
201 spc * startcyl[part] + defpart[def][part] - 1);
11236beb
SL
202 }
203 exit(0);
204 }
205 if (dflag) {
510f89e2
SL
206 int nparts;
207
11236beb
SL
208 /*
209 * In case the disk is in the ``in-between'' range
210 * where the 'g' partition is smaller than the 'h'
211 * partition, reverse the frag sizes so the /usr partition
212 * is always set up with a frag size larger than the
213 * user's partition.
214 */
215 if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
216 int temp;
217
218 temp = defparam[PART('h')].p_fsize;
219 defparam[PART('h')].p_fsize =
220 defparam[PART('g')].p_fsize;
221 defparam[PART('g')].p_fsize = temp;
222 }
223 printf("%s:\\\n", dp->d_name);
f0a5197a
KM
224 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:%s%s\\\n", dp->d_type,
225 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders,
226 dp->d_badsectforw ? "sf:" : "",
227 dp->d_sectoffset ? "so:" : "");
510f89e2
SL
228 for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
229 if (defpart[def][part] != 0)
230 nparts++;
11236beb
SL
231 for (part = PART('a'); part < NPARTITIONS; part++) {
232 if (defpart[def][part] == 0)
233 continue;
234 printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
510f89e2 235 if (defparam[part].p_bsize != 0) {
11236beb
SL
236 printf("b%c#%d:f%c#%d:",
237 'a' + part, defparam[part].p_bsize,
238 'a' + part, defparam[part].p_fsize);
510f89e2
SL
239 }
240 nparts--;
241 printf("%s\n", nparts > 0 ? "\\" : "");
11236beb
SL
242 }
243 exit(0);
244 }
245 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
246 dp->d_name, dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
247 printf("\n Partition\t Size\t Range\n");
248 for (part = PART('a'); part < NPARTITIONS; part++) {
249 printf("\t%c\t", 'a' + part);
250 if (numcyls[part] == 0) {
251 printf(" unused\n");
252 continue;
253 }
254 printf("%7d\t%4d - %d\n", defpart[def][part], startcyl[part],
255 startcyl[part] + numcyls[part] - 1);
256 }
257}
258
259struct disktab disk;
260
261struct field {
262 char *f_name;
263 char *f_defaults;
264 int *f_location;
265} fields[] = {
266 { "sector size", "512", &disk.d_secsize },
267 { "#sectors/track", 0, &disk.d_nsectors },
268 { "#tracks/cylinder", 0, &disk.d_ntracks },
269 { "#cylinders", 0, &disk.d_ncylinders },
270 { "revolutions/minute", "3600", &disk.d_rpm },
271 { 0, 0, 0 },
272};
273
274struct disktab *
275promptfordisk(name)
276 char *name;
277{
278 register struct disktab *dp = &disk;
279 register struct field *fp;
280 static char type[BUFSIZ];
281 char buf[BUFSIZ], *cp, *gets();
282
283 dp->d_name = name;
284 fprintf(stderr,
285 "%s: unknown disk type, want to supply parameters (y/n)? ",
286 name);
287 (void) gets(buf);
288 if (*buf != 'y')
289 return ((struct disktab *)0);
290gettype:
291 fprintf(stderr, "type (winchester|removable|simulated)? ");
292 (void) gets(type);
293 if (strcmp(type, "winchester") && strcmp(type, "removable") &&
294 strcmp(type, "simulated")) {
295 fprintf(stderr, "%s: bad disk type\n", type);
296 goto gettype;
297 }
298 dp->d_type = type;
299 fprintf(stderr, "(type <cr> to get default value, if only one)\n");
f0a5197a
KM
300 fprintf(stderr, "Do %ss require sector or cylinder offsets (%s)? ",
301 dp->d_name, "cylinder");
302 (void) gets(buf);
303 if (*buf == 's')
304 dp->d_sectoffset = 1;
305 else
306 dp->d_sectoffset = 0;
307 fprintf(stderr, "Do %ss support bad144 bad block forwarding (yes)? ",
308 dp->d_name);
309 (void) gets(buf);
310 if (*buf != 'n')
311 dp->d_badsectforw = 1;
312 else
313 dp->d_badsectforw = 0;
11236beb
SL
314 for (fp = fields; fp->f_name != NULL; fp++) {
315again:
316 fprintf(stderr, "%s ", fp->f_name);
317 if (fp->f_defaults != NULL)
318 fprintf(stderr, "(%s)", fp->f_defaults);
319 fprintf(stderr, "? ");
320 cp = gets(buf);
321 if (*cp == '\0') {
322 if (fp->f_defaults == NULL) {
323 fprintf(stderr, "no default value\n");
324 goto again;
325 }
326 cp = fp->f_defaults;
327 }
328 *fp->f_location = atoi(cp);
329 if (*fp->f_location == 0) {
330 fprintf(stderr, "%s: bad value\n", cp);
331 goto again;
332 }
333 }
334 return (dp);
335}