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