Commit | Line | Data |
---|---|---|
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 | |
8 | char 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 | 14 | static 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 | |
32 | int 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 | |
45 | char 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 | */ | |
57 | struct 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 | 79 | int badsecttable = 126; /* # sectors */ |
11236beb SL |
80 | |
81 | int pflag; /* print device driver partition tables */ | |
82 | int dflag; /* print disktab entry */ | |
83 | ||
84 | struct disktab *promptfordisk(); | |
85 | ||
86 | main(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 | ||
246 | struct disktab disk; | |
247 | ||
248 | struct 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 | ||
261 | struct disktab * | |
262 | promptfordisk(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); | |
277 | gettype: | |
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++) { | |
288 | again: | |
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 | } |