xref: /minix3/minix/commands/partition/partition.c (revision 3083d603ba9dea68befc9da05a714884e10ec7e8)
1433d6423SLionel Sambuc /*	partition 1.13 - Make a partition table		Author: Kees J. Bot
2433d6423SLionel Sambuc  *								27 Apr 1992
3433d6423SLionel Sambuc  */
4433d6423SLionel Sambuc #define nil ((void*)0)
5433d6423SLionel Sambuc #include <stdio.h>
6433d6423SLionel Sambuc #include <sys/types.h>
7433d6423SLionel Sambuc #include <stdlib.h>
8433d6423SLionel Sambuc #include <unistd.h>
9433d6423SLionel Sambuc #include <fcntl.h>
10433d6423SLionel Sambuc #include <sys/stat.h>
11433d6423SLionel Sambuc #include <string.h>
12433d6423SLionel Sambuc #include <errno.h>
13433d6423SLionel Sambuc #include <sys/ioctl.h>
14433d6423SLionel Sambuc #include <limits.h>
15433d6423SLionel Sambuc #include <stdint.h>
167c48de6cSDavid van Moolenbroek #include <inttypes.h>
17433d6423SLionel Sambuc #include <assert.h>
18433d6423SLionel Sambuc 
19433d6423SLionel Sambuc #ifdef __minix
20433d6423SLionel Sambuc #include <machine/partition.h>
21433d6423SLionel Sambuc #include <minix/config.h>
22433d6423SLionel Sambuc #include <minix/const.h>
23433d6423SLionel Sambuc #include <minix/partition.h>
24433d6423SLionel Sambuc #else
25433d6423SLionel Sambuc #include "partition.h"
26433d6423SLionel Sambuc #define NR_PARTITIONS 4
27433d6423SLionel Sambuc #endif
28433d6423SLionel Sambuc 
29433d6423SLionel Sambuc #define SECTOR_SIZE	512
30433d6423SLionel Sambuc 
31433d6423SLionel Sambuc #define arraysize(a)	(sizeof(a)/sizeof((a)[0]))
32433d6423SLionel Sambuc #define arraylimit(a)	((a) + arraysize(a))
33433d6423SLionel Sambuc 
34433d6423SLionel Sambuc char *arg0;
35433d6423SLionel Sambuc 
report(const char * label)36433d6423SLionel Sambuc void report(const char *label)
37433d6423SLionel Sambuc {
38433d6423SLionel Sambuc 	fprintf(stderr, "%s: %s: %s\n", arg0, label, strerror(errno));
39433d6423SLionel Sambuc }
40433d6423SLionel Sambuc 
fatal(const char * label)41433d6423SLionel Sambuc void fatal(const char *label)
42433d6423SLionel Sambuc {
43433d6423SLionel Sambuc 	report(label);
44433d6423SLionel Sambuc 	exit(1);
45433d6423SLionel Sambuc }
46433d6423SLionel Sambuc 
47433d6423SLionel Sambuc int aflag;			/* Add a new partition to the current table. */
48433d6423SLionel Sambuc int mflag;			/* Minix rules, no need for alignment. */
49433d6423SLionel Sambuc int rflag;			/* Report current partitions. */
50433d6423SLionel Sambuc int fflag;			/* Force making a table even if too small. */
51433d6423SLionel Sambuc int nflag;			/* Play-act, don't really do it. */
52433d6423SLionel Sambuc 
53433d6423SLionel Sambuc int cylinders, heads, sectors;	/* Device's geometry */
54433d6423SLionel Sambuc int pad;			/* Partitions must be padded. */
55433d6423SLionel Sambuc 
56433d6423SLionel Sambuc /* Descriptions of the device to divide and the partitions to make, including
57433d6423SLionel Sambuc  * gaps between partitions.
58433d6423SLionel Sambuc  */
59433d6423SLionel Sambuc char *device;
60433d6423SLionel Sambuc struct part_entry primary, table[2 * NR_PARTITIONS + 1];
61433d6423SLionel Sambuc int npart;
62433d6423SLionel Sambuc 
63433d6423SLionel Sambuc /* Extra flags at construction time. */
64433d6423SLionel Sambuc #define EXPAND_FLAG	0x01	/* Add the remaining sectors to this one */
65433d6423SLionel Sambuc #define EXIST_FLAG	0x02	/* Use existing partition */
66433d6423SLionel Sambuc 
find_exist(struct part_entry * exist,int sysind,int nr)67433d6423SLionel Sambuc void find_exist(struct part_entry *exist, int sysind, int nr)
68433d6423SLionel Sambuc {
69433d6423SLionel Sambuc 	int f;
70433d6423SLionel Sambuc 	uint16_t signature;
71433d6423SLionel Sambuc 	struct part_entry oldtable[NR_PARTITIONS];
72433d6423SLionel Sambuc 	int n, i;
73433d6423SLionel Sambuc 	uint32_t minlow, curlow;
74433d6423SLionel Sambuc 	struct part_entry *cur;
75433d6423SLionel Sambuc 	char *nr_s[] = { "", "second ", "third ", "fourth" };
76433d6423SLionel Sambuc 
77433d6423SLionel Sambuc 	if ((f= open(device, O_RDONLY)) < 0
78433d6423SLionel Sambuc 
79433d6423SLionel Sambuc 		|| lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
80433d6423SLionel Sambuc 
81433d6423SLionel Sambuc 		|| read(f, oldtable, sizeof(oldtable)) < 0
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc 		|| read(f, &signature, sizeof(signature)) < 0
84433d6423SLionel Sambuc 
85433d6423SLionel Sambuc 		|| close(f) < 0
86433d6423SLionel Sambuc 	) fatal(device);
87433d6423SLionel Sambuc 
88433d6423SLionel Sambuc 	minlow= 0;
89433d6423SLionel Sambuc 	n= 0;
90433d6423SLionel Sambuc 	for (;;) {
91433d6423SLionel Sambuc 		curlow= -1;
92433d6423SLionel Sambuc 		cur= nil;
93433d6423SLionel Sambuc 		for (i= 0; i < NR_PARTITIONS; i++) {
94433d6423SLionel Sambuc 			if (signature == 0xAA55
95433d6423SLionel Sambuc 				&& oldtable[i].sysind != NO_PART
96433d6423SLionel Sambuc 				&& oldtable[i].lowsec >= minlow
97433d6423SLionel Sambuc 				&& oldtable[i].lowsec < curlow
98433d6423SLionel Sambuc 			) {
99433d6423SLionel Sambuc 				cur= &oldtable[i];
100433d6423SLionel Sambuc 				curlow= oldtable[i].lowsec;
101433d6423SLionel Sambuc 			}
102433d6423SLionel Sambuc 		}
103433d6423SLionel Sambuc 		if (n == nr) break;
104433d6423SLionel Sambuc 		n++;
105433d6423SLionel Sambuc 		minlow= curlow+1;
106433d6423SLionel Sambuc 	}
107433d6423SLionel Sambuc 
108433d6423SLionel Sambuc 	if (cur == nil || cur->sysind != sysind) {
109433d6423SLionel Sambuc 		fprintf(stderr,
110433d6423SLionel Sambuc 		"%s: Can't find a %sexisting partition of type 0x%02X\n",
111433d6423SLionel Sambuc 			arg0, nr_s[nr], sysind);
112433d6423SLionel Sambuc 		exit(1);
113433d6423SLionel Sambuc 	}
114433d6423SLionel Sambuc 	*exist = *cur;
115433d6423SLionel Sambuc }
116433d6423SLionel Sambuc 
write_table(void)117433d6423SLionel Sambuc void write_table(void)
118433d6423SLionel Sambuc {
119433d6423SLionel Sambuc 	int f;
120433d6423SLionel Sambuc 	uint16_t signature= 0xAA55;
121433d6423SLionel Sambuc 	struct part_entry newtable[NR_PARTITIONS];
122433d6423SLionel Sambuc 	int i;
123433d6423SLionel Sambuc 
124433d6423SLionel Sambuc 	if (nflag) {
125433d6423SLionel Sambuc 		printf("(Table not written)\n");
126433d6423SLionel Sambuc 		return;
127433d6423SLionel Sambuc 	}
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc 	for (i= 0; i < NR_PARTITIONS; i++) newtable[i]= table[1 + 2*i];
130433d6423SLionel Sambuc 
131433d6423SLionel Sambuc 	/* we have a abstract struct but it must conform to a certain
132433d6423SLionel Sambuc 	 * reality that will never change (in-MBR sizes and offsets).
133433d6423SLionel Sambuc 	 * each partition entry is 16 bytes and there are 4 of them.
134433d6423SLionel Sambuc 	 * this also determines the signature offset.
135433d6423SLionel Sambuc 	 */
136433d6423SLionel Sambuc 	assert(sizeof(struct part_entry) == 16);
137433d6423SLionel Sambuc 	assert(sizeof(newtable) == 64);
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc 	if ((f= open(device, O_WRONLY)) < 0
140433d6423SLionel Sambuc 
141433d6423SLionel Sambuc 		|| lseek(f, (off_t) PART_TABLE_OFF, SEEK_SET) == -1
142433d6423SLionel Sambuc 
143433d6423SLionel Sambuc 		|| write(f, newtable, sizeof(newtable)) < 0
144433d6423SLionel Sambuc 
145433d6423SLionel Sambuc 		|| write(f, &signature, sizeof(signature)) < 0
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc 		|| close(f) < 0
148433d6423SLionel Sambuc 	) fatal(device);
149433d6423SLionel Sambuc }
150433d6423SLionel Sambuc 
sec2dos(unsigned long sec,unsigned char * dos)151433d6423SLionel Sambuc void sec2dos(unsigned long sec, unsigned char *dos)
152433d6423SLionel Sambuc /* Translate a sector number into the three bytes DOS uses. */
153433d6423SLionel Sambuc {
154433d6423SLionel Sambuc 	unsigned secspcyl= heads * sectors;
155433d6423SLionel Sambuc 	unsigned cyl;
156433d6423SLionel Sambuc 
157433d6423SLionel Sambuc 	cyl= sec / secspcyl;
158433d6423SLionel Sambuc 	dos[2]= cyl;
159433d6423SLionel Sambuc 	dos[1]= ((sec % sectors) + 1) | ((cyl >> 2) & 0xC0);
160433d6423SLionel Sambuc 	dos[0]= (sec % secspcyl) / sectors;
161433d6423SLionel Sambuc }
162433d6423SLionel Sambuc 
show_chs(unsigned long pos)163433d6423SLionel Sambuc void show_chs(unsigned long pos)
164433d6423SLionel Sambuc {
165433d6423SLionel Sambuc 	int cyl, head, sec;
166433d6423SLionel Sambuc 
167433d6423SLionel Sambuc 	if (pos == -1) {
168433d6423SLionel Sambuc 		cyl= head= 0;
169433d6423SLionel Sambuc 		sec= -1;
170433d6423SLionel Sambuc 	} else {
171433d6423SLionel Sambuc 		cyl= pos / (heads * sectors);
172433d6423SLionel Sambuc 		head= (pos / sectors) - (cyl * heads);
173433d6423SLionel Sambuc 		sec= pos % sectors;
174433d6423SLionel Sambuc 	}
175433d6423SLionel Sambuc 	printf("  %4d/%03d/%02d", cyl, head, sec);
176433d6423SLionel Sambuc }
177433d6423SLionel Sambuc 
show_part(struct part_entry * p)178433d6423SLionel Sambuc void show_part(struct part_entry *p)
179433d6423SLionel Sambuc {
180433d6423SLionel Sambuc 	static int banner= 0;
181433d6423SLionel Sambuc 	int n;
182433d6423SLionel Sambuc 
183433d6423SLionel Sambuc 	n= p - table;
184433d6423SLionel Sambuc 	if ((n % 2) == 0) return;
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc 	if (!banner) {
187433d6423SLionel Sambuc 		printf(
188433d6423SLionel Sambuc 	"Part     First         Last         Base      Size       Kb\n");
189433d6423SLionel Sambuc 		banner= 1;
190433d6423SLionel Sambuc 	}
191433d6423SLionel Sambuc 
192433d6423SLionel Sambuc 	printf("%3d ", (n-1) / 2);
193433d6423SLionel Sambuc 	show_chs(p->lowsec);
194433d6423SLionel Sambuc 	show_chs(p->lowsec + p->size - 1);
1957c48de6cSDavid van Moolenbroek 	printf("  %8"PRIu32"  %8"PRIu32"  %7"PRIu32"\n",
1967c48de6cSDavid van Moolenbroek 	    p->lowsec, p->size, p->size / 2);
197433d6423SLionel Sambuc }
198433d6423SLionel Sambuc 
usage(void)199433d6423SLionel Sambuc void usage(void)
200433d6423SLionel Sambuc {
201433d6423SLionel Sambuc 	fprintf(stderr,
202433d6423SLionel Sambuc 		"Usage: partition [-mfn] device [type:]length[+*] ...\n");
203433d6423SLionel Sambuc 	exit(1);
204433d6423SLionel Sambuc }
205433d6423SLionel Sambuc 
206433d6423SLionel Sambuc #define between(a, c, z)	((unsigned) ((c) - (a)) <= ((z) - (a)))
207433d6423SLionel Sambuc 
parse(char * descr)208433d6423SLionel Sambuc void parse(char *descr)
209433d6423SLionel Sambuc {
210433d6423SLionel Sambuc 	int seen= 0, sysind, flags, c;
211433d6423SLionel Sambuc 	unsigned long lowsec, size;
212433d6423SLionel Sambuc 
213433d6423SLionel Sambuc 	lowsec= 0;
214433d6423SLionel Sambuc 
215433d6423SLionel Sambuc 	if (strchr(descr, ':') == nil) {
216433d6423SLionel Sambuc 		/* A hole. */
217433d6423SLionel Sambuc 		if ((npart % 2) != 0) {
218433d6423SLionel Sambuc 			fprintf(stderr, "%s: Two holes can't be adjacent.\n",
219433d6423SLionel Sambuc 				arg0);
220433d6423SLionel Sambuc 			exit(1);
221433d6423SLionel Sambuc 		}
222433d6423SLionel Sambuc 		sysind= NO_PART;
223433d6423SLionel Sambuc 		seen|= 1;
224433d6423SLionel Sambuc 	} else {
225433d6423SLionel Sambuc 		/* A partition. */
226433d6423SLionel Sambuc 		if ((npart % 2) == 0) {
227433d6423SLionel Sambuc 			/* Need a hole before this partition. */
228433d6423SLionel Sambuc 			if (npart == 0) {
229433d6423SLionel Sambuc 				/* First hole contains the partition table. */
230433d6423SLionel Sambuc 				table[0].size= 1;
231433d6423SLionel Sambuc 			}
232433d6423SLionel Sambuc 			npart++;
233433d6423SLionel Sambuc 		}
234433d6423SLionel Sambuc 		sysind= 0;
235433d6423SLionel Sambuc 		for (;;) {
236433d6423SLionel Sambuc 			c= *descr++;
237433d6423SLionel Sambuc 			if (between('0', c, '9'))
238433d6423SLionel Sambuc 				c= (c - '0') + 0x0;
239433d6423SLionel Sambuc 			else
240433d6423SLionel Sambuc 			if (between('a', c, 'z'))
241433d6423SLionel Sambuc 				c= (c - 'a') + 0xa;
242433d6423SLionel Sambuc 			else
243433d6423SLionel Sambuc 			if (between('A', c, 'Z'))
244433d6423SLionel Sambuc 				c= (c - 'A') + 0xA;
245433d6423SLionel Sambuc 			else
246433d6423SLionel Sambuc 				break;
247433d6423SLionel Sambuc 			sysind= 0x10 * sysind + c;
248433d6423SLionel Sambuc 			seen|= 1;
249433d6423SLionel Sambuc 		}
250433d6423SLionel Sambuc 		if (c != ':') usage();
251433d6423SLionel Sambuc 	}
252433d6423SLionel Sambuc 
253433d6423SLionel Sambuc 	flags= 0;
254433d6423SLionel Sambuc 
255433d6423SLionel Sambuc 	if (strncmp(descr, "exist", 5) == 0 && (npart % 2) == 1) {
256433d6423SLionel Sambuc 		struct part_entry exist;
257433d6423SLionel Sambuc 
258433d6423SLionel Sambuc 		find_exist(&exist, sysind, (npart - 1) / 2);
259433d6423SLionel Sambuc 		sysind= exist.sysind;
260433d6423SLionel Sambuc 		lowsec= exist.lowsec;
261433d6423SLionel Sambuc 		size= exist.size;
262433d6423SLionel Sambuc 		flags |= EXIST_FLAG;
263433d6423SLionel Sambuc 		descr += 5;
264433d6423SLionel Sambuc 		c= *descr++;
265433d6423SLionel Sambuc 		seen|= 2;
266433d6423SLionel Sambuc 	} else {
267433d6423SLionel Sambuc 		size= 0;
268433d6423SLionel Sambuc 		while (between('0', (c= *descr++), '9')) {
269433d6423SLionel Sambuc 			size= 10 * size + (c - '0');
270433d6423SLionel Sambuc 			seen|= 2;
271433d6423SLionel Sambuc 		}
272433d6423SLionel Sambuc 	}
273433d6423SLionel Sambuc 
274433d6423SLionel Sambuc 	for (;;) {
275433d6423SLionel Sambuc 		if (c == '*')
276433d6423SLionel Sambuc 			flags|= ACTIVE_FLAG;
277433d6423SLionel Sambuc 		else
278433d6423SLionel Sambuc 		if (c == '+' && !(flags & EXIST_FLAG))
279433d6423SLionel Sambuc 			flags|= EXPAND_FLAG;
280433d6423SLionel Sambuc 		else
281433d6423SLionel Sambuc 			break;
282433d6423SLionel Sambuc 		c= *descr++;
283433d6423SLionel Sambuc 	}
284433d6423SLionel Sambuc 
285433d6423SLionel Sambuc 	if (seen != 3 || c != 0) usage();
286433d6423SLionel Sambuc 
287433d6423SLionel Sambuc 	if (npart == arraysize(table)) {
288433d6423SLionel Sambuc 		fprintf(stderr, "%s: too many partitions, only %d possible.\n",
289433d6423SLionel Sambuc 			arg0, NR_PARTITIONS);
290433d6423SLionel Sambuc 		exit(1);
291433d6423SLionel Sambuc 	}
292433d6423SLionel Sambuc 	table[npart].bootind= flags;
293433d6423SLionel Sambuc 	table[npart].sysind= sysind;
294433d6423SLionel Sambuc 	table[npart].lowsec= lowsec;
295433d6423SLionel Sambuc 	table[npart].size= size;
296433d6423SLionel Sambuc 	npart++;
297433d6423SLionel Sambuc }
298433d6423SLionel Sambuc 
geometry(void)299433d6423SLionel Sambuc void geometry(void)
300433d6423SLionel Sambuc /* Get the geometry of the drive the device lives on, and the base and size
301433d6423SLionel Sambuc  * of the device.
302433d6423SLionel Sambuc  */
303433d6423SLionel Sambuc {
304433d6423SLionel Sambuc 	int fd;
305433d6423SLionel Sambuc 	struct stat sb;
306433d6423SLionel Sambuc 
307433d6423SLionel Sambuc 	if ((fd= open(device, O_RDONLY)) < 0) fatal(device);
308433d6423SLionel Sambuc 
309433d6423SLionel Sambuc #ifdef __minix
310433d6423SLionel Sambuc 	struct part_geom geometry;
311433d6423SLionel Sambuc 
312433d6423SLionel Sambuc 
313433d6423SLionel Sambuc 	/* Get the geometry of the drive, and the device's base and size. */
314433d6423SLionel Sambuc 	if (ioctl(fd, DIOCGETP, &geometry) < 0)
315433d6423SLionel Sambuc 	{
316433d6423SLionel Sambuc 		/* Use the same fake geometry as part. */
317433d6423SLionel Sambuc 		if (fstat(fd, &sb) < 0)
318433d6423SLionel Sambuc 			fatal(device);
319433d6423SLionel Sambuc 		geometry.base= ((u64_t)(0));
320433d6423SLionel Sambuc 		geometry.size= ((u64_t)(sb.st_size));
321433d6423SLionel Sambuc 		geometry.sectors= 32;
322433d6423SLionel Sambuc 		geometry.heads= 64;
323433d6423SLionel Sambuc 		geometry.cylinders= (sb.st_size-1)/SECTOR_SIZE/
324433d6423SLionel Sambuc 			(geometry.sectors*geometry.heads) + 1;
325433d6423SLionel Sambuc 	}
326433d6423SLionel Sambuc 	primary.lowsec= (unsigned long)(geometry.base / SECTOR_SIZE);
327433d6423SLionel Sambuc 	primary.size  = (unsigned long)(geometry.size / SECTOR_SIZE);
328433d6423SLionel Sambuc 	cylinders= geometry.cylinders;
329433d6423SLionel Sambuc 	heads= geometry.heads;
330433d6423SLionel Sambuc 	sectors= geometry.sectors;
331433d6423SLionel Sambuc #else
332433d6423SLionel Sambuc 	if (fstat(fd, &sb) < 0) fatal(device);
333433d6423SLionel Sambuc 	primary.lowsec= 0;
334433d6423SLionel Sambuc 	primary.size= sb.st_size / SECTOR_SIZE;
335433d6423SLionel Sambuc 	heads= 64;
336433d6423SLionel Sambuc 	sectors= 32;
337433d6423SLionel Sambuc 	cylinders= (sb.st_size-1) / SECTOR_SIZE / (sectors*heads) + 1;
338433d6423SLionel Sambuc #endif
339433d6423SLionel Sambuc 
340433d6423SLionel Sambuc 	close(fd);
341433d6423SLionel Sambuc 
342433d6423SLionel Sambuc 	/* Is this a primary partition table?  If so then pad partitions. */
343433d6423SLionel Sambuc 	pad= (!mflag && primary.lowsec == 0);
344433d6423SLionel Sambuc }
345433d6423SLionel Sambuc 
boundary(struct part_entry * pe,int exp)346433d6423SLionel Sambuc void boundary(struct part_entry *pe, int exp)
347433d6423SLionel Sambuc /* Expand or reduce a primary partition to a track or cylinder boundary to
348433d6423SLionel Sambuc  * avoid giving the fdisk's of simpler operating systems a fit.
349433d6423SLionel Sambuc  */
350433d6423SLionel Sambuc {
351433d6423SLionel Sambuc 	unsigned n;
352433d6423SLionel Sambuc 
353433d6423SLionel Sambuc 	n= !pad ? 1 : pe == &table[0] ? sectors : heads * sectors;
354433d6423SLionel Sambuc 	if (exp) pe->size+= n - 1;
355433d6423SLionel Sambuc 	pe->size= ((pe->lowsec + pe->size) / n * n) - pe->lowsec;
356433d6423SLionel Sambuc }
357433d6423SLionel Sambuc 
distribute(void)358433d6423SLionel Sambuc void distribute(void)
359433d6423SLionel Sambuc /* Fit the partitions onto the device.  Try to start and end them on a
360433d6423SLionel Sambuc  * cylinder boundary if so required.  The first partition is to start on
361433d6423SLionel Sambuc  * track 1, not on cylinder 1.
362433d6423SLionel Sambuc  */
363433d6423SLionel Sambuc {
364433d6423SLionel Sambuc 	struct part_entry *pe, *exp;
365433d6423SLionel Sambuc 	long count;
366433d6423SLionel Sambuc 	unsigned long base, oldbase;
367433d6423SLionel Sambuc 
368433d6423SLionel Sambuc 	do {
369433d6423SLionel Sambuc 		exp= nil;
370433d6423SLionel Sambuc 		base= primary.lowsec;
371433d6423SLionel Sambuc 		count= primary.size;
372433d6423SLionel Sambuc 
373433d6423SLionel Sambuc 		for (pe= table; pe < arraylimit(table); pe++) {
374433d6423SLionel Sambuc 			oldbase= base;
375433d6423SLionel Sambuc 			if (pe->bootind & EXIST_FLAG) {
376433d6423SLionel Sambuc 				if (base > pe->lowsec) {
377433d6423SLionel Sambuc 					fprintf(stderr,
378d0055759SDavid van Moolenbroek 	"%s: fixed partition %u is preceded by too big partitions/holes\n",
379*3083d603SDavid van Moolenbroek 				arg0, ((unsigned int)(pe - table) - 1) / 2);
380433d6423SLionel Sambuc 					exit(1);
381433d6423SLionel Sambuc 				}
382433d6423SLionel Sambuc 				exp= nil;	/* XXX - Extend before? */
383433d6423SLionel Sambuc 			} else {
384433d6423SLionel Sambuc 				pe->lowsec= base;
385433d6423SLionel Sambuc 				boundary(pe, 1);
386433d6423SLionel Sambuc 				if (pe->bootind & EXPAND_FLAG) exp= pe;
387433d6423SLionel Sambuc 			}
388433d6423SLionel Sambuc 			base= pe->lowsec + pe->size;
389433d6423SLionel Sambuc 			count-= base - oldbase;
390433d6423SLionel Sambuc 		}
391433d6423SLionel Sambuc 		if (count < 0) {
392433d6423SLionel Sambuc 			if (fflag) break;
393433d6423SLionel Sambuc 			fprintf(stderr, "%s: %s is %ld sectors too small\n",
394433d6423SLionel Sambuc 				arg0, device, -count);
395433d6423SLionel Sambuc 			exit(1);
396433d6423SLionel Sambuc 		}
397433d6423SLionel Sambuc 		if (exp != nil) {
398433d6423SLionel Sambuc 			/* Add leftover space to the partition marked for
399433d6423SLionel Sambuc 			 * expanding.
400433d6423SLionel Sambuc 			 */
401433d6423SLionel Sambuc 			exp->size+= count;
402433d6423SLionel Sambuc 			boundary(exp, 0);
403433d6423SLionel Sambuc 			exp->bootind&= ~EXPAND_FLAG;
404433d6423SLionel Sambuc 		}
405433d6423SLionel Sambuc 	} while (exp != nil);
406433d6423SLionel Sambuc 
407433d6423SLionel Sambuc 	for (pe= table; pe < arraylimit(table); pe++) {
408433d6423SLionel Sambuc 		if (pe->sysind == NO_PART) {
409433d6423SLionel Sambuc 			memset(pe, 0, sizeof(*pe));
410433d6423SLionel Sambuc 		} else {
411433d6423SLionel Sambuc 			sec2dos(pe->lowsec, &pe->start_head);
412433d6423SLionel Sambuc 			sec2dos(pe->lowsec + pe->size - 1, &pe->last_head);
413433d6423SLionel Sambuc 			pe->bootind&= ACTIVE_FLAG;
414433d6423SLionel Sambuc 		}
415433d6423SLionel Sambuc 		show_part(pe);
416433d6423SLionel Sambuc 	}
417433d6423SLionel Sambuc }
418433d6423SLionel Sambuc 
main(int argc,char ** argv)419433d6423SLionel Sambuc int main(int argc, char **argv)
420433d6423SLionel Sambuc {
421433d6423SLionel Sambuc 	int i;
422433d6423SLionel Sambuc 
423433d6423SLionel Sambuc 	if ((arg0= strrchr(argv[0], '/')) == nil) arg0= argv[0]; else arg0++;
424433d6423SLionel Sambuc 
425433d6423SLionel Sambuc 	i= 1;
426433d6423SLionel Sambuc 	while (i < argc && argv[i][0] == '-') {
427433d6423SLionel Sambuc 		char *opt= argv[i++] + 1;
428433d6423SLionel Sambuc 
429433d6423SLionel Sambuc 		if (opt[0] == '-' && opt[1] == 0) break;
430433d6423SLionel Sambuc 
431433d6423SLionel Sambuc 		while (*opt != 0) switch (*opt++) {
432433d6423SLionel Sambuc 		case 'a':	aflag= 1;	break;
433433d6423SLionel Sambuc 		case 'm':	mflag= 1;	break;
434433d6423SLionel Sambuc 		case 'r':	rflag= 1;	break;
435433d6423SLionel Sambuc 		case 'f':	fflag= 1;	break;
436433d6423SLionel Sambuc 		case 'n':	nflag= 1;	break;
437433d6423SLionel Sambuc 		default:	usage();
438433d6423SLionel Sambuc 		}
439433d6423SLionel Sambuc 	}
440433d6423SLionel Sambuc 
441433d6423SLionel Sambuc 	if (rflag) {
442433d6423SLionel Sambuc 		if (aflag) usage();
443433d6423SLionel Sambuc 		if ((argc - i) != 1) usage();
444433d6423SLionel Sambuc 		fprintf(stderr, "%s: -r is not yet implemented\n", __func__);
445433d6423SLionel Sambuc 		exit(1);
446433d6423SLionel Sambuc 	} else {
447433d6423SLionel Sambuc 		if ((argc - i) < 1) usage();
448433d6423SLionel Sambuc 		if (aflag) fprintf(stderr, "%s: -a is not yet implemented\n", __func__);
449433d6423SLionel Sambuc 
450433d6423SLionel Sambuc 		device= argv[i++];
451433d6423SLionel Sambuc 		geometry();
452433d6423SLionel Sambuc 
453433d6423SLionel Sambuc 		while (i < argc) parse(argv[i++]);
454433d6423SLionel Sambuc 
455433d6423SLionel Sambuc 		distribute();
456433d6423SLionel Sambuc 		write_table();
457433d6423SLionel Sambuc 	}
458433d6423SLionel Sambuc 	exit(0);
459433d6423SLionel Sambuc }
460