xref: /freebsd/sbin/fdisk/fdisk.c (revision e627b39baccd1ec9129690167cf5e6d860509655)
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, unsigned char *c, unsigned char *s, unsigned char *h);
187 static int open_disk(int u_flag);
188 static ssize_t read_disk(off_t sector, void *buf);
189 static ssize_t write_disk(off_t sector, void *buf);
190 static int get_params();
191 static int read_s0();
192 static int write_s0();
193 static int ok(char *str);
194 static int decimal(char *str, int *num, int deflt);
195 static char *get_type(int type);
196 #if 0
197 static int hex(char *str, int *num, int deflt);
198 static int string(char *str, char **ans);
199 #endif
200 
201 
202 int
203 main(int argc, char *argv[])
204 {
205 	int	i;
206 
207 	name = *argv;
208 	{register char *cp = name;
209 		while (*cp) if (*cp++ == '/') name = cp;
210 	}
211 
212 	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
213 		if (*token++ != '-' || !*token)
214 			break;
215 		else { register int flag;
216 			for ( ; (flag = *token++) ; ) {
217 				switch (flag) {
218 				case '0':
219 					partition = 0;
220 					break;
221 				case '1':
222 					partition = 1;
223 					break;
224 				case '2':
225 					partition = 2;
226 					break;
227 				case '3':
228 					partition = 3;
229 					break;
230 				case 'a':
231 					a_flag = 1;
232 					break;
233 				case 'i':
234 					i_flag = 1;
235 				case 'u':
236 					u_flag = 1;
237 					break;
238 				default:
239 					goto usage;
240 				}
241 			}
242 		}
243 	}
244 
245 	if (argc > 0)
246 	{
247 		static char realname[12];
248 
249 		if(strncmp(argv[0], "/dev", 4) == 0)
250 			disk = argv[0];
251 		else
252 		{
253 			snprintf(realname, 12, "/dev/r%s", argv[0]);
254 			disk = realname;
255 		}
256 
257 		if (open_disk(u_flag) < 0)
258 		{
259 			fprintf(stderr, "Cannot open disk %s (%s)\n",
260 				disk, sys_errlist[errno]);
261 			exit(1);
262 		}
263 	}
264 	else
265 	{
266 		int i, rv = 0;
267 
268 		for(i = 0; disks[i]; i++)
269 		{
270 			disk = disks[i];
271 			rv = open_disk(u_flag);
272 			if(rv != -2) break;
273 		}
274 		if(rv < 0)
275 		{
276 			fprintf(stderr, "Cannot open any disk (%s)\n",
277 				sys_errlist[errno]);
278 			exit(1);
279 		}
280 	}
281 
282 	printf("******* Working on device %s *******\n",disk);
283 	if(u_flag)
284 	{
285 		get_params_to_use();
286 	}
287 	else
288 	{
289 		print_params();
290 	}
291 
292 	if (read_s0())
293 		init_sector0(1);
294 
295 	printf("Warning: BIOS sector numbering starts with sector 1\n");
296 	printf("Information from DOS bootblock is:\n");
297 	if (partition == -1)
298 		for (i = 0; i < NDOSPART; i++)
299 			change_part(i);
300 	else
301 		change_part(partition);
302 
303 	if (u_flag || a_flag)
304 		change_active(partition);
305 
306 	if (u_flag || a_flag) {
307 		printf("\nWe haven't changed the partition table yet.  ");
308 		printf("This is your last chance.\n");
309 		print_s0(-1);
310 		if (ok("Should we write new partition table?"))
311 			write_s0();
312 	}
313 
314 	exit(0);
315 
316 usage:
317 	printf("fdisk {-a|-i|-u} [-{0,1,2,3}] [disk]\n");
318 	return(1);
319 }
320 
321 static void
322 print_s0(int which)
323 {
324 int	i;
325 
326 	print_params();
327 	printf("Information from DOS bootblock is:\n");
328 	if (which == -1)
329 		for (i = 0; i < NDOSPART; i++)
330 			printf("%d: ", i), print_part(i);
331 	else
332 		print_part(which);
333 }
334 
335 static struct dos_partition mtpart = { 0 };
336 
337 static void
338 print_part(int i)
339 {
340 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
341 
342 
343 	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
344 		printf("<UNUSED>\n");
345 		return;
346 	}
347 	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
348 	printf("    start %ld, size %ld (%ld Meg), flag %x\n",
349 		partp->dp_start,
350 		partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
351 		partp->dp_flag);
352 	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
353 		,DPCYL(partp->dp_scyl, partp->dp_ssect)
354 		,DPSECT(partp->dp_ssect)
355 		,partp->dp_shd
356 		,DPCYL(partp->dp_ecyl, partp->dp_esect)
357 		,DPSECT(partp->dp_esect)
358 		,partp->dp_ehd);
359 }
360 
361 static void
362 init_sector0(unsigned long start)
363 {
364 struct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
365 unsigned long size = disksecs - start;
366 
367 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
368 	mboot.signature = BOOT_MAGIC;
369 
370 	partp->dp_typ = DOSPTYP_386BSD;
371 	partp->dp_flag = ACTIVE;
372 	partp->dp_start = start;
373 	partp->dp_size = size;
374 
375 	dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
376 	dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
377 }
378 
379 static void
380 change_part(int i)
381 {
382 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
383 
384     printf("The data for partition %d is:\n", i);
385     print_part(i);
386 
387     if (u_flag && ok("Do you want to change it?")) {
388 	int tmp;
389 
390 	if (i_flag) {
391 		bzero((char *)partp, sizeof (struct dos_partition));
392 		if (i == 3) {
393 			init_sector0(1);
394 			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
395 			print_part(i);
396 		}
397 	}
398 
399 	do {
400 		Decimal("sysid", partp->dp_typ, tmp);
401 		Decimal("start", partp->dp_start, tmp);
402 		Decimal("size", partp->dp_size, tmp);
403 
404 		if (ok("Explicitly specifiy beg/end address ?"))
405 		{
406 			int	tsec,tcyl,thd;
407 			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
408 			thd = partp->dp_shd;
409 			tsec = DPSECT(partp->dp_ssect);
410 			Decimal("beginning cylinder", tcyl, tmp);
411 			Decimal("beginning head", thd, tmp);
412 			Decimal("beginning sector", tsec, tmp);
413 			partp->dp_scyl = DOSCYL(tcyl);
414 			partp->dp_ssect = DOSSECT(tsec,tcyl);
415 			partp->dp_shd = thd;
416 
417 			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
418 			thd = partp->dp_ehd;
419 			tsec = DPSECT(partp->dp_esect);
420 			Decimal("ending cylinder", tcyl, tmp);
421 			Decimal("ending head", thd, tmp);
422 			Decimal("ending sector", tsec, tmp);
423 			partp->dp_ecyl = DOSCYL(tcyl);
424 			partp->dp_esect = DOSSECT(tsec,tcyl);
425 			partp->dp_ehd = thd;
426 		} else {
427 			dos(partp->dp_start,
428 				&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
429 			dos(partp->dp_start+partp->dp_size - 1,
430 				&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
431 		}
432 
433 		print_part(i);
434 	} while (!ok("Are we happy with this entry?"));
435     }
436 }
437 
438 static void
439 print_params()
440 {
441 	printf("parameters extracted from in-core disklabel are:\n");
442 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
443 			,cyls,heads,sectors,cylsecs);
444 	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
445 		printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
446 	printf("parameters to be used for BIOS calculations are:\n");
447 	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
448 		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
449 }
450 
451 static void
452 change_active(int which)
453 {
454 int i;
455 int active = 3, tmp;
456 struct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
457 
458 	if (a_flag && which != -1)
459 		active = which;
460 	if (!ok("Do you want to change the active partition?"))
461 		return;
462 	do
463 		Decimal("active partition", active, tmp);
464 	while (!ok("Are you happy with this choice"));
465 	for (i = 0; i < NDOSPART; i++)
466 		partp[i].dp_flag = 0;
467 	if (active >= 0 && active < NDOSPART)
468 		partp[active].dp_flag = ACTIVE;
469 }
470 
471 void
472 get_params_to_use()
473 {
474 	int	tmp;
475 	print_params();
476 	if (ok("Do you want to change our idea of what BIOS thinks ?"))
477 	{
478 		do
479 		{
480 			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
481 			Decimal("BIOS's idea of #heads", dos_heads, tmp);
482 			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
483 			dos_cylsecs = dos_heads * dos_sectors;
484 			print_params();
485 		}
486 		while(!ok("Are you happy with this choice"));
487 	}
488 }
489 
490 /***********************************************\
491 * Change real numbers into strange dos numbers	*
492 \***********************************************/
493 static void
494 dos(sec, c, s, h)
495 int sec;
496 unsigned char *c, *s, *h;
497 {
498 int cy;
499 int hd;
500 
501 	if (sec == 0) {
502 		*s = *c = *h = 0;
503 		return;
504 	}
505 
506 	cy = sec / ( dos_cylsecs );
507 	sec = sec - cy * ( dos_cylsecs );
508 
509 	hd = sec / dos_sectors;
510 	sec = (sec - hd * dos_sectors) + 1;
511 
512 	*h = hd;
513 	*c = cy & 0xff;
514 	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
515 }
516 
517 int fd;
518 
519 	/* Getting device status */
520 
521 static int
522 open_disk(int u_flag)
523 {
524 struct stat 	st;
525 
526 	if (stat(disk, &st) == -1) {
527 		fprintf(stderr, "%s: Can't get file status of %s\n",
528 			name, disk);
529 		return -1;
530 	}
531 	if ( !(st.st_mode & S_IFCHR) )
532 		fprintf(stderr,"%s: Device %s is not character special\n",
533 			name, disk);
534 	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
535 		if(errno == ENXIO)
536 			return -2;
537 		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
538 		return -1;
539 	}
540 	if (get_params(0) == -1) {
541 		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
542 			name, disk);
543 		return -1;
544 	}
545 	return fd;
546 }
547 
548 static ssize_t
549 read_disk(off_t sector, void *buf)
550 {
551 	lseek(fd,(sector * 512), 0);
552 	return read(fd, buf, 512);
553 }
554 
555 static ssize_t
556 write_disk(off_t sector, void *buf)
557 {
558 	lseek(fd,(sector * 512), 0);
559 	return write(fd, buf, 512);
560 }
561 
562 static int
563 get_params()
564 {
565 
566     if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
567 	fprintf(stderr,
568 		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
569 		name, disk);
570 	dos_cyls = cyls = 1;
571 	dos_heads = heads = 1;
572 	dos_sectors = sectors = 1;
573 	dos_cylsecs = cylsecs = heads * sectors;
574 	disksecs = cyls * heads * sectors;
575 	return disksecs;
576     }
577 
578     dos_cyls = cyls = disklabel.d_ncylinders;
579     dos_heads = heads = disklabel.d_ntracks;
580     dos_sectors = sectors = disklabel.d_nsectors;
581     dos_cylsecs = cylsecs = heads * sectors;
582     disksecs = cyls * heads * sectors;
583 
584     return (disksecs);
585 }
586 
587 
588 static int
589 read_s0()
590 {
591 	if (read_disk(0, (char *) mboot.bootinst) == -1) {
592 		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
593 		return -1;
594 	}
595 	if (mboot.signature != BOOT_MAGIC) {
596 		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
597 			name);
598 		/* So should we initialize things */
599 		return -1;
600 	}
601 	return 0;
602 }
603 
604 static int
605 write_s0()
606 {
607 	int	flag;
608 	if (iotest) {
609 		print_s0(-1);
610 		return 0;
611 	}
612 	/*
613 	 * write enable label sector before write (if necessary),
614 	 * disable after writing.
615 	 * needed if the disklabel protected area also protects
616 	 * sector 0. (e.g. empty disk)
617 	 */
618 	flag = 1;
619 #ifdef NOT_NOW
620 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
621 		perror("ioctl DIOCWLABEL");
622 #endif
623 	if (write_disk(0, (char *) mboot.bootinst) == -1) {
624 		fprintf(stderr, "%s: Can't write fdisk partition table\n",
625 			name);
626 		return -1;
627 	flag = 0;
628 #ifdef NOT_NOW
629 	(void) ioctl(fd, DIOCWLABEL, &flag);
630 #endif
631 	}
632 	return(0);
633 }
634 
635 
636 static int
637 ok(str)
638 char *str;
639 {
640 	printf("%s [n] ", str);
641 	fgets(lbuf, LBUF, stdin);
642 	lbuf[strlen(lbuf)-1] = 0;
643 
644 	if (*lbuf &&
645 		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
646 		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
647 		return 1;
648 	else
649 		return 0;
650 }
651 
652 static int
653 decimal(char *str, int *num, int deflt)
654 {
655 int acc = 0, c;
656 char *cp;
657 
658 	while (1) {
659 		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
660 		fgets(lbuf, LBUF, stdin);
661 		lbuf[strlen(lbuf)-1] = 0;
662 
663 		if (!*lbuf)
664 			return 0;
665 
666 		cp = lbuf;
667 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
668 		if (!c)
669 			return 0;
670 		while ((c = *cp++)) {
671 			if (c <= '9' && c >= '0')
672 				acc = acc * 10 + c - '0';
673 			else
674 				break;
675 		}
676 		if (c == ' ' || c == '\t')
677 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
678 		if (!c) {
679 			*num = acc;
680 			return 1;
681 		} else
682 			printf("%s is an invalid decimal number.  Try again\n",
683 				lbuf);
684 	}
685 
686 }
687 
688 #if 0
689 static int
690 hex(char *str, int *num, int deflt)
691 {
692 int acc = 0, c;
693 char *cp;
694 
695 	while (1) {
696 		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
697 		fgets(lbuf, LBUF, stdin);
698 		lbuf[strlen(lbuf)-1] = 0;
699 
700 		if (!*lbuf)
701 			return 0;
702 
703 		cp = lbuf;
704 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
705 		if (!c)
706 			return 0;
707 		while ((c = *cp++)) {
708 			if (c <= '9' && c >= '0')
709 				acc = (acc << 4) + c - '0';
710 			else if (c <= 'f' && c >= 'a')
711 				acc = (acc << 4) + c - 'a' + 10;
712 			else if (c <= 'F' && c >= 'A')
713 				acc = (acc << 4) + c - 'A' + 10;
714 			else
715 				break;
716 		}
717 		if (c == ' ' || c == '\t')
718 			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
719 		if (!c) {
720 			*num = acc;
721 			return 1;
722 		} else
723 			printf("%s is an invalid hex number.  Try again\n",
724 				lbuf);
725 	}
726 
727 }
728 
729 static int
730 string(char *str, char **ans)
731 {
732 int c;
733 char *cp = lbuf;
734 
735 	while (1) {
736 		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
737 		fgets(lbuf, LBUF, stdin);
738 		lbuf[strlen(lbuf)-1] = 0;
739 
740 		if (!*lbuf)
741 			return 0;
742 
743 		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
744 		if (c == '"') {
745 			c = *++cp;
746 			*ans = cp;
747 			while ((c = *cp) && c != '"') cp++;
748 		} else {
749 			*ans = cp;
750 			while ((c = *cp) && c != ' ' && c != '\t') cp++;
751 		}
752 
753 		if (c)
754 			*cp = 0;
755 		return 1;
756 	}
757 }
758 #endif
759 
760 static char *
761 get_type(int type)
762 {
763 	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
764 	int	counter = 0;
765 	struct	part_type *ptr = part_types;
766 
767 
768 	while(counter < numentries)
769 	{
770 		if(ptr->type == type)
771 		{
772 			return(ptr->name);
773 		}
774 		ptr++;
775 		counter++;
776 	}
777 	return("unknown");
778 }
779