lint
[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
da158ee3 14static char sccsid[] = "@(#)diskpart.c 5.3 (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
SL
125 threshhold = howmany(spc, badsecttable);
126
127 /*
128 * Figure out if disk is large enough for
129 * expanded swap area and 'd', 'e', and 'f'
130 * partitions. Otherwise, use smaller defaults
131 * based on RK07.
132 */
133 for (def = 0; def < NDEFAULTS; def++) {
134 curcyl = 0;
135 for (part = PART('a'); part < NPARTITIONS; part++)
136 curcyl += howmany(defpart[def][part], spc);
137 if (curcyl < dp->d_ncylinders - threshhold)
138 break;
139 }
140 if (def >= NDEFAULTS) {
141 fprintf(stderr, "%s: disk too small, calculate by hand\n",
142 *argv);
143 exit(3);
144 }
145
146 /*
147 * Calculate number of cylinders allocated to each disk
148 * partition. We may waste a bit of space here, but it's
149 * in the interest of compatibility (for mixed disk systems).
150 */
151 for (curcyl = 0, part = PART('a'); part < NPARTITIONS; part++) {
152 numcyls[part] = 0;
153 if (defpart[def][part] != 0) {
154 numcyls[part] = howmany(defpart[def][part], spc);
155 curcyl += numcyls[part];
156 }
157 }
158 numcyls[PART('f')] = dp->d_ncylinders - curcyl;
159 numcyls[PART('g')] =
160 numcyls[PART('d')] + numcyls[PART('e')] + numcyls[PART('f')];
161 numcyls[PART('c')] = dp->d_ncylinders;
162 defpart[def][PART('f')] = numcyls[PART('f')] * spc - badsecttable;
163 defpart[def][PART('g')] = numcyls[PART('g')] * spc - badsecttable;
164 defpart[def][PART('c')] = numcyls[PART('c')] * spc;
165
166 /*
167 * Calculate starting cylinder number for each partition.
168 * Note the 'h' partition is physically located before the
169 * 'g' or 'd' partition. This is reflected in the layout
170 * arrays defined above.
171 */
172 for (layout = 0; layout < NLAYOUTS; layout++) {
173 curcyl = 0;
174 for (lp = layouts[layout]; *lp != 0; lp++) {
175 startcyl[PART(*lp)] = curcyl;
176 curcyl += numcyls[PART(*lp)];
177 }
178 }
179
180 if (pflag) {
181 printf("}, %s_sizes[%d] = {\n", dp->d_name, NPARTITIONS);
182 for (part = PART('a'); part < NPARTITIONS; part++) {
183 if (numcyls[part] == 0) {
184 printf("\t0,\t0,\n");
185 continue;
186 }
187 printf("\t%d,\t%d,\t\t/* %c=cyl %d thru %d */\n",
188 defpart[def][part], startcyl[part],
189 'A' + part, startcyl[part],
190 startcyl[part] + numcyls[part] - 1);
191 }
192 exit(0);
193 }
194 if (dflag) {
510f89e2
SL
195 int nparts;
196
11236beb
SL
197 /*
198 * In case the disk is in the ``in-between'' range
199 * where the 'g' partition is smaller than the 'h'
200 * partition, reverse the frag sizes so the /usr partition
201 * is always set up with a frag size larger than the
202 * user's partition.
203 */
204 if (defpart[def][PART('g')] < defpart[def][PART('h')]) {
205 int temp;
206
207 temp = defparam[PART('h')].p_fsize;
208 defparam[PART('h')].p_fsize =
209 defparam[PART('g')].p_fsize;
210 defparam[PART('g')].p_fsize = temp;
211 }
212 printf("%s:\\\n", dp->d_name);
213 printf("\t:ty=%s:ns#%d:nt#%d:nc#%d:\\\n", dp->d_type,
214 dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
510f89e2
SL
215 for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
216 if (defpart[def][part] != 0)
217 nparts++;
11236beb
SL
218 for (part = PART('a'); part < NPARTITIONS; part++) {
219 if (defpart[def][part] == 0)
220 continue;
221 printf("\t:p%c#%d:", 'a' + part, defpart[def][part]);
510f89e2 222 if (defparam[part].p_bsize != 0) {
11236beb
SL
223 printf("b%c#%d:f%c#%d:",
224 'a' + part, defparam[part].p_bsize,
225 'a' + part, defparam[part].p_fsize);
510f89e2
SL
226 }
227 nparts--;
228 printf("%s\n", nparts > 0 ? "\\" : "");
11236beb
SL
229 }
230 exit(0);
231 }
232 printf("%s: #sectors/track=%d, #tracks/cylinder=%d #cylinders=%d\n",
233 dp->d_name, dp->d_nsectors, dp->d_ntracks, dp->d_ncylinders);
234 printf("\n Partition\t Size\t Range\n");
235 for (part = PART('a'); part < NPARTITIONS; part++) {
236 printf("\t%c\t", 'a' + part);
237 if (numcyls[part] == 0) {
238 printf(" unused\n");
239 continue;
240 }
241 printf("%7d\t%4d - %d\n", defpart[def][part], startcyl[part],
242 startcyl[part] + numcyls[part] - 1);
243 }
244}
245
246struct disktab disk;
247
248struct field {
249 char *f_name;
250 char *f_defaults;
251 int *f_location;
252} fields[] = {
253 { "sector size", "512", &disk.d_secsize },
254 { "#sectors/track", 0, &disk.d_nsectors },
255 { "#tracks/cylinder", 0, &disk.d_ntracks },
256 { "#cylinders", 0, &disk.d_ncylinders },
257 { "revolutions/minute", "3600", &disk.d_rpm },
258 { 0, 0, 0 },
259};
260
261struct disktab *
262promptfordisk(name)
263 char *name;
264{
265 register struct disktab *dp = &disk;
266 register struct field *fp;
267 static char type[BUFSIZ];
268 char buf[BUFSIZ], *cp, *gets();
269
270 dp->d_name = name;
271 fprintf(stderr,
272 "%s: unknown disk type, want to supply parameters (y/n)? ",
273 name);
274 (void) gets(buf);
275 if (*buf != 'y')
276 return ((struct disktab *)0);
277gettype:
278 fprintf(stderr, "type (winchester|removable|simulated)? ");
279 (void) gets(type);
280 if (strcmp(type, "winchester") && strcmp(type, "removable") &&
281 strcmp(type, "simulated")) {
282 fprintf(stderr, "%s: bad disk type\n", type);
283 goto gettype;
284 }
285 dp->d_type = type;
286 fprintf(stderr, "(type <cr> to get default value, if only one)\n");
287 for (fp = fields; fp->f_name != NULL; fp++) {
288again:
289 fprintf(stderr, "%s ", fp->f_name);
290 if (fp->f_defaults != NULL)
291 fprintf(stderr, "(%s)", fp->f_defaults);
292 fprintf(stderr, "? ");
293 cp = gets(buf);
294 if (*cp == '\0') {
295 if (fp->f_defaults == NULL) {
296 fprintf(stderr, "no default value\n");
297 goto again;
298 }
299 cp = fp->f_defaults;
300 }
301 *fp->f_location = atoi(cp);
302 if (*fp->f_location == 0) {
303 fprintf(stderr, "%s: bad value\n", cp);
304 goto again;
305 }
306 }
307 return (dp);
308}