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