xref: /freebsd/sbin/fdisk/fdisk.c (revision 9ee40678bbdcedc6a3ac1e311abe740018911cf1)
1 /*
2  * Mach Operating System
3  * Copyright (c) 1992 Carnegie Mellon University
4  * All Rights Reserved.
5  *
6  * Permission to use, copy, modify and distribute this software and its
7  * documentation is hereby granted, provided that both the copyright
8  * notice and this permission notice appear in all copies of the
9  * software, derivative works or modified versions, and any portions
10  * thereof, and that both notices appear in supporting documentation.
11  *
12  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
13  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
14  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
15  *
16  * Carnegie Mellon requests users of this software to return to
17  *
18  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
19  *  School of Computer Science
20  *  Carnegie Mellon University
21  *  Pittsburgh PA 15213-3890
22  *
23  * any improvements or extensions that they make and grant Carnegie Mellon
24  * the rights to redistribute these changes.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/disklabel.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include <errno.h>
32 #include <sys/stat.h>
33 #include <sys/ioctl.h>
34 #include <fcntl.h>
35 #include <unistd.h>
36 
37 int iotest;
38 
39 #define LBUF 100
40 static char lbuf[LBUF];
41 
42 /*
43  *
44  * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
45  *
46  * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
47  *	Copyright (c) 1989	Robert. V. Baron
48  *	Created.
49  */
50 
51 #define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
52 #define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
53 #define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
54 
55 #define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
56 
57 #define SECSIZE 512
58 
59 const char *disk;
60 const char *disks[] =
61 {
62   "/dev/rwd0", "/dev/rsd0", "/dev/rod0", 0
63 };
64 
65 char *name;
66 
67 struct disklabel disklabel;		/* disk parameters */
68 
69 int cyls, sectors, heads, cylsecs, disksecs;
70 
71 struct mboot
72 {
73 	unsigned char padding[2]; /* force the longs to be long alligned */
74 	unsigned char bootinst[DOSPARTOFF];
75 	struct	dos_partition parts[4];
76 	unsigned short int	signature;
77 };
78 struct mboot mboot;
79 
80 #define ACTIVE 0x80
81 #define BOOT_MAGIC 0xAA55
82 
83 int dos_cyls;
84 int dos_heads;
85 int dos_sectors;
86 int dos_cylsecs;
87 
88 #define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
89 #define DOSCYL(c)	(c & 0xff)
90 static int partition = -1;
91 
92 
93 static int a_flag  = 0;		/* set active partition */
94 static int i_flag  = 0;		/* replace partition data */
95 static int u_flag  = 0;		/* update partition data */
96 
97 static unsigned char bootcode[] = {
98 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
99 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
100 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
101 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
102 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
103 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
104 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
105 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
106 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
107 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
108 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
109 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
110 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
111 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
112 	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
113 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
114 	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
115 
116   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
117   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
118   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
119   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
120   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
121   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
122   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
123   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
124   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
125   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
126   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
127   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
128   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
129 };
130 
131 struct part_type
132 {
133  unsigned char type;
134  char *name;
135 }part_types[] =
136 {
137 	 {0x00, "unused"}
138 	,{0x01, "Primary DOS with 12 bit FAT"}
139 	,{0x02, "XENIX / filesystem"}
140 	,{0x03, "XENIX /usr filesystem"}
141 	,{0x04, "Primary DOS with 16 bit FAT"}
142 	,{0x05, "Extended DOS"}
143 	,{0x06, "Primary 'big' DOS (> 32MB)"}
144 	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
145 	,{0x08, "AIX filesystem"}
146 	,{0x09, "AIX boot partition or Coherent"}
147 	,{0x0A, "OS/2 Boot Manager or OPUS"}
148 	,{0x10, "OPUS"}
149 	,{0x40, "VENIX 286"}
150 	,{0x50, "DM"}
151 	,{0x51, "DM"}
152 	,{0x52, "CP/M or Microport SysV/AT"}
153 	,{0x56, "GB"}
154 	,{0x61, "Speed"}
155 	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
156 	,{0x64, "Novell Netware 2.xx"}
157 	,{0x65, "Novell Netware 3.xx"}
158 	,{0x75, "PCIX"}
159 	,{0x80, "Minix 1.1 ... 1.4a"}
160 	,{0x81, "Minix 1.4b ... 1.5.10"}
161 	,{0x82, "Linux swap"}
162 	,{0x83, "Linux filesystem"}
163 	,{0x93, "Amoeba filesystem"}
164 	,{0x94, "Amoeba bad block table"}
165 	,{0xA5, "FreeBSD/NetBSD/386BSD"}
166 	,{0xA7, "NEXTSTEP"}
167 	,{0xB7, "BSDI BSD/386 filesystem"}
168 	,{0xB8, "BSDI BSD/386 swap"}
169 	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
170 	,{0xE1, "Speed"}
171 	,{0xE3, "Speed"}
172 	,{0xE4, "Speed"}
173 	,{0xF1, "Speed"}
174 	,{0xF2, "DOS 3.3+ Secondary"}
175 	,{0xF4, "Speed"}
176 	,{0xFF, "BBT (Bad Blocks Table)"}
177 };
178 
179 static void print_s0(int which);
180 static void print_part(int i);
181 static void init_sector0(unsigned long start);
182 static void change_part(int i);
183 static void print_params();
184 static void change_active(int which);
185 static void get_params_to_use();
186 static void dos(int sec, int size, unsigned char *c, unsigned char *s,
187 		unsigned char *h);
188 static int open_disk(int u_flag);
189 static ssize_t read_disk(off_t sector, void *buf);
190 static ssize_t write_disk(off_t sector, void *buf);
191 static int get_params();
192 static int read_s0();
193 static int write_s0();
194 static int ok(char *str);
195 static int decimal(char *str, int *num, int deflt);
196 static char *get_type(int type);
197 #if 0
198 static int hex(char *str, int *num, int deflt);
199 static int string(char *str, char **ans);
200 #endif
201 
202 
203 int
204 main(int argc, char *argv[])
205 {
206 	int	i;
207 
208 	name = *argv;
209 	{register char *cp = name;
210 		while (*cp) if (*cp++ == '/') name = cp;
211 	}
212 
213 	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
214 		if (*token++ != '-' || !*token)
215 			break;
216 		else { register int flag;
217 			for ( ; (flag = *token++) ; ) {
218 				switch (flag) {
219 				case '0':
220 					partition = 0;
221 					break;
222 				case '1':
223 					partition = 1;
224 					break;
225 				case '2':
226 					partition = 2;
227 					break;
228 				case '3':
229 					partition = 3;
230 					break;
231 				case 'a':
232 					a_flag = 1;
233 					break;
234 				case 'i':
235 					i_flag = 1;
236 				case 'u':
237 					u_flag = 1;
238 					break;
239 				default:
240 					goto usage;
241 				}
242 			}
243 		}
244 	}
245 
246 	if (argc > 0)
247 	{
248 		static char realname[12];
249 
250 		if(strncmp(argv[0], "/dev", 4) == 0)
251 			disk = argv[0];
252 		else
253 		{
254 			snprintf(realname, 12, "/dev/r%s", argv[0]);
255 			disk = realname;
256 		}
257 
258 		if (open_disk(u_flag) < 0)
259 		{
260 			fprintf(stderr, "Cannot open disk %s (%s)\n",
261 				disk, sys_errlist[errno]);
262 			exit(1);
263 		}
264 	}
265 	else
266 	{
267 		int i, rv = 0;
268 
269 		for(i = 0; disks[i]; i++)
270 		{
271 			disk = disks[i];
272 			rv = open_disk(u_flag);
273 			if(rv != -2) break;
274 		}
275 		if(rv < 0)
276 		{
277 			fprintf(stderr, "Cannot open any disk (%s)\n",
278 				sys_errlist[errno]);
279 			exit(1);
280 		}
281 	}
282 
283 	printf("******* Working on device %s *******\n",disk);
284 	if(u_flag)
285 	{
286 		get_params_to_use();
287 	}
288 	else
289 	{
290 		print_params();
291 	}
292 
293 	if (read_s0())
294 		init_sector0(1);
295 
296 	printf("Warning: BIOS sector numbering starts with sector 1\n");
297 	printf("Information from DOS bootblock is:\n");
298 	if (partition == -1)
299 		for (i = 0; i < NDOSPART; i++)
300 			change_part(i);
301 	else
302 		change_part(partition);
303 
304 	if (u_flag || a_flag)
305 		change_active(partition);
306 
307 	if (u_flag || a_flag) {
308 		printf("\nWe haven't changed the partition table yet.  ");
309 		printf("This is your last chance.\n");
310 		print_s0(-1);
311 		if (ok("Should we write new partition table?"))
312 			write_s0();
313 	}
314 
315 	exit(0);
316 
317 usage:
318 	printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n");
319 	return(1);
320 }
321 
322 static void
323 print_s0(int which)
324 {
325 int	i;
326 
327 	print_params();
328 	printf("Information from DOS bootblock is:\n");
329 	if (which == -1)
330 		for (i = 0; i < NDOSPART; i++)
331 			printf("%d: ", i), print_part(i);
332 	else
333 		print_part(which);
334 }
335 
336 static struct dos_partition mtpart = { 0 };
337 
338 static void
339 print_part(int i)
340 {
341 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
342 
343 
344 	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
345 		printf("<UNUSED>\n");
346 		return;
347 	}
348 	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
349 	printf("    start %ld, size %ld (%ld Meg), flag %x\n",
350 		partp->dp_start,
351 		partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
352 		partp->dp_flag);
353 	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
354 		,DPCYL(partp->dp_scyl, partp->dp_ssect)
355 		,DPSECT(partp->dp_ssect)
356 		,partp->dp_shd
357 		,DPCYL(partp->dp_ecyl, partp->dp_esect)
358 		,DPSECT(partp->dp_esect)
359 		,partp->dp_ehd);
360 }
361 
362 static void
363 init_sector0(unsigned long start)
364 {
365 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
366 unsigned long size = disksecs - start;
367 
368 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
369 	mboot.signature = BOOT_MAGIC;
370 
371 	partp->dp_typ = DOSPTYP_386BSD;
372 	partp->dp_flag = ACTIVE;
373 	partp->dp_start = start;
374 	partp->dp_size = size;
375 
376 	dos(partp->dp_start, partp->dp_size,
377 	    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
378 	dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
379 	    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
380 }
381 
382 static void
383 change_part(int i)
384 {
385 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
386 
387     printf("The data for partition %d is:\n", i);
388     print_part(i);
389 
390     if (u_flag && ok("Do you want to change it?")) {
391 	int tmp;
392 
393 	if (i_flag) {
394 		bzero((char *)partp, sizeof (struct dos_partition));
395 		if (i == 3) {
396 			init_sector0(1);
397 			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
398 			print_part(i);
399 		}
400 	}
401 
402 	do {
403 		Decimal("sysid", partp->dp_typ, tmp);
404 		Decimal("start", partp->dp_start, tmp);
405 		Decimal("size", partp->dp_size, tmp);
406 
407 		if (ok("Explicitly specifiy beg/end address ?"))
408 		{
409 			int	tsec,tcyl,thd;
410 			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
411 			thd = partp->dp_shd;
412 			tsec = DPSECT(partp->dp_ssect);
413 			Decimal("beginning cylinder", tcyl, tmp);
414 			Decimal("beginning head", thd, tmp);
415 			Decimal("beginning sector", tsec, tmp);
416 			partp->dp_scyl = DOSCYL(tcyl);
417 			partp->dp_ssect = DOSSECT(tsec,tcyl);
418 			partp->dp_shd = thd;
419 
420 			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
421 			thd = partp->dp_ehd;
422 			tsec = DPSECT(partp->dp_esect);
423 			Decimal("ending cylinder", tcyl, tmp);
424 			Decimal("ending head", thd, tmp);
425 			Decimal("ending sector", tsec, tmp);
426 			partp->dp_ecyl = DOSCYL(tcyl);
427 			partp->dp_esect = DOSSECT(tsec,tcyl);
428 			partp->dp_ehd = thd;
429 		} else {
430 			dos(partp->dp_start, partp->dp_size,
431 			    &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
432 			dos(partp->dp_start + partp->dp_size - 1, partp->dp_size,
433 			    &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
434 		}
435 
436 		print_part(i);
437 	} while (!ok("Are we happy with this entry?"));
438     }
439 }
440 
441 static void
442 print_params()
443 {
444 	printf("parameters extracted from in-core disklabel are:\n");
445 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
446 			,cyls,heads,sectors,cylsecs);
447 	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
448 		printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
449 	printf("parameters to be used for BIOS calculations are:\n");
450 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
451 		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
452 }
453 
454 static void
455 change_active(int which)
456 {
457 int i;
458 int active = 3, tmp;
459 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
460 
461 	if (a_flag && which != -1)
462 		active = which;
463 	if (!ok("Do you want to change the active partition?"))
464 		return;
465 	do
466 		Decimal("active partition", active, tmp);
467 	while (!ok("Are you happy with this choice"));
468 	for (i = 0; i < NDOSPART; i++)
469 		partp[i].dp_flag = 0;
470 	if (active >= 0 && active < NDOSPART)
471 		partp[active].dp_flag = ACTIVE;
472 }
473 
474 void
475 get_params_to_use()
476 {
477 	int	tmp;
478 	print_params();
479 	if (ok("Do you want to change our idea of what BIOS thinks ?"))
480 	{
481 		do
482 		{
483 			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
484 			Decimal("BIOS's idea of #heads", dos_heads, tmp);
485 			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
486 			dos_cylsecs = dos_heads * dos_sectors;
487 			print_params();
488 		}
489 		while(!ok("Are you happy with this choice"));
490 	}
491 }
492 
493 /***********************************************\
494 * Change real numbers into strange dos numbers	*
495 \***********************************************/
496 static void
497 dos(sec, size, c, s, h)
498 int sec, size;
499 unsigned char *c, *s, *h;
500 {
501 int cy;
502 int hd;
503 
504 	if (sec == 0 && size == 0) {
505 		*s = *c = *h = 0;
506 		return;
507 	}
508 
509 	cy = sec / ( dos_cylsecs );
510 	sec = sec - cy * ( dos_cylsecs );
511 
512 	hd = sec / dos_sectors;
513 	sec = (sec - hd * dos_sectors) + 1;
514 
515 	*h = hd;
516 	*c = cy & 0xff;
517 	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
518 }
519 
520 int fd;
521 
522 	/* Getting device status */
523 
524 static int
525 open_disk(int u_flag)
526 {
527 struct stat 	st;
528 
529 	if (stat(disk, &st) == -1) {
530 		fprintf(stderr, "%s: Can't get file status of %s\n",
531 			name, disk);
532 		return -1;
533 	}
534 	if ( !(st.st_mode & S_IFCHR) )
535 		fprintf(stderr,"%s: Device %s is not character special\n",
536 			name, disk);
537 	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
538 		if(errno == ENXIO)
539 			return -2;
540 		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
541 		return -1;
542 	}
543 	if (get_params(0) == -1) {
544 		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
545 			name, disk);
546 		return -1;
547 	}
548 	return fd;
549 }
550 
551 static ssize_t
552 read_disk(off_t sector, void *buf)
553 {
554 	lseek(fd,(sector * 512), 0);
555 	return read(fd, buf, 512);
556 }
557 
558 static ssize_t
559 write_disk(off_t sector, void *buf)
560 {
561 	lseek(fd,(sector * 512), 0);
562 	return write(fd, buf, 512);
563 }
564 
565 static int
566 get_params()
567 {
568 
569     if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
570 	fprintf(stderr,
571 		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
572 		name, disk);
573 	dos_cyls = cyls = 1;
574 	dos_heads = heads = 1;
575 	dos_sectors = sectors = 1;
576 	dos_cylsecs = cylsecs = heads * sectors;
577 	disksecs = cyls * heads * sectors;
578 	return disksecs;
579     }
580 
581     dos_cyls = cyls = disklabel.d_ncylinders;
582     dos_heads = heads = disklabel.d_ntracks;
583     dos_sectors = sectors = disklabel.d_nsectors;
584     dos_cylsecs = cylsecs = heads * sectors;
585     disksecs = cyls * heads * sectors;
586 
587     return (disksecs);
588 }
589 
590 
591 static int
592 read_s0()
593 {
594 	if (read_disk(0, (char *) mboot.bootinst) == -1) {
595 		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
596 		return -1;
597 	}
598 	if (mboot.signature != BOOT_MAGIC) {
599 		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
600 			name);
601 		/* So should we initialize things */
602 		return -1;
603 	}
604 	return 0;
605 }
606 
607 static int
608 write_s0()
609 {
610 	int	flag;
611 	if (iotest) {
612 		print_s0(-1);
613 		return 0;
614 	}
615 	/*
616 	 * write enable label sector before write (if necessary),
617 	 * disable after writing.
618 	 * needed if the disklabel protected area also protects
619 	 * sector 0. (e.g. empty disk)
620 	 */
621 	flag = 1;
622 #ifdef NOT_NOW
623 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
624 		perror("ioctl DIOCWLABEL");
625 #endif
626 	if (write_disk(0, (char *) mboot.bootinst) == -1) {
627 		fprintf(stderr, "%s: Can't write fdisk partition table\n",
628 			name);
629 		return -1;
630 	flag = 0;
631 #ifdef NOT_NOW
632 	(void) ioctl(fd, DIOCWLABEL, &flag);
633 #endif
634 	}
635 	return(0);
636 }
637 
638 
639 static int
640 ok(str)
641 char *str;
642 {
643 	printf("%s [n] ", str);
644 	fgets(lbuf, LBUF, stdin);
645 	lbuf[strlen(lbuf)-1] = 0;
646 
647 	if (*lbuf &&
648 		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
649 		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
650 		return 1;
651 	else
652 		return 0;
653 }
654 
655 static int
656 decimal(char *str, int *num, int deflt)
657 {
658 int acc = 0, c;
659 char *cp;
660 
661 	while (1) {
662 		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
663 		fgets(lbuf, LBUF, stdin);
664 		lbuf[strlen(lbuf)-1] = 0;
665 
666 		if (!*lbuf)
667 			return 0;
668 
669 		cp = lbuf;
670 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
671 		if (!c)
672 			return 0;
673 		while ((c = *cp++)) {
674 			if (c <= '9' && c >= '0')
675 				acc = acc * 10 + c - '0';
676 			else
677 				break;
678 		}
679 		if (c == ' ' || c == '\t')
680 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
681 		if (!c) {
682 			*num = acc;
683 			return 1;
684 		} else
685 			printf("%s is an invalid decimal number.  Try again\n",
686 				lbuf);
687 	}
688 
689 }
690 
691 #if 0
692 static int
693 hex(char *str, int *num, int deflt)
694 {
695 int acc = 0, c;
696 char *cp;
697 
698 	while (1) {
699 		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
700 		fgets(lbuf, LBUF, stdin);
701 		lbuf[strlen(lbuf)-1] = 0;
702 
703 		if (!*lbuf)
704 			return 0;
705 
706 		cp = lbuf;
707 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
708 		if (!c)
709 			return 0;
710 		while ((c = *cp++)) {
711 			if (c <= '9' && c >= '0')
712 				acc = (acc << 4) + c - '0';
713 			else if (c <= 'f' && c >= 'a')
714 				acc = (acc << 4) + c - 'a' + 10;
715 			else if (c <= 'F' && c >= 'A')
716 				acc = (acc << 4) + c - 'A' + 10;
717 			else
718 				break;
719 		}
720 		if (c == ' ' || c == '\t')
721 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
722 		if (!c) {
723 			*num = acc;
724 			return 1;
725 		} else
726 			printf("%s is an invalid hex number.  Try again\n",
727 				lbuf);
728 	}
729 
730 }
731 
732 static int
733 string(char *str, char **ans)
734 {
735 int c;
736 char *cp = lbuf;
737 
738 	while (1) {
739 		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
740 		fgets(lbuf, LBUF, stdin);
741 		lbuf[strlen(lbuf)-1] = 0;
742 
743 		if (!*lbuf)
744 			return 0;
745 
746 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
747 		if (c == '"') {
748 			c = *++cp;
749 			*ans = cp;
750 			while ((c = *cp) && c != '"') cp++;
751 		} else {
752 			*ans = cp;
753 			while ((c = *cp) && c != ' ' && c != '\t') cp++;
754 		}
755 
756 		if (c)
757 			*cp = 0;
758 		return 1;
759 	}
760 }
761 #endif
762 
763 static char *
764 get_type(int type)
765 {
766 	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
767 	int	counter = 0;
768 	struct	part_type *ptr = part_types;
769 
770 
771 	while(counter < numentries)
772 	{
773 		if(ptr->type == type)
774 		{
775 			return(ptr->name);
776 		}
777 		ptr++;
778 		counter++;
779 	}
780 	return("unknown");
781 }
782