fdisk.c revision 5576
118334Speter/*
290075Sobrien * Mach Operating System
3132718Skan * Copyright (c) 1992 Carnegie Mellon University
418334Speter * All Rights Reserved.
590075Sobrien *
618334Speter * Permission to use, copy, modify and distribute this software and its
790075Sobrien * documentation is hereby granted, provided that both the copyright
890075Sobrien * notice and this permission notice appear in all copies of the
990075Sobrien * software, derivative works or modified versions, and any portions
1090075Sobrien * thereof, and that both notices appear in supporting documentation.
1118334Speter *
1290075Sobrien * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
1390075Sobrien * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
1490075Sobrien * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
1590075Sobrien *
1618334Speter * Carnegie Mellon requests users of this software to return to
1718334Speter *
1890075Sobrien *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
1990075Sobrien *  School of Computer Science
2090075Sobrien *  Carnegie Mellon University
2118334Speter *  Pittsburgh PA 15213-3890
2218334Speter *
2318334Speter * any improvements or extensions that they make and grant Carnegie Mellon
2418334Speter * the rights to redistribute these changes.
2518334Speter */
2618334Speter
2718334Speter#include <sys/types.h>
2818334Speter#include <sys/disklabel.h>
2918334Speter#include <stdio.h>
3018334Speter#include <sys/stat.h>
3118334Speter#include <sys/ioctl.h>
3218334Speter#include <fcntl.h>
3350397Sobrien
34132718Skanint iotest;
35132718Skan
3690075Sobrien#define LBUF 100
3718334Speterstatic char lbuf[LBUF];
3818334Speter
3990075Sobrien/*
4018334Speter *
4118334Speter * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
4250397Sobrien *
4350397Sobrien * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
4452284Sobrien *	Copyright (c) 1989	Robert. V. Baron
4590075Sobrien *	Created.
4690075Sobrien */
4718334Speter
4818334Speter#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
4918334Speter#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
5018334Speter#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
5118334Speter
52132718Skan#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
53132718Skan
5490075Sobrien#define SECSIZE 512
55132718Skan
56132718Skanchar *disk = "/dev/rwd0d";
57132718Skanchar *name;
58132718Skan
59132718Skanstruct disklabel disklabel;		/* disk parameters */
60132718Skan
61132718Skanint cyls, sectors, heads, cylsecs, disksecs;
62132718Skan
63132718Skanstruct mboot
64132718Skan{
65132718Skan	unsigned char padding[2]; /* force the longs to be long alligned */
66132718Skan	unsigned char bootinst[DOSPARTOFF];
67132718Skan	struct	dos_partition parts[4];
68132718Skan	unsigned short int	signature;
69132718Skan};
70132718Skanstruct mboot mboot;
71132718Skan
72132718Skan#define ACTIVE 0x80
73132718Skan#define BOOT_MAGIC 0xAA55
74132718Skan
75132718Skanint dos_cyls;
76132718Skanint dos_heads;
77132718Skanint dos_sectors;
78132718Skanint dos_cylsecs;
79132718Skan
80132718Skan#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
81132718Skan#define DOSCYL(c)	(c & 0xff)
82132718Skanstatic int dos();
83132718Skanchar *get_type();
84132718Skanstatic int partition = -1;
85132718Skan
86132718Skan
87132718Skanstatic int a_flag  = 0;		/* set active partition */
8818334Speterstatic int i_flag  = 0;		/* replace partition data */
8918334Speterstatic int u_flag  = 0;		/* update partition data */
9018334Speter
9118334Speterstatic unsigned char bootcode[] = {
9218334Speter0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
93132718Skan0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
9418334Speter0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
9518334Speter0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
9618334Speter0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
9790075Sobrien0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
9852284Sobrien0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
9952284Sobrien0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
10018334Speter0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
10190075Sobrien'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
10218334Speter	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
10318334Speter'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
104117395Skan	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
10518334Speter'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
10618334Speter	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
10718334Speter'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
10818334Speter	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
10918334Speter
11018334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11118334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11218334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
113132718Skan  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11418334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11552284Sobrien  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11618334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11718334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11818334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
11918334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
12018334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
12118334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
12218334Speter  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
12318334Speter};
12418334Speter
12518334Speterstruct part_type
12618334Speter{
12718334Speter unsigned char type;
12818334Speter char *name;
12918334Speter}part_types[] =
13018334Speter{
13118334Speter	 {0x00, "unused"}
13218334Speter	,{0x01, "Primary DOS with 12 bit FAT"}
13352284Sobrien	,{0x02, "XENIX / filesystem"}
13418334Speter	,{0x03, "XENIX /usr filesystem"}
13518334Speter	,{0x04, "Primary DOS with 16 bit FAT"}
13618334Speter	,{0x05, "Extended DOS"}
13752284Sobrien	,{0x06, "Primary 'big' DOS (> 32MB)"}
13818334Speter	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}
13918334Speter	,{0x08, "AIX filesystem"}
14018334Speter	,{0x09, "AIX boot partition or Coherent"}
14152284Sobrien	,{0x0A, "OS/2 Boot Manager or OPUS"}
14218334Speter	,{0x10, "OPUS"}
14318334Speter	,{0x40, "VENIX 286"}
14418334Speter	,{0x50, "DM"}
14518334Speter	,{0x51, "DM"}
14618334Speter	,{0x52, "CP/M or Microport SysV/AT"}
14718334Speter	,{0x56, "GB"}
14818334Speter	,{0x61, "Speed"}
14918334Speter	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}
15018334Speter	,{0x64, "Novell Netware 2.xx"}
15196263Sobrien	,{0x65, "Novell Netware 3.xx"}
15296263Sobrien	,{0x75, "PCIX"}
15396263Sobrien	,{0x80, "Minix 1.1 ... 1.4a"}
15496263Sobrien	,{0x81, "Minix 1.4b ... 1.5.10"}
15596263Sobrien	,{0x82, "Linux swap"}
15618334Speter	,{0x83, "Linux filesystem"}
15718334Speter	,{0x93, "Amoeba filesystem"}
15818334Speter	,{0x94, "Amoeba bad block table"}
15918334Speter	,{0xA5, "FreeBSD/NetBSD/386BSD"}
16018334Speter	,{0xB7, "BSDI BSD/386 filesystem"}
16118334Speter	,{0xB8, "BSDI BSD/386 swap"}
16218334Speter	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}
16318334Speter	,{0xE1, "Speed"}
16418334Speter	,{0xE3, "Speed"}
16518334Speter	,{0xE4, "Speed"}
16618334Speter	,{0xF1, "Speed"}
16752284Sobrien	,{0xF2, "DOS 3.3+ Secondary"}
16852284Sobrien	,{0xF4, "Speed"}
16918334Speter	,{0xFF, "BBT (Bad Blocks Table)"}
17018334Speter};
17118334Speter
17218334Speter
17318334Spetermain(argc, argv)
17418334Speterchar **argv;
17518334Speter{
176117395Skanint	i;
177117395Skan
178117395Skan	name = *argv;
179117395Skan	{register char *cp = name;
180132718Skan		while (*cp) if (*cp++ == '/') name = cp;
181117395Skan	}
182117395Skan
183117395Skan	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
184117395Skan		if (*token++ != '-' || !*token)
185117395Skan			break;
186117395Skan		else { register int flag;
187117395Skan			for ( ; flag = *token++ ; ) {
188117395Skan				switch (flag) {
189117395Skan				case '0':
190117395Skan					partition = 0;
191117395Skan					break;
192117395Skan				case '1':
193117395Skan					partition = 1;
194117395Skan					break;
195117395Skan				case '2':
196117395Skan					partition = 2;
19718334Speter					break;
19818334Speter				case '3':
19918334Speter					partition = 3;
20018334Speter					break;
201132718Skan				case 'a':
20218334Speter					a_flag = 1;
203132718Skan					break;
20452750Sobrien				case 'i':
20518334Speter					i_flag = 1;
20618334Speter				case 'u':
20718334Speter					u_flag = 1;
20818334Speter					break;
20918334Speter				default:
21018334Speter					goto usage;
21118334Speter				}
21218334Speter			}
21318334Speter		}
21418334Speter	}
21518334Speter
216132718Skan	if (argc > 0)
21718334Speter		disk = argv[0];
21890075Sobrien
21990075Sobrien	if (open_disk(u_flag) < 0)
22018334Speter		exit(1);
22118334Speter
22218334Speter	printf("******* Working on device %s *******\n",disk);
22318334Speter	if(u_flag)
22418334Speter	{
22518334Speter		get_params_to_use();
22618334Speter	}
22718334Speter	else
22818334Speter	{
22918334Speter		print_params();
23018334Speter	}
23118334Speter
23250397Sobrien	if (read_s0())
23390075Sobrien		init_sector0(1);
23418334Speter
23518334Speter	printf("Warning: BIOS sector numbering starts with sector 1\n");
23618334Speter	printf("Information from DOS bootblock is:\n");
23718334Speter	if (partition == -1)
238117395Skan		for (i = 0; i < NDOSPART; i++)
23918334Speter			change_part(i);
240117395Skan	else
24118334Speter		change_part(partition);
24218334Speter
24318334Speter	if (u_flag || a_flag)
24418334Speter		change_active(partition);
24518334Speter
24618334Speter	if (u_flag || a_flag) {
24718334Speter		printf("\nWe haven't changed the partition table yet.  ");
24818334Speter		printf("This is your last chance.\n");
24918334Speter		print_s0(-1);
25018334Speter		if (ok("Should we write new partition table?"))
25118334Speter			write_s0();
25218334Speter	}
25318334Speter
25418334Speter	exit(0);
25518334Speter
25618334Speterusage:
25718334Speter	printf("fdisk {-a|-i|-r} {disk}\n");
25818334Speter}
25918334Speter
26018334Speterprint_s0(which)
26118334Speter{
26218334Speterint	i;
26318334Speter
26418334Speter	print_params();
26518334Speter	printf("Information from DOS bootblock is:\n");
26618334Speter	if (which == -1)
26718334Speter		for (i = 0; i < NDOSPART; i++)
26818334Speter			printf("%d: ", i), print_part(i);
26918334Speter	else
27018334Speter		print_part(which);
27118334Speter}
27218334Speter
27318334Speterstatic struct dos_partition mtpart = { 0 };
27418334Speter
27518334Speterprint_part(i)
27618334Speter{
27718334Speterstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
27818334Speter
27918334Speter
28018334Speter	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
28118334Speter		printf("<UNUSED>\n");
28218334Speter		return;
28318334Speter	}
28418334Speter	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
28518334Speter	printf("    start %d, size %d (%d Meg), flag %x\n",
286132718Skan		partp->dp_start,
287132718Skan		partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
288132718Skan		partp->dp_flag);
289132718Skan	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
290132718Skan		,DPCYL(partp->dp_scyl, partp->dp_ssect)
29118334Speter		,DPSECT(partp->dp_ssect)
29218334Speter		,partp->dp_shd
29318334Speter		,DPCYL(partp->dp_ecyl, partp->dp_esect)
29418334Speter		,DPSECT(partp->dp_esect)
295132718Skan		,partp->dp_ehd);
296132718Skan}
29718334Speter
29818334Speterinit_sector0(start)
29918334Speter{
300132718Skanstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
30118334Speterint size = disksecs - start;
302132718Skanint rest;
303132718Skan
304132718Skan	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
305132718Skan	mboot.signature = BOOT_MAGIC;
30618334Speter
30718334Speter	partp->dp_typ = DOSPTYP_386BSD;
30850397Sobrien	partp->dp_flag = ACTIVE;
30950397Sobrien	partp->dp_start = start;
31050397Sobrien	partp->dp_size = size;
311132718Skan
312132718Skan	dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
313132718Skan	dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
314132718Skan}
315132718Skan
31650397Sobrienchange_part(i)
31718334Speter{
31818334Speterstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
31918334Speter
32018334Speter    printf("The data for partition %d is:\n", i);
32118334Speter    print_part(i);
32218334Speter
32318334Speter    if (u_flag && ok("Do you want to change it?")) {
32418334Speter	int tmp;
32518334Speter
32618334Speter	if (i_flag) {
32718334Speter		bzero((char *)partp, sizeof (struct dos_partition));
32818334Speter		if (i == 3) {
32918334Speter			init_sector0(1);
33018334Speter			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
33152284Sobrien			print_part(i);
33252284Sobrien		}
33352284Sobrien	}
33452284Sobrien
335132718Skan	do {
336132718Skan		Decimal("sysid", partp->dp_typ, tmp);
337132718Skan		Decimal("start", partp->dp_start, tmp);
33852284Sobrien		Decimal("size", partp->dp_size, tmp);
33918334Speter
34018334Speter		if (ok("Explicitly specifiy beg/end address ?"))
34118334Speter		{
34218334Speter			int	tsec,tcyl,thd;
34318334Speter			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
34418334Speter			thd = partp->dp_shd;
34518334Speter			tsec = DPSECT(partp->dp_ssect);
34618334Speter			Decimal("beginning cylinder", tcyl, tmp);
34718334Speter			Decimal("beginning head", thd, tmp);
34818334Speter			Decimal("beginning sector", tsec, tmp);
34918334Speter			partp->dp_scyl = DOSCYL(tcyl);
35018334Speter			partp->dp_ssect = DOSSECT(tsec,tcyl);
35118334Speter			partp->dp_shd = thd;
35218334Speter
35318334Speter			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
35418334Speter			thd = partp->dp_ehd;
35518334Speter			tsec = DPSECT(partp->dp_esect);
35618334Speter			Decimal("ending cylinder", tcyl, tmp);
35718334Speter			Decimal("ending head", thd, tmp);
35818334Speter			Decimal("ending sector", tsec, tmp);
35918334Speter			partp->dp_ecyl = DOSCYL(tcyl);
36018334Speter			partp->dp_esect = DOSSECT(tsec,tcyl);
36118334Speter			partp->dp_ehd = thd;
36218334Speter		} else {
36318334Speter			dos(partp->dp_start,
36418334Speter				&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
36518334Speter			dos(partp->dp_start+partp->dp_size - 1,
36618334Speter				&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
36718334Speter		}
36818334Speter
36918334Speter		print_part(i);
37018334Speter	} while (!ok("Are we happy with this entry?"));
37118334Speter    }
37218334Speter}
37318334Speter
37418334Speterprint_params()
37518334Speter{
37618334Speter	printf("parameters extracted from in-core disklabel are:\n");
37718334Speter	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
37818334Speter			,cyls,heads,sectors,cylsecs);
37918334Speter	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
38018334Speter		printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
38118334Speter	printf("parameters to be used for BIOS calculations are:\n");
38218334Speter	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
38318334Speter		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
38418334Speter}
38518334Speter
38618334Speterchange_active(which)
38790075Sobrien{
388132718Skanint i;
38990075Sobrienint active = 3, tmp;
39018334Speterstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
39118334Speter
39218334Speter	if (a_flag && which != -1)
39318334Speter		active = which;
39418334Speter	if (!ok("Do you want to change the active partition?"))
39518334Speter		return;
39618334Speter	do
39718334Speter		Decimal("active partition", active, tmp);
39818334Speter	while (!ok("Are you happy with this choice"));
39918334Speter	for (i = 0; i < NDOSPART; i++)
40018334Speter		partp[i].dp_flag = 0;
40118334Speter	if (active >= 0 && active < NDOSPART)
40218334Speter		partp[active].dp_flag = ACTIVE;
40318334Speter}
40418334Speter
40518334Speterget_params_to_use()
40618334Speter{
40718334Speter	int	tmp;
40818334Speter	print_params();
40918334Speter	if (ok("Do you want to change our idea of what BIOS thinks ?"))
41018334Speter	{
41118334Speter		do
41218334Speter		{
413132718Skan			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
41418334Speter			Decimal("BIOS's idea of #heads", dos_heads, tmp);
41518334Speter			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
41618334Speter			dos_cylsecs = dos_heads * dos_sectors;
41718334Speter			print_params();
41818334Speter		}
41918334Speter		while(!ok("Are you happy with this choice"));
42018334Speter	}
42118334Speter}
42218334Speter
423132718Skan/***********************************************\
424132718Skan* Change real numbers into strange dos numbers	*
42518334Speter\***********************************************/
42618334Speterstatic
42718334Speterdos(sec, c, s, h)
42890075Sobrienint sec;
42918334Speterunsigned char *c, *s, *h;
43018334Speter{
43118334Speterint cy;
43218334Speterint hd;
43318334Speter
43418334Speter	if (sec == 0) {
43518334Speter		*s = *c = *h = 0;
43618334Speter		return;
43718334Speter	}
438132718Skan
439132718Skan	cy = sec / ( dos_cylsecs );
44018334Speter	sec = sec - cy * ( dos_cylsecs );
44118334Speter
44218334Speter	hd = sec / dos_sectors;
44390075Sobrien	sec = (sec - hd * dos_sectors) + 1;
44418334Speter
44518334Speter	*h = hd;
44618334Speter	*c = cy & 0xff;
44718334Speter	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
44818334Speter}
44918334Speter
45018334Speterint fd;
45190075Sobrien
45290075Sobrien	/* Getting device status */
45318334Speter
45450397Sobrienopen_disk(u_flag)
45518334Speter{
45618334Speterstruct stat 	st;
45718334Speter
45818334Speter	if (stat(disk, &st) == -1) {
45918334Speter		fprintf(stderr, "%s: Can't get file status of %s\n",
46018334Speter			name, disk);
46118334Speter		return -1;
46218334Speter	}
46318334Speter	if ( !(st.st_mode & S_IFCHR) )
46418334Speter		fprintf(stderr,"%s: Device %s is not character special\n",
46518334Speter			name, disk);
46618334Speter	if ((fd = open(disk, a_flag || u_flag ? O_RDWR : O_RDONLY)) == -1) {
46718334Speter		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
468132718Skan		return -1;
46918334Speter	}
47090075Sobrien	if (get_params(0) == -1) {
47190075Sobrien		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
47218334Speter			name, disk);
47318334Speter		return -1;
47418334Speter	}
47518334Speter	return fd;
47650397Sobrien}
47750397Sobrien
47818334Speter
47918334Speterread_disk(sector, buf)
48090075Sobrien{
48190075Sobrien	lseek(fd,(sector * 512), 0);
48290075Sobrien	return read(fd, buf, 512);
48390075Sobrien}
48490075Sobrien
48590075Sobrienwrite_disk(sector, buf)
48690075Sobrien{
48790075Sobrien	lseek(fd,(sector * 512), 0);
48890075Sobrien	return write(fd, buf, 512);
48990075Sobrien}
490132718Skan
491132718Skanget_params(verbose)
492132718Skan{
49318334Speter
494132718Skan    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
495117395Skan	fprintf(stderr,
496132718Skan		"%s: Can't get disk parameters on %s; supplying dummy ones\n",
497117395Skan		name, disk);
49818334Speter	dos_cyls = cyls = 1;
49918334Speter	dos_heads = heads = 1;
50018334Speter	dos_sectors = sectors = 1;
50118334Speter	dos_cylsecs = cylsecs = heads * sectors;
50218334Speter	disksecs = cyls * heads * sectors;
50318334Speter	return disksecs;
504132718Skan    }
505132718Skan
50618334Speter    dos_cyls = cyls = disklabel.d_ncylinders;
50718334Speter    dos_heads = heads = disklabel.d_ntracks;
50818334Speter    dos_sectors = sectors = disklabel.d_nsectors;
50952284Sobrien    dos_cylsecs = cylsecs = heads * sectors;
51018334Speter    disksecs = cyls * heads * sectors;
51118334Speter
51218334Speter    return (disksecs);
51318334Speter}
51450397Sobrien
51518334Speter
51618334Speterread_s0()
51718334Speter{
51818334Speter	if (read_disk(0, (char *) mboot.bootinst) == -1) {
51918334Speter		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
52090075Sobrien		return -1;
52118334Speter	}
52218334Speter	if (mboot.signature != BOOT_MAGIC) {
52318334Speter		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
52418334Speter			name);
52518334Speter		/* So should we initialize things */
52618334Speter		return -1;
52718334Speter	}
52818334Speter	return 0;
529132718Skan}
530132718Skan
531132718Skanwrite_s0()
532132718Skan{
53318334Speter	int	flag;
534132718Skan	if (iotest) {
53518334Speter		print_s0(-1);
53618334Speter		return 0;
53718334Speter	}
538132718Skan	/*
53918334Speter	 * write enable label sector before write (if necessary),
54018334Speter	 * disable after writing.
54118334Speter	 * needed if the disklabel protected area also protects
54218334Speter	 * sector 0. (e.g. empty disk)
54318334Speter	 */
54418334Speter	flag = 1;
54590075Sobrien	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
54690075Sobrien		perror("ioctl DIOCWLABEL");
54718334Speter	if (write_disk(0, (char *) mboot.bootinst) == -1) {
54818334Speter		fprintf(stderr, "%s: Can't write fdisk partition table\n",
54918334Speter			name);
55018334Speter		return -1;
551132718Skan	flag = 0;
552132718Skan	(void) ioctl(fd, DIOCWLABEL, &flag);
55318334Speter	}
55418334Speter}
55518334Speter
55690075Sobrien
55718334Speter
55818334Speterok(str)
55990075Sobrienchar *str;
56090075Sobrien{
56190075Sobrien	printf("%s [n] ", str);
56290075Sobrien	fgets(lbuf, LBUF, stdin);
56390075Sobrien	lbuf[strlen(lbuf)-1] = 0;
56490075Sobrien
56590075Sobrien	if (*lbuf &&
56690075Sobrien		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
56790075Sobrien		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
56890075Sobrien		return 1;
56990075Sobrien	else
57090075Sobrien		return 0;
57190075Sobrien}
57290075Sobrien
57390075Sobriendecimal(str, num, deflt)
57490075Sobrienchar *str;
57590075Sobrienint *num;
57690075Sobrien{
57790075Sobrienint acc = 0, c;
57818334Speterchar *cp;
57918334Speter
58018334Speter	while (1) {
58118334Speter		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
582132718Skan		fgets(lbuf, LBUF, stdin);
583132718Skan		lbuf[strlen(lbuf)-1] = 0;
584132718Skan
58518334Speter		if (!*lbuf)
586132718Skan			return 0;
587132718Skan
588132718Skan		cp = lbuf;
589132718Skan		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
590132718Skan		if (!c)
59118334Speter			return 0;
59250397Sobrien		while (c = *cp++) {
593132718Skan			if (c <= '9' && c >= '0')
594132718Skan				acc = acc * 10 + c - '0';
595132718Skan			else
596132718Skan				break;
597132718Skan		}
598132718Skan		if (c == ' ' || c == '\t')
59950397Sobrien			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
60050397Sobrien		if (!c) {
60118334Speter			*num = acc;
60218334Speter			return 1;
60318334Speter		} else
60418334Speter			printf("%s is an invalid decimal number.  Try again\n",
60518334Speter				lbuf);
606117395Skan	}
607117395Skan
608117395Skan}
609117395Skan
610117395Skanhex(str, num, deflt)
61118334Speterchar *str;
61218334Speterint *num;
613132718Skan{
61418334Speterint acc = 0, c;
61518334Speterchar *cp;
61618334Speter
617117395Skan	while (1) {
618117395Skan		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
61918334Speter		fgets(lbuf, LBUF, stdin);
62018334Speter		lbuf[strlen(lbuf)-1] = 0;
62118334Speter
622132718Skan		if (!*lbuf)
62318334Speter			return 0;
62418334Speter
62518334Speter		cp = lbuf;
62618334Speter		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
62718334Speter		if (!c)
62818334Speter			return 0;
62918334Speter		while (c = *cp++) {
63018334Speter			if (c <= '9' && c >= '0')
631132718Skan				acc = (acc << 4) + c - '0';
632132718Skan			else if (c <= 'f' && c >= 'a')
633132718Skan				acc = (acc << 4) + c - 'a' + 10;
634132718Skan			else if (c <= 'F' && c >= 'A')
635132718Skan				acc = (acc << 4) + c - 'A' + 10;
636132718Skan			else
637132718Skan				break;
638132718Skan		}
639132718Skan		if (c == ' ' || c == '\t')
640132718Skan			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
641132718Skan		if (!c) {
642132718Skan			*num = acc;
643132718Skan			return 1;
644132718Skan		} else
645132718Skan			printf("%s is an invalid hex number.  Try again\n",
646132718Skan				lbuf);
647132718Skan	}
648132718Skan
649132718Skan}
650146895Skan
651132718Skanstring(str, ans)
652132718Skanchar *str;
653132718Skanchar **ans;
654132718Skan{
655132718Skanint c;
656132718Skanchar *cp = lbuf;
657132718Skan
658132718Skan	while (1) {
659132718Skan		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
660132718Skan		fgets(lbuf, LBUF, stdin);
661132718Skan		lbuf[strlen(lbuf)-1] = 0;
662132718Skan
663132718Skan		if (!*lbuf)
664132718Skan			return 0;
665132718Skan
666132718Skan		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
667132718Skan		if (c == '"') {
668132718Skan			c = *++cp;
669132718Skan			*ans = cp;
670132718Skan			while ((c = *cp) && c != '"') cp++;
671132718Skan		} else {
672132718Skan			*ans = cp;
673132718Skan			while ((c = *cp) && c != ' ' && c != '\t') cp++;
674132718Skan		}
675132718Skan
676132718Skan		if (c)
677132718Skan			*cp = 0;
678132718Skan		return 1;
679132718Skan	}
680132718Skan}
681132718Skan
682132718Skanchar *get_type(type)
683132718Skanint	type;
684132718Skan{
685132718Skan	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
686132718Skan	int	counter = 0;
687132718Skan	struct	part_type *ptr = part_types;
688132718Skan
689132718Skan
690132718Skan	while(counter < numentries)
691132718Skan	{
692132718Skan		if(ptr->type == type)
693132718Skan		{
694132718Skan			return(ptr->name);
695132718Skan		}
696132718Skan		ptr++;
697132718Skan		counter++;
698132718Skan	}
699132718Skan	return("unknown");
700132718Skan}
701132718Skan