xref: /original-bsd/usr.sbin/diskpart/diskpart.c (revision 3c32e3a3)
1 #ifndef lint
2 static char sccsid[] = "@(#)diskpart.c	4.3 (Berkeley) 05/03/83";
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
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.
66  */
67 int	badsecttable = 126;	/* # sectors */
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;
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);
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) {
183 		int nparts;
184 
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);
203 		for (nparts = 0, part = PART('a'); part < NPARTITIONS; part++)
204 			if (defpart[def][part] != 0)
205 				nparts++;
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]);
210 			if (defparam[part].p_bsize != 0) {
211 				printf("b%c#%d:f%c#%d:",
212 				  'a' + part, defparam[part].p_bsize,
213 				  'a' + part, defparam[part].p_fsize);
214 			}
215 			nparts--;
216 			printf("%s\n", nparts > 0 ? "\\" : "");
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 }
297