Home | History | Annotate | Line # | Download | only in fdisk
fdisk.c revision 1.29
      1  1.29        ws /*	$NetBSD: fdisk.c,v 1.29 1998/10/02 17:23:22 ws Exp $	*/
      2  1.10       cgd 
      3   1.4   mycroft /*
      4   1.1       cgd  * Mach Operating System
      5   1.1       cgd  * Copyright (c) 1992 Carnegie Mellon University
      6   1.1       cgd  * All Rights Reserved.
      7   1.4   mycroft  *
      8   1.1       cgd  * Permission to use, copy, modify and distribute this software and its
      9   1.1       cgd  * documentation is hereby granted, provided that both the copyright
     10   1.1       cgd  * notice and this permission notice appear in all copies of the
     11   1.1       cgd  * software, derivative works or modified versions, and any portions
     12   1.1       cgd  * thereof, and that both notices appear in supporting documentation.
     13   1.4   mycroft  *
     14   1.1       cgd  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15   1.1       cgd  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
     16   1.1       cgd  * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17   1.4   mycroft  *
     18   1.1       cgd  * Carnegie Mellon requests users of this software to return to
     19   1.4   mycroft  *
     20   1.1       cgd  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21   1.1       cgd  *  School of Computer Science
     22   1.1       cgd  *  Carnegie Mellon University
     23   1.1       cgd  *  Pittsburgh PA 15213-3890
     24   1.4   mycroft  *
     25   1.1       cgd  * any improvements or extensions that they make and grant Carnegie Mellon
     26   1.1       cgd  * the rights to redistribute these changes.
     27   1.1       cgd  */
     28   1.1       cgd 
     29  1.16      phil #include <sys/cdefs.h>
     30  1.16      phil 
     31   1.2   mycroft #ifndef lint
     32  1.29        ws __RCSID("$NetBSD: fdisk.c,v 1.29 1998/10/02 17:23:22 ws Exp $");
     33   1.2   mycroft #endif /* not lint */
     34   1.2   mycroft 
     35   1.1       cgd #include <sys/types.h>
     36   1.1       cgd #include <sys/disklabel.h>
     37   1.4   mycroft #include <sys/ioctl.h>
     38  1.18     lukem #include <sys/param.h>
     39   1.1       cgd #include <sys/stat.h>
     40   1.4   mycroft 
     41   1.8       cgd #include <ctype.h>
     42   1.4   mycroft #include <err.h>
     43  1.18     lukem #include <errno.h>
     44   1.1       cgd #include <fcntl.h>
     45  1.18     lukem #include <paths.h>
     46   1.4   mycroft #include <stdio.h>
     47   1.4   mycroft #include <stdlib.h>
     48   1.8       cgd #include <string.h>
     49   1.8       cgd #include <unistd.h>
     50  1.19     lukem #include <util.h>
     51   1.1       cgd 
     52   1.1       cgd #define LBUF 100
     53   1.1       cgd static char lbuf[LBUF];
     54   1.1       cgd 
     55   1.1       cgd /*
     56   1.1       cgd  * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
     57   1.1       cgd  *	Copyright (c) 1989	Robert. V. Baron
     58   1.1       cgd  *	Created.
     59   1.1       cgd  */
     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.5   mycroft int cylinders, sectors, heads, cylindersectors, disksectors;
     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.5   mycroft int dos_cylinders;
     79   1.1       cgd int dos_heads;
     80   1.1       cgd int dos_sectors;
     81   1.5   mycroft int dos_cylindersectors;
     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.28        ws 
     86  1.28        ws #define	MAXCYL	1024
     87   1.4   mycroft int partition = -1;
     88   1.4   mycroft 
     89   1.4   mycroft int a_flag;		/* set active partition */
     90  1.28        ws int i_flag;		/* init bootcode */
     91   1.4   mycroft int u_flag;		/* update partition data */
     92  1.15      phil int sh_flag;		/* Output data as shell defines */
     93  1.15      phil int f_flag;		/* force --not interactive */
     94  1.15      phil int s_flag;		/* set id,offset,size */
     95  1.16      phil int b_flag;		/* Set cyl, heads, secs (as c/h/s) */
     96  1.16      phil int b_cyl, b_head, b_sec;  /* b_flag values. */
     97   1.4   mycroft 
     98   1.4   mycroft unsigned char bootcode[] = {
     99   1.4   mycroft 0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf,
    100   1.4   mycroft 0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe,
    101   1.4   mycroft 0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd,
    102   1.4   mycroft 0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74,
    103   1.4   mycroft 0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00,
    104   1.4   mycroft 0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe,
    105   1.4   mycroft 0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00,
    106   1.4   mycroft 0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10,
    107   1.1       cgd 0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
    108   1.1       cgd 'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
    109   1.1       cgd 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
    110   1.4   mycroft 'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ',
    111   1.1       cgd 	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
    112   1.1       cgd 'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
    113   1.1       cgd 	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
    114   1.1       cgd 'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
    115   1.4   mycroft 	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0,
    116   1.1       cgd 
    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,   0,   0,
    123   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    124   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    125   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    126   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    127   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    128   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,
    129   1.4   mycroft   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0
    130   1.1       cgd };
    131   1.1       cgd 
    132  1.25  drochner static char reserved[] = "reserved";
    134   1.4   mycroft 
    135   1.4   mycroft struct part_type {
    136   1.4   mycroft 	int type;
    137   1.4   mycroft 	char *name;
    138   1.4   mycroft } part_types[] = {
    139   1.4   mycroft 	{0x00, "unused"},
    140   1.4   mycroft 	{0x01, "Primary DOS with 12 bit FAT"},
    141   1.4   mycroft 	{0x02, "XENIX / filesystem"},
    142  1.13     perry 	{0x03, "XENIX /usr filesystem"},
    143  1.25  drochner 	{0x04, "Primary DOS with 16 bit FAT <32M"},
    144  1.13     perry 	{0x05, "Extended partition"},
    145  1.13     perry 	{0x06, "Primary 'big' DOS, 16-bit FAT (> 32MB)"},
    146  1.25  drochner 	{0x07, "OS/2 HPFS or NTFS or QNX2 or Advanced UNIX"},
    147  1.25  drochner 	{0x08, "AIX filesystem or OS/2 (thru v1.3) or DELL multiple drives"
    148   1.4   mycroft 	       "or Commodore DOS or SplitDrive"},
    149  1.13     perry 	{0x09, "AIX boot partition or Coherent"},
    150  1.25  drochner 	{0x0A, "OS/2 Boot Manager or Coherent swap or OPUS"},
    151  1.25  drochner 	{0x0b, "Primary DOS with 32 bit FAT"},
    152  1.25  drochner 	{0x0c, "Primary DOS with 32 bit FAT - LBA"},
    153  1.25  drochner 	{0x0d, "Type 7??? - LBA"},
    154  1.25  drochner 	{0x0E, "DOS (16-bit FAT) - LBA"},
    155   1.4   mycroft 	{0x0F, "Ext. partition - LBA"},
    156  1.13     perry 	{0x10, "OPUS"},
    157  1.13     perry 	{0x11, "OS/2 BM: hidden DOS 12-bit FAT"},
    158  1.25  drochner 	{0x12, "Compaq diagnostics"},
    159  1.13     perry 	{0x14, "OS/2 BM: hidden DOS 16-bit FAT <32M or Novell DOS 7.0 bug"},
    160  1.13     perry 	{0x16, "OS/2 BM: hidden DOS 16-bit FAT >=32M"},
    161  1.13     perry 	{0x17, "OS/2 BM: hidden IFS"},
    162  1.25  drochner 	{0x18, "AST Windows swapfile"},
    163  1.25  drochner 	{0x19, "Willowtech Photon coS"},
    164  1.25  drochner 	{0x1e, "hidden FAT95"},
    165  1.25  drochner 	{0x20, "Willowsoft OFS1"},
    166  1.25  drochner 	{0x21, reserved},
    167  1.13     perry 	{0x23, reserved},
    168  1.25  drochner 	{0x24, "NEC DOS"},
    169  1.25  drochner 	{0x26, reserved},
    170  1.25  drochner 	{0x31, reserved},
    171  1.25  drochner 	{0x33, reserved},
    172  1.25  drochner 	{0x34, reserved},
    173  1.25  drochner 	{0x36, reserved},
    174  1.13     perry 	{0x38, "Theos"},
    175  1.25  drochner 	{0x3C, "PartitionMagic recovery"},
    176  1.25  drochner 	{0x40, "VENIX 286 or LynxOS"},
    177  1.13     perry 	{0x41, "Linux/MINIX (sharing disk with DRDOS) or Personal RISC boot"},
    178  1.13     perry 	{0x42, "SFS or Linux swap (sharing disk with DRDOS)"},
    179  1.13     perry 	{0x43, "Linux native (sharing disk with DRDOS)"},
    180  1.13     perry 	{0x50, "DM (disk manager)"},
    181   1.4   mycroft 	{0x51, "DM6 Aux1 (or Novell)"},
    182  1.13     perry 	{0x52, "CP/M or Microport SysV/AT"},
    183  1.25  drochner 	{0x53, "DM6 Aux3"},
    184  1.13     perry 	{0x54, "DM6 DDO"},
    185  1.13     perry 	{0x55, "EZ-Drive (disk manager)"},
    186  1.13     perry 	{0x56, "Golden Bow (disk manager)"},
    187  1.13     perry 	{0x5C, "Priam Edisk (disk manager)"},
    188  1.25  drochner 	{0x61, "SpeedStor"},
    189  1.25  drochner 	{0x63, "GNU HURD or Mach or Sys V/386 (such as ISC UNIX) or MtXinu"},
    190   1.4   mycroft 	{0x64, "Novell Netware 2.xx or Speedstore"},
    191  1.25  drochner 	{0x65, "Novell Netware 3.xx"},
    192  1.25  drochner 	{0x66, "Novell 386 Netware"},
    193  1.25  drochner 	{0x67, "Novell"},
    194  1.25  drochner 	{0x68, "Novell"},
    195  1.13     perry 	{0x69, "Novell"},
    196  1.25  drochner 	{0x70, "DiskSecure Multi-Boot"},
    197  1.25  drochner 	{0x71, reserved},
    198  1.25  drochner 	{0x73, reserved},
    199  1.13     perry 	{0x74, reserved},
    200  1.25  drochner 	{0x75, "PC/IX"},
    201  1.13     perry 	{0x76, reserved},
    202  1.13     perry 	{0x77, "QNX4.x"},
    203  1.13     perry 	{0x78, "QNX4.x 2nd part"},
    204  1.13     perry 	{0x79, "QNX4.x 3rd part"},
    205  1.13     perry 	{0x80, "MINIX until 1.4a"},
    206  1.25  drochner 	{0x81, "MINIX since 1.4b, early Linux, Mitac dmgr"},
    207  1.13     perry 	{0x82, "Linux swap or Prime or Solaris"},
    208  1.13     perry 	{0x83, "Linux native"},
    209  1.13     perry 	{0x84, "OS/2 hidden C: drive"},
    210  1.25  drochner 	{0x85, "Linux extended"},
    211  1.25  drochner 	{0x86, "NT FAT volume set"},
    212   1.4   mycroft 	{0x87, "NTFS volume set or HPFS mirrored"},
    213   1.4   mycroft 	{0x93, "Amoeba filesystem"},
    214  1.25  drochner 	{0x94, "Amoeba bad block table"},
    215  1.25  drochner 	{0x99, "Mylex EISA SCSI"},
    216  1.13     perry 	{0x9f, "BSDI?"},
    217  1.25  drochner 	{0xA0, "IBM Thinkpad hibernation"},
    218  1.25  drochner 	{0xa1, reserved},
    219  1.25  drochner 	{0xa3, reserved},
    220  1.25  drochner 	{0xa4, reserved},
    221  1.13     perry 	{0xA5, "FreeBSD or 386BSD or old NetBSD"},
    222  1.13     perry 	{0xA6, "OpenBSD"},
    223  1.25  drochner 	{0xA7, "NeXTSTEP 486"},
    224  1.25  drochner 	{0xa9, "NetBSD"},
    225  1.25  drochner 	{0xb1, reserved},
    226  1.25  drochner 	{0xb3, reserved},
    227  1.25  drochner 	{0xb4, reserved},
    228   1.4   mycroft 	{0xb6, reserved},
    229   1.4   mycroft 	{0xB7, "BSDI BSD/386 filesystem"},
    230  1.25  drochner 	{0xB8, "BSDI BSD/386 swap"},
    231  1.13     perry 	{0xc0, "CTOS"},
    232  1.13     perry 	{0xC1, "DRDOS/sec (FAT-12)"},
    233  1.13     perry 	{0xC4, "DRDOS/sec (FAT-16, < 32M)"},
    234  1.25  drochner 	{0xC6, "DRDOS/sec (FAT-16, >= 32M)"},
    235  1.25  drochner 	{0xC7, "Syrinx (Cyrnix?) or HPFS disabled"},
    236  1.13     perry 	{0xd8, "CP/M 86"},
    237  1.13     perry 	{0xDB, "CP/M or Concurrent CP/M or Concurrent DOS or CTOS"},
    238  1.25  drochner 	{0xE1, "DOS access or SpeedStor 12-bit FAT extended partition"},
    239  1.13     perry 	{0xE3, "DOS R/O or SpeedStor or Storage Dimensions"},
    240  1.25  drochner 	{0xE4, "SpeedStor 16-bit FAT extended partition < 1024 cyl."},
    241  1.25  drochner 	{0xe5, reserved},
    242  1.25  drochner 	{0xe6, reserved},
    243   1.4   mycroft 	{0xF1, "SpeedStor or Storage Dimensions"},
    244  1.25  drochner 	{0xF2, "DOS 3.3+ Secondary"},
    245  1.25  drochner 	{0xf3, reserved},
    246  1.25  drochner 	{0xF4, "SpeedStor large partition or Storage Dimensions"},
    247  1.25  drochner 	{0xf6, reserved},
    248  1.13     perry 	{0xFE, "SpeedStor >1024 cyl. or LANstep or IBM PS/2 IML"},
    249   1.1       cgd 	{0xFF, "Xenix Bad Block Table"},
    250   1.1       cgd };
    251   1.4   mycroft 
    252   1.4   mycroft void	usage __P((void));
    253   1.4   mycroft void	print_s0 __P((int));
    254  1.28        ws void	print_part __P((int));
    255  1.11   ghudson void	init_sector0 __P((int, int));
    256  1.11   ghudson void	intuit_translated_geometry __P((void));
    257  1.11   ghudson int	try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t,
    258  1.11   ghudson 		       quad_t));
    259  1.15      phil int	try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t));
    260   1.4   mycroft void	change_part __P((int, int, int, int));
    261   1.4   mycroft void	print_params __P((void));
    262   1.4   mycroft void	change_active __P((int));
    263   1.4   mycroft void	get_params_to_use __P((void));
    264   1.4   mycroft void	dos __P((int, unsigned char *, unsigned char *, unsigned char *));
    265   1.4   mycroft int	open_disk __P((int));
    266   1.4   mycroft int	read_disk __P((int, void *));
    267   1.4   mycroft int	write_disk __P((int, void *));
    268   1.4   mycroft int	get_params __P((void));
    269   1.4   mycroft int	read_s0 __P((void));
    270   1.4   mycroft int	write_s0 __P((void));
    271   1.5   mycroft int	yesno __P((char *));
    272   1.4   mycroft void	decimal __P((char *, int *));
    273   1.4   mycroft int	type_match __P((const void *, const void *));
    274  1.16      phil char	*get_type __P((int));
    275  1.16      phil int	get_mapping __P((int, int *, int *, int *, long *));
    276  1.16      phil 
    277  1.16      phil static inline unsigned short getshort __P((void *));
    278  1.16      phil static inline void putshort __P((void *p, unsigned short));
    279  1.16      phil static inline unsigned long getlong __P((void *));
    280  1.16      phil static inline void putlong __P((void *,	unsigned long));
    281  1.16      phil 
    282  1.16      phil 
    283   1.1       cgd int	main __P((int, char **));
    284   1.4   mycroft 
    285   1.1       cgd int
    286   1.4   mycroft main(argc, argv)
    287   1.4   mycroft 	int argc;
    288   1.1       cgd 	char *argv[];
    289   1.4   mycroft {
    290   1.4   mycroft 	int ch;
    291   1.1       cgd 	int part;
    292  1.15      phil 
    293  1.15      phil 	int csysid, cstart, csize;	/* For the b_flag. */
    294  1.16      phil 
    295  1.15      phil 	a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
    296  1.16      phil 	csysid = cstart = csize = 0;
    297   1.4   mycroft 	while ((ch = getopt(argc, argv, "0123Safius:b:")) != -1)
    298   1.4   mycroft 		switch (ch) {
    299   1.4   mycroft 		case '0':
    300   1.4   mycroft 			partition = 0;
    301   1.4   mycroft 			break;
    302   1.4   mycroft 		case '1':
    303   1.4   mycroft 			partition = 1;
    304   1.4   mycroft 			break;
    305   1.4   mycroft 		case '2':
    306   1.4   mycroft 			partition = 2;
    307   1.4   mycroft 			break;
    308   1.4   mycroft 		case '3':
    309   1.4   mycroft 			partition = 3;
    310  1.15      phil 			break;
    311  1.15      phil 		case 'S':
    312  1.15      phil 			sh_flag = 1;
    313   1.4   mycroft 			break;
    314   1.4   mycroft 		case 'a':
    315   1.4   mycroft 			a_flag = 1;
    316  1.15      phil 			break;
    317  1.15      phil 		case 'f':
    318  1.15      phil 			f_flag = 1;
    319   1.4   mycroft 			break;
    320   1.4   mycroft 		case 'i':
    321  1.15      phil 			i_flag = 1;
    322   1.4   mycroft 			break;
    323   1.4   mycroft 		case 'u':
    324   1.1       cgd 			u_flag = 1;
    325  1.14      phil 			break;
    326  1.14      phil 		case 's':
    327  1.16      phil 			s_flag = 1;
    328  1.16      phil 			if (sscanf (optarg, "%d/%d/%d",
    329  1.16      phil 				    &csysid, &cstart, &csize) != 3) {
    330  1.16      phil 				(void)fprintf (stderr, "%s: Bad argument "
    331  1.16      phil 					       "to the -s flag.\n",
    332  1.16      phil 					       argv[0]);
    333  1.16      phil 				exit (1);
    334  1.16      phil 			}
    335  1.16      phil 			break;
    336  1.16      phil 		case 'b':
    337  1.16      phil 			b_flag = 1;
    338  1.16      phil 			if (sscanf (optarg, "%d/%d/%d",
    339  1.16      phil 				    &b_cyl, &b_head, &b_sec) != 3) {
    340  1.16      phil 				(void)fprintf (stderr, "%s: Bad argument "
    341  1.16      phil 					       "to the -b flag.\n",
    342  1.16      phil 					       argv[0]);
    343  1.16      phil 				exit (1);
    344  1.28        ws 			}
    345  1.28        ws 			if (b_cyl > MAXCYL)
    346  1.14      phil 				b_cyl = MAXCYL;
    347   1.4   mycroft 			break;
    348   1.4   mycroft 		default:
    349   1.1       cgd 			usage();
    350   1.4   mycroft 		}
    351   1.4   mycroft 	argc -= optind;
    352   1.1       cgd 	argv += optind;
    353  1.15      phil 
    354  1.15      phil 	if (sh_flag && (a_flag || i_flag || u_flag || f_flag || s_flag))
    355  1.15      phil 		usage();
    356  1.15      phil 
    357  1.15      phil 	if (partition == -1 && s_flag) {
    358  1.15      phil 		(void) fprintf (stderr,
    359  1.14      phil 				"-s flag requires a partition selected.\n");
    360  1.15      phil 		usage();
    361  1.15      phil 	}
    362   1.1       cgd 
    363   1.1       cgd 	if (argc > 0)
    364   1.4   mycroft 		disk = argv[0];
    365   1.4   mycroft 
    366   1.1       cgd 	if (open_disk(a_flag || i_flag || u_flag) < 0)
    367   1.1       cgd 		exit(1);
    368  1.11   ghudson 
    369  1.28        ws 	if (read_s0())
    370  1.11   ghudson 		init_sector0(sectors > 63 ? 63 : sectors, 1);
    371  1.11   ghudson 
    372  1.11   ghudson 	intuit_translated_geometry();
    373  1.17      phil 
    374  1.14      phil 	if (!sh_flag && !f_flag)
    375  1.15      phil 		printf("******* Working on device %s *******\n", disk);
    376  1.15      phil 
    377  1.16      phil 
    378   1.1       cgd 	if ((i_flag || u_flag) && (!f_flag || b_flag))
    379   1.1       cgd 		get_params_to_use();
    380  1.15      phil 
    381  1.28        ws 	if (i_flag)
    382  1.15      phil 		init_sector0(dos_sectors > 63 ? 63 : dos_sectors, 0);
    383  1.17      phil 
    384  1.14      phil 	if (!sh_flag && !f_flag)
    385  1.14      phil 		printf("Warning: BIOS sector numbering starts with sector 1\n");
    386  1.15      phil 
    387  1.15      phil 	/* Do the update stuff! */
    388  1.15      phil 	if (u_flag) {
    389  1.15      phil 		if (!f_flag)
    390  1.15      phil 			printf("Information from DOS bootblock is:\n");
    391  1.15      phil 		if (partition == -1)
    392  1.15      phil 			for (part = 0; part < NDOSPART; part++)
    393  1.15      phil 				change_part(part,-1, -1, -1);
    394  1.15      phil 		else
    395   1.4   mycroft 			change_part(partition, csysid, cstart, csize);
    396  1.15      phil 	} else
    397  1.15      phil 		if (!i_flag)
    398   1.1       cgd 			print_s0(partition);
    399  1.15      phil 
    400   1.1       cgd 	if (a_flag)
    401   1.1       cgd 		change_active(partition);
    402  1.15      phil 
    403  1.15      phil 	if (u_flag || a_flag || i_flag) {
    404  1.15      phil 		if (!f_flag) {
    405  1.15      phil 			printf("\nWe haven't changed the partition table "
    406  1.15      phil 			       "yet.  This is your last chance.\n");
    407  1.15      phil 			print_s0(-1);
    408  1.15      phil 			if (yesno("Should we write new partition table?"))
    409  1.15      phil 				write_s0();
    410   1.1       cgd 		} else
    411   1.1       cgd 			write_s0();
    412   1.1       cgd 	}
    413   1.1       cgd 
    414   1.4   mycroft 	exit(0);
    415   1.1       cgd }
    416   1.4   mycroft 
    417   1.4   mycroft void
    418   1.4   mycroft usage()
    419  1.15      phil {
    420  1.16      phil 	(void)fprintf(stderr, "usage: fdisk [-aiufS] [-0|-1|-2|-3] "
    421   1.4   mycroft 		      "[device]\n");
    422   1.1       cgd 	exit(1);
    423   1.1       cgd }
    424   1.4   mycroft 
    425   1.1       cgd void
    426   1.4   mycroft print_s0(which)
    427   1.1       cgd 	int which;
    428   1.4   mycroft {
    429   1.1       cgd 	int part;
    430   1.1       cgd 
    431  1.15      phil 	print_params();
    432  1.15      phil 	if (!sh_flag)
    433   1.4   mycroft 		printf("Information from DOS bootblock is:\n");
    434  1.15      phil 	if (which == -1) {
    435  1.15      phil 		for (part = 0; part < NDOSPART; part++) {
    436  1.15      phil 			if (!sh_flag)
    437  1.15      phil 				printf("%d: ", part);
    438  1.15      phil 			print_part(part);
    439   1.4   mycroft 		}
    440   1.1       cgd 	} else
    441   1.1       cgd 		print_part(which);
    442   1.1       cgd }
    443   1.1       cgd 
    444   1.1       cgd static struct dos_partition mtpart = { 0 };
    445  1.12   thorpej 
    446  1.12   thorpej static inline unsigned short
    447  1.12   thorpej getshort(p)
    448  1.12   thorpej 	void *p;
    449  1.12   thorpej {
    450  1.12   thorpej 	unsigned char *cp = p;
    451  1.12   thorpej 
    452  1.12   thorpej 	return cp[0] | (cp[1] << 8);
    453  1.12   thorpej }
    454  1.12   thorpej 
    455  1.12   thorpej static inline void
    456  1.12   thorpej putshort(p, l)
    457  1.12   thorpej 	void *p;
    458  1.12   thorpej 	unsigned short l;
    459  1.12   thorpej {
    460  1.12   thorpej 	unsigned char *cp = p;
    461  1.12   thorpej 
    462  1.12   thorpej 	*cp++ = l;
    463  1.12   thorpej 	*cp++ = l >> 8;
    464  1.12   thorpej }
    465  1.12   thorpej 
    466  1.12   thorpej static inline unsigned long
    467  1.12   thorpej getlong(p)
    468  1.12   thorpej 	void *p;
    469  1.12   thorpej {
    470  1.12   thorpej 	unsigned char *cp = p;
    471  1.12   thorpej 
    472  1.12   thorpej 	return cp[0] | (cp[1] << 8) | (cp[2] << 16) | (cp[3] << 24);
    473  1.12   thorpej }
    474  1.12   thorpej 
    475  1.12   thorpej static inline void
    476  1.12   thorpej putlong(p, l)
    477  1.12   thorpej 	void *p;
    478  1.12   thorpej 	unsigned long l;
    479  1.12   thorpej {
    480  1.12   thorpej 	unsigned char *cp = p;
    481  1.12   thorpej 
    482  1.12   thorpej 	*cp++ = l;
    483  1.12   thorpej 	*cp++ = l >> 8;
    484  1.12   thorpej 	*cp++ = l >> 16;
    485  1.12   thorpej 	*cp++ = l >> 24;
    486  1.12   thorpej }
    487   1.4   mycroft 
    488   1.4   mycroft void
    489   1.4   mycroft print_part(part)
    490   1.1       cgd 	int part;
    491   1.4   mycroft {
    492  1.14      phil 	struct dos_partition *partp;
    493   1.1       cgd 	int empty;
    494   1.4   mycroft 
    495  1.14      phil 	partp = &mboot.parts[part];
    496  1.14      phil 	empty = !memcmp(partp, &mtpart, sizeof(struct dos_partition));
    497  1.15      phil 
    498  1.14      phil 	if (sh_flag) {
    499  1.14      phil 		if (empty) {
    500  1.14      phil 			printf("PART%dSIZE=0\n", part);
    501  1.14      phil 			return;
    502  1.14      phil 		}
    503  1.14      phil 
    504  1.16      phil 		printf("PART%dID=%d\n", part, partp->dp_typ);
    505  1.16      phil 		printf("PART%dSIZE=%ld\n", part, getlong(&partp->dp_size));
    506  1.18     lukem 		printf("PART%dSTART=%ld\n", part, getlong(&partp->dp_start));
    507  1.14      phil 		printf("PART%dFLAG=0x%x\n", part, partp->dp_flag);
    508  1.14      phil 		printf("PART%dBCYL=%d\n", part, DPCYL(partp->dp_scyl,
    509  1.14      phil 						      partp->dp_ssect));
    510  1.14      phil 		printf("PART%dBHEAD=%d\n", part, partp->dp_shd);
    511  1.14      phil 		printf("PART%dBSEC=%d\n", part, DPSECT(partp->dp_ssect));
    512  1.14      phil 		printf("PART%dECYL=%d\n", part, DPCYL(partp->dp_ecyl,
    513  1.14      phil 						      partp->dp_esect));
    514  1.14      phil 		printf("PART%dEHEAD=%d\n", part, partp->dp_ehd);
    515  1.14      phil 		printf("PART%dESEC=%d\n", part, DPSECT(partp->dp_esect));
    516  1.14      phil 		return;
    517  1.14      phil 	}
    518  1.15      phil 
    519  1.14      phil 	/* Not sh_flag. */
    520   1.1       cgd 	if (empty) {
    521   1.1       cgd 		printf("<UNUSED>\n");
    522   1.1       cgd 		return;
    523   1.5   mycroft 	}
    524  1.18     lukem 	printf("sysid %d (%s)\n", partp->dp_typ, get_type(partp->dp_typ));
    525  1.12   thorpej 	printf("    start %ld, size %ld (%ld MB), flag 0x%x\n",
    526  1.12   thorpej 	    getlong(&partp->dp_start), getlong(&partp->dp_size),
    527   1.5   mycroft 	    getlong(&partp->dp_size) * 512 / (1024 * 1024), partp->dp_flag);
    528   1.5   mycroft 	printf("\tbeg: cylinder %4d, head %3d, sector %2d\n",
    529   1.5   mycroft 	    DPCYL(partp->dp_scyl, partp->dp_ssect),
    530   1.5   mycroft 	    partp->dp_shd, DPSECT(partp->dp_ssect));
    531   1.5   mycroft 	printf("\tend: cylinder %4d, head %3d, sector %2d\n",
    532   1.5   mycroft 	    DPCYL(partp->dp_ecyl, partp->dp_esect),
    533   1.1       cgd 	    partp->dp_ehd, DPSECT(partp->dp_esect));
    534   1.1       cgd }
    535   1.4   mycroft 
    536  1.28        ws void
    537  1.28        ws init_sector0(start, dopart)
    538   1.1       cgd 	int start, dopart;
    539  1.15      phil {
    540  1.15      phil 	int i;
    541   1.4   mycroft 
    542  1.12   thorpej 	memcpy(mboot.bootinst, bootcode, sizeof(bootcode));
    543  1.15      phil 	putshort(&mboot.signature, BOOT_MAGIC);
    544  1.28        ws 
    545  1.28        ws 	if (dopart)
    546  1.28        ws 		for (i=0; i<3; i++)
    547   1.1       cgd 			memset (&mboot.parts[i], 0, sizeof(struct dos_partition));
    548  1.11   ghudson 
    549  1.11   ghudson }
    550  1.11   ghudson 
    551  1.11   ghudson /* Prerequisite: the disklabel parameters and master boot record must
    552  1.11   ghudson  *		 have been read (i.e. dos_* and mboot are meaningful).
    553  1.11   ghudson  * Specification: modifies dos_cylinders, dos_heads, dos_sectors, and
    554  1.11   ghudson  *		  dos_cylindersectors to be consistent with what the
    555  1.11   ghudson  *		  partition table is using, if we can find a geometry
    556  1.11   ghudson  *		  which is consistent with all partition table entries.
    557  1.11   ghudson  *		  We may get the number of cylinders slightly wrong (in
    558  1.11   ghudson  *		  the conservative direction).  The idea is to be able
    559  1.11   ghudson  *		  to create a NetBSD partition on a disk we don't know
    560  1.11   ghudson  *		  the translated geometry of.
    561  1.11   ghudson  * This whole routine should be replaced with a kernel interface to get
    562  1.11   ghudson  * the BIOS geometry (which in turn requires modifications to the i386
    563  1.11   ghudson  * boot loader to pass in the BIOS geometry for each disk). */
    564  1.11   ghudson void
    565  1.11   ghudson intuit_translated_geometry()
    566  1.15      phil {
    567  1.11   ghudson 
    568  1.11   ghudson 	int cylinders = -1, heads = -1, sectors = -1, i, j;
    569  1.11   ghudson 	int c1, h1, s1, c2, h2, s2;
    570  1.11   ghudson 	long a1, a2;
    571  1.11   ghudson 	quad_t num, denom;
    572  1.11   ghudson 
    573  1.11   ghudson 	/* Try to deduce the number of heads from two different mappings. */
    574  1.11   ghudson 	for (i = 0; i < NDOSPART * 2; i++) {
    575  1.11   ghudson 		if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
    576  1.11   ghudson 			continue;
    577  1.11   ghudson 		for (j = 0; j < 8; j++) {
    578  1.11   ghudson 			if (get_mapping(j, &c2, &h2, &s2, &a2) < 0)
    579  1.22     enami 				continue;
    580  1.22     enami 			num = (quad_t)h1*(a2-s2) - (quad_t)h2*(a1-s1);
    581  1.11   ghudson 			denom = (quad_t)c2*(a1-s1) - (quad_t)c1*(a2-s2);
    582  1.11   ghudson 			if (denom != 0 && num % denom == 0) {
    583  1.11   ghudson 				heads = num / denom;
    584  1.11   ghudson 				break;
    585  1.11   ghudson 			}
    586  1.11   ghudson 		}
    587  1.11   ghudson 		if (heads != -1)
    588  1.11   ghudson 			break;
    589  1.11   ghudson 	}
    590  1.11   ghudson 
    591  1.11   ghudson 	if (heads == -1)
    592  1.11   ghudson 		return;
    593  1.11   ghudson 
    594  1.11   ghudson 	/* Now figure out the number of sectors from a single mapping. */
    595  1.11   ghudson 	for (i = 0; i < NDOSPART * 2; i++) {
    596  1.11   ghudson 		if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
    597  1.11   ghudson 			continue;
    598  1.11   ghudson 		num = a1 - s1;
    599  1.11   ghudson 		denom = c1 * heads + h1;
    600  1.11   ghudson 		if (denom != 0 && num % denom == 0) {
    601  1.11   ghudson 			sectors = num / denom;
    602  1.11   ghudson 			break;
    603  1.11   ghudson 		}
    604  1.11   ghudson 	}
    605  1.11   ghudson 
    606  1.11   ghudson 	if (sectors == -1)
    607  1.11   ghudson 		return;
    608  1.11   ghudson 
    609  1.24   ghudson 	/* Estimate the number of cylinders. */
    610  1.11   ghudson 	cylinders = disklabel.d_secperunit / heads / sectors;
    611  1.11   ghudson 
    612  1.11   ghudson 	/* Now verify consistency with each of the partition table entries.
    613  1.11   ghudson 	 * Be willing to shove cylinders up a little bit to make things work,
    614  1.11   ghudson 	 * but translation mismatches are fatal. */
    615  1.11   ghudson 	for (i = 0; i < NDOSPART * 2; i++) {
    616  1.11   ghudson 		if (get_mapping(i, &c1, &h1, &s1, &a1) < 0)
    617  1.11   ghudson 			continue;
    618  1.11   ghudson 		if (sectors * (c1 * heads + h1) + s1 != a1)
    619  1.11   ghudson 			return;
    620  1.11   ghudson 		if (c1 >= cylinders)
    621  1.11   ghudson 			cylinders = c1 + 1;
    622  1.11   ghudson 	}
    623  1.11   ghudson 
    624  1.11   ghudson 	/* Everything checks out.  Reset the geometry to use for further
    625  1.11   ghudson 	 * calculations. */
    626  1.11   ghudson 	dos_cylinders = cylinders;
    627  1.11   ghudson 	dos_heads = heads;
    628  1.11   ghudson 	dos_sectors = sectors;
    629  1.11   ghudson 	dos_cylindersectors = heads * sectors;
    630  1.11   ghudson }
    631  1.11   ghudson 
    632  1.11   ghudson /* For the purposes of intuit_translated_geometry(), treat the partition
    633  1.11   ghudson  * table as a list of eight mapping between (cylinder, head, sector)
    634  1.11   ghudson  * triplets and absolute sectors.  Get the relevant geometry triplet and
    635  1.11   ghudson  * absolute sectors for a given entry, or return -1 if it isn't present.
    636  1.11   ghudson  * Note: for simplicity, the returned sector is 0-based. */
    637  1.11   ghudson int
    638  1.11   ghudson get_mapping(i, cylinder, head, sector, absolute)
    639  1.11   ghudson 	int i, *cylinder, *head, *sector;
    640  1.11   ghudson 	long *absolute;
    641  1.11   ghudson {
    642  1.11   ghudson 	struct dos_partition *part = &mboot.parts[i / 2];
    643  1.11   ghudson 
    644  1.11   ghudson 	if (part->dp_typ == 0)
    645  1.11   ghudson 		return -1;
    646  1.11   ghudson 	if (i % 2 == 0) {
    647  1.11   ghudson 		*cylinder = DPCYL(part->dp_scyl, part->dp_ssect);
    648  1.11   ghudson 		*head = part->dp_shd;
    649  1.12   thorpej 		*sector = DPSECT(part->dp_ssect) - 1;
    650  1.11   ghudson 		*absolute = getlong(&part->dp_start);
    651  1.11   ghudson 	} else {
    652  1.11   ghudson 		*cylinder = DPCYL(part->dp_ecyl, part->dp_esect);
    653  1.11   ghudson 		*head = part->dp_ehd;
    654  1.12   thorpej 		*sector = DPSECT(part->dp_esect) - 1;
    655  1.12   thorpej 		*absolute = getlong(&part->dp_start)
    656  1.11   ghudson 		    + getlong(&part->dp_size) - 1;
    657  1.11   ghudson 	}
    658   1.1       cgd 	return 0;
    659   1.1       cgd }
    660   1.4   mycroft 
    661  1.15      phil void
    662  1.15      phil change_part(part, csysid, cstart, csize)
    663   1.1       cgd 	int part, csysid, cstart, csize;
    664   1.4   mycroft {
    665   1.1       cgd 	struct dos_partition *partp;
    666   1.4   mycroft 
    667   1.1       cgd 	partp = &mboot.parts[part];
    668  1.15      phil 
    669  1.29        ws 	if (s_flag) {
    670  1.29        ws 		if (csysid == 0 && cstart == 0 && csize == 0)
    671  1.29        ws 			memset(partp, 0, sizeof *partp);
    672  1.29        ws 		else {
    673  1.28        ws 			partp->dp_typ = csysid;
    674  1.29        ws #if 0
    675  1.28        ws 			checkcyl(cstart / dos_cylindersectors);
    676  1.29        ws #endif
    677  1.29        ws 			putlong(&partp->dp_start, cstart);
    678  1.29        ws 			putlong(&partp->dp_size, csize);
    679  1.29        ws 			dos(getlong(&partp->dp_start),
    680  1.29        ws 			    &partp->dp_scyl, &partp->dp_shd, &partp->dp_ssect);
    681  1.29        ws 			dos(getlong(&partp->dp_start)
    682  1.29        ws 			    + getlong(&partp->dp_size) - 1,
    683  1.29        ws 			    &partp->dp_ecyl, &partp->dp_ehd, &partp->dp_esect);
    684  1.15      phil 		}
    685  1.15      phil 		if (f_flag)
    686  1.15      phil 			return;
    687  1.15      phil 	}
    688  1.15      phil 
    689   1.4   mycroft 	printf("The data for partition %d is:\n", part);
    690   1.4   mycroft 	print_part(part);
    691   1.4   mycroft 	if (!u_flag || !yesno("Do you want to change it?"))
    692   1.1       cgd 		return;
    693   1.1       cgd 
    694   1.5   mycroft 	do {
    695   1.5   mycroft 		{
    696   1.5   mycroft 			int sysid, start, size;
    697   1.5   mycroft 
    698  1.12   thorpej 			sysid = partp->dp_typ,
    699  1.12   thorpej 			start = getlong(&partp->dp_start),
    700   1.5   mycroft 			size = getlong(&partp->dp_size);
    701   1.5   mycroft 			decimal("sysid", &sysid);
    702   1.5   mycroft 			decimal("start", &start);
    703   1.5   mycroft 			decimal("size", &size);
    704  1.12   thorpej 			partp->dp_typ = sysid;
    705  1.12   thorpej 			putlong(&partp->dp_start, start);
    706   1.5   mycroft 			putlong(&partp->dp_size, size);
    707   1.1       cgd 		}
    708   1.7   mycroft 
    709   1.5   mycroft 		if (yesno("Explicitly specify beg/end address?")) {
    710   1.4   mycroft 			int tsector, tcylinder, thead;
    711   1.5   mycroft 
    712   1.5   mycroft 			tcylinder = DPCYL(partp->dp_scyl, partp->dp_ssect);
    713   1.5   mycroft 			thead = partp->dp_shd;
    714   1.5   mycroft 			tsector = DPSECT(partp->dp_ssect);
    715  1.28        ws 			decimal("beginning cylinder", &tcylinder);
    716  1.28        ws #if 0
    717  1.28        ws 			checkcyl(tcylinder);
    718   1.5   mycroft #endif
    719   1.5   mycroft 			decimal("beginning head", &thead);
    720   1.5   mycroft 			decimal("beginning sector", &tsector);
    721   1.5   mycroft 			partp->dp_scyl = DOSCYL(tcylinder);
    722   1.5   mycroft 			partp->dp_shd = thead;
    723   1.5   mycroft 			partp->dp_ssect = DOSSECT(tsector, tcylinder);
    724   1.5   mycroft 
    725   1.5   mycroft 			tcylinder = DPCYL(partp->dp_ecyl, partp->dp_esect);
    726   1.5   mycroft 			thead = partp->dp_ehd;
    727   1.5   mycroft 			tsector = DPSECT(partp->dp_esect);
    728   1.5   mycroft 			decimal("ending cylinder", &tcylinder);
    729   1.5   mycroft 			decimal("ending head", &thead);
    730   1.5   mycroft 			decimal("ending sector", &tsector);
    731   1.5   mycroft 			partp->dp_ecyl = DOSCYL(tcylinder);
    732   1.5   mycroft 			partp->dp_ehd = thead;
    733   1.1       cgd 			partp->dp_esect = DOSSECT(tsector, tcylinder);
    734  1.28        ws 		} else {
    735  1.29        ws 
    736  1.29        ws 			if (partp->dp_typ == 0
    737  1.29        ws 			    && getlong(&partp->dp_start) == 0
    738  1.29        ws 			    && getlong(&partp->dp_size) == 0)
    739  1.29        ws 				memset(partp, 0, sizeof *partp);
    740  1.28        ws 			else {
    741  1.29        ws #if 0
    742  1.29        ws 				checkcyl(getlong(&partp->dp_start)
    743  1.28        ws 					 / dos_cylindersectors);
    744  1.29        ws #endif
    745  1.29        ws 				dos(getlong(&partp->dp_start), &partp->dp_scyl,
    746  1.29        ws 				    &partp->dp_shd, &partp->dp_ssect);
    747  1.29        ws 				dos(getlong(&partp->dp_start)
    748  1.29        ws 				    + getlong(&partp->dp_size) - 1,
    749  1.29        ws 				    &partp->dp_ecyl, &partp->dp_ehd,
    750  1.29        ws 				    &partp->dp_esect);
    751   1.1       cgd 			}
    752   1.4   mycroft 		}
    753   1.4   mycroft 
    754   1.7   mycroft 		print_part(part);
    755   1.1       cgd 	} while (!yesno("Is this entry okay?"));
    756   1.1       cgd }
    757   1.4   mycroft 
    758   1.1       cgd void
    759   1.1       cgd print_params()
    760   1.4   mycroft {
    761  1.15      phil 
    762  1.14      phil 	if (sh_flag) {
    763  1.14      phil 		printf ("DLCYL=%d\nDLHEAD=%d\nDLSEC=%d\n",
    764  1.14      phil 			cylinders, heads, sectors);
    765  1.14      phil 		printf ("BCYL=%d\nBHEAD=%d\nBSEC=%d\n",
    766  1.14      phil 			dos_cylinders, dos_heads, dos_sectors);
    767  1.14      phil 		return;
    768  1.14      phil 	}
    769  1.15      phil 
    770   1.1       cgd 	/* Not sh_flag */
    771   1.5   mycroft 	printf("parameters extracted from in-core disklabel are:\n");
    772   1.5   mycroft 	printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
    773  1.28        ws 	    cylinders, heads, sectors, cylindersectors);
    774   1.5   mycroft 	if (dos_sectors > 63 || dos_heads > 255)
    775   1.1       cgd 		printf("Figures below won't work with BIOS for partitions not in cylinder 1\n");
    776   1.5   mycroft 	printf("parameters to be used for BIOS calculations are:\n");
    777   1.5   mycroft 	printf("cylinders=%d heads=%d sectors/track=%d (%d sectors/cylinder)\n\n",
    778   1.1       cgd 	    dos_cylinders, dos_heads, dos_sectors, dos_cylindersectors);
    779   1.1       cgd }
    780   1.4   mycroft 
    781   1.1       cgd void
    782   1.4   mycroft change_active(which)
    783   1.1       cgd 	int which;
    784   1.4   mycroft {
    785   1.4   mycroft 	struct dos_partition *partp;
    786  1.15      phil 	int part;
    787   1.4   mycroft 	int active = 4;
    788   1.4   mycroft 
    789   1.1       cgd 	partp = &mboot.parts[0];
    790   1.1       cgd 
    791   1.1       cgd 	if (a_flag && which != -1)
    792   1.4   mycroft 		active = which;
    793   1.4   mycroft 	else {
    794   1.4   mycroft 		for (part = 0; part < NDOSPART; part++)
    795   1.4   mycroft 			if (partp[part].dp_flag & ACTIVE)
    796   1.4   mycroft 				active = part;
    797  1.15      phil 	}
    798  1.15      phil 	if (!f_flag) {
    799  1.15      phil 		if (yesno("Do you want to change the active partition?")) {
    800  1.15      phil 			printf ("Choosing 4 will make no partition active.\n");
    801  1.15      phil 			do {
    802  1.15      phil 				decimal("active partition", &active);
    803  1.15      phil 			} while (!yesno("Are you happy with this choice?"));
    804  1.15      phil 		} else
    805  1.15      phil 			return;
    806  1.15      phil 	} else
    807  1.15      phil 		if (active != 4)
    808  1.15      phil 			printf ("Making partition %d active.\n", active);
    809   1.4   mycroft 
    810   1.4   mycroft 	for (part = 0; part < NDOSPART; part++)
    811  1.15      phil 		partp[part].dp_flag &= ~ACTIVE;
    812  1.15      phil 	if (active < 4)
    813   1.1       cgd 		partp[active].dp_flag |= ACTIVE;
    814   1.1       cgd }
    815   1.4   mycroft 
    816   1.1       cgd void
    817   1.1       cgd get_params_to_use()
    818  1.16      phil {
    819  1.16      phil 	if (b_flag) {
    820  1.16      phil 		dos_cylinders = b_cyl;
    821  1.16      phil 		dos_heads = b_head;
    822  1.16      phil 		dos_sectors = b_sec;
    823  1.16      phil 		dos_cylindersectors = dos_heads * dos_sectors;
    824  1.16      phil 		return;
    825   1.4   mycroft 	}
    826   1.1       cgd 
    827   1.4   mycroft 	print_params();
    828   1.4   mycroft 	if (yesno("Do you want to change our idea of what BIOS thinks?")) {
    829   1.5   mycroft 		do {
    830   1.5   mycroft 			decimal("BIOS's idea of #cylinders", &dos_cylinders);
    831   1.5   mycroft 			decimal("BIOS's idea of #heads", &dos_heads);
    832   1.5   mycroft 			decimal("BIOS's idea of #sectors", &dos_sectors);
    833   1.1       cgd 			dos_cylindersectors = dos_heads * dos_sectors;
    834   1.4   mycroft 			print_params();
    835   1.1       cgd 		} while (!yesno("Are you happy with this choice?"));
    836   1.1       cgd 	}
    837   1.1       cgd }
    838   1.1       cgd 
    839   1.1       cgd /***********************************************\
    840   1.1       cgd * Change real numbers into strange dos numbers	*
    841   1.4   mycroft \***********************************************/
    842   1.5   mycroft void
    843   1.5   mycroft dos(sector, cylinderp, headp, sectorp)
    844   1.5   mycroft 	int sector;
    845   1.4   mycroft 	unsigned char *cylinderp, *headp, *sectorp;
    846   1.5   mycroft {
    847   1.4   mycroft 	int cylinder, head;
    848   1.5   mycroft 
    849  1.28        ws 	cylinder = sector / dos_cylindersectors;
    850   1.5   mycroft 
    851   1.4   mycroft 	sector -= cylinder * dos_cylindersectors;
    852   1.5   mycroft 
    853   1.5   mycroft 	head = sector / dos_sectors;
    854   1.4   mycroft 	sector -= head * dos_sectors;
    855  1.28        ws 
    856  1.28        ws 	if (cylinder >= MAXCYL)
    857   1.5   mycroft 		cylinder = MAXCYL - 1;
    858   1.5   mycroft 	*cylinderp = DOSCYL(cylinder);
    859   1.5   mycroft 	*headp = head;
    860   1.1       cgd 	*sectorp = DOSSECT(sector + 1, cylinder);
    861   1.1       cgd }
    862  1.28        ws 
    863  1.28        ws #if 0
    864  1.28        ws void
    865  1.28        ws checkcyl(cyl)
    866  1.28        ws 	int cyl;
    867  1.28        ws {
    868  1.28        ws 	if (cyl >= MAXCYL)
    869  1.28        ws 		warnx("partition start beyond BIOS limit");
    870  1.28        ws }
    871  1.28        ws #endif
    872   1.1       cgd 
    873   1.1       cgd int fd;
    874   1.4   mycroft 
    875   1.1       cgd int
    876   1.4   mycroft open_disk(u_flag)
    877   1.1       cgd 	int u_flag;
    878  1.18     lukem {
    879   1.4   mycroft 	static char namebuf[MAXPATHLEN + 1];
    880   1.1       cgd 	struct stat st;
    881  1.19     lukem 
    882  1.19     lukem 	fd = opendisk(disk, u_flag ? O_RDWR : O_RDONLY, namebuf,
    883  1.18     lukem 	    sizeof(namebuf), 0);
    884  1.18     lukem 	if (fd < 0) {
    885   1.4   mycroft 		warn("%s", namebuf);
    886   1.4   mycroft 		return (-1);
    887  1.18     lukem 	}
    888   1.4   mycroft 	disk = namebuf;
    889   1.4   mycroft 	if (fstat(fd, &st) == -1) {
    890   1.4   mycroft 		close(fd);
    891   1.4   mycroft 		warn("%s", disk);
    892   1.1       cgd 		return (-1);
    893   1.7   mycroft 	}
    894   1.4   mycroft 	if (!S_ISCHR(st.st_mode) && !S_ISREG(st.st_mode)) {
    895   1.7   mycroft 		close(fd);
    896   1.4   mycroft 		warnx("%s is not a character device or regular file", disk);
    897   1.1       cgd 		return (-1);
    898   1.4   mycroft 	}
    899   1.4   mycroft 	if (get_params() == -1) {
    900   1.4   mycroft 		close(fd);
    901   1.1       cgd 		return (-1);
    902   1.4   mycroft 	}
    903   1.1       cgd 	return (0);
    904   1.1       cgd }
    905   1.4   mycroft 
    906   1.1       cgd int
    907   1.4   mycroft read_disk(sector, buf)
    908   1.4   mycroft 	int sector;
    909   1.1       cgd 	void *buf;
    910   1.4   mycroft {
    911   1.4   mycroft 
    912   1.4   mycroft 	if (lseek(fd, (off_t)(sector * 512), 0) == -1)
    913   1.4   mycroft 		return (-1);
    914   1.1       cgd 	return (read(fd, buf, 512));
    915   1.1       cgd }
    916   1.4   mycroft 
    917   1.1       cgd int
    918   1.4   mycroft write_disk(sector, buf)
    919   1.4   mycroft 	int sector;
    920   1.1       cgd 	void *buf;
    921   1.4   mycroft {
    922   1.4   mycroft 
    923   1.4   mycroft 	if (lseek(fd, (off_t)(sector * 512), 0) == -1)
    924   1.4   mycroft 		return (-1);
    925   1.1       cgd 	return (write(fd, buf, 512));
    926   1.1       cgd }
    927   1.4   mycroft 
    928   1.4   mycroft int
    929   1.1       cgd get_params()
    930   1.1       cgd {
    931   1.4   mycroft 
    932   1.4   mycroft 	if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
    933   1.4   mycroft 		warn("DIOCGDINFO");
    934   1.4   mycroft 		return (-1);
    935   1.1       cgd 	}
    936   1.5   mycroft 
    937   1.4   mycroft 	dos_cylinders = cylinders = disklabel.d_ncylinders;
    938   1.4   mycroft 	dos_heads = heads = disklabel.d_ntracks;
    939   1.5   mycroft 	dos_sectors = sectors = disklabel.d_nsectors;
    940   1.5   mycroft 	dos_cylindersectors = cylindersectors = heads * sectors;
    941   1.1       cgd 	disksectors = cylinders * heads * sectors;
    942   1.4   mycroft 
    943   1.1       cgd 	return (0);
    944   1.1       cgd }
    945   1.4   mycroft 
    946   1.1       cgd int
    947   1.1       cgd read_s0()
    948   1.4   mycroft {
    949   1.4   mycroft 
    950   1.4   mycroft 	if (read_disk(0, mboot.bootinst) == -1) {
    951   1.4   mycroft 		warn("can't read fdisk partition table");
    952   1.1       cgd 		return (-1);
    953  1.12   thorpej 	}
    954  1.12   thorpej 	if (getshort(&mboot.signature) != BOOT_MAGIC) {
    955   1.4   mycroft 		warnx("invalid fdisk partition table found");
    956   1.1       cgd 		return (-1);
    957   1.4   mycroft 	}
    958   1.1       cgd 	return (0);
    959   1.1       cgd }
    960   1.4   mycroft 
    961   1.1       cgd int
    962   1.1       cgd write_s0()
    963   1.4   mycroft {
    964   1.4   mycroft 	int flag;
    965   1.1       cgd 
    966   1.1       cgd 	/*
    967   1.1       cgd 	 * write enable label sector before write (if necessary),
    968   1.1       cgd 	 * disable after writing.
    969   1.1       cgd 	 * needed if the disklabel protected area also protects
    970   1.1       cgd 	 * sector 0. (e.g. empty disk)
    971   1.1       cgd 	 */
    972   1.1       cgd 	flag = 1;
    973   1.4   mycroft 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
    974   1.4   mycroft 		warn("DIOCWLABEL");
    975   1.4   mycroft 	if (write_disk(0, mboot.bootinst) == -1) {
    976   1.1       cgd 		warn("can't write fdisk partition table");
    977   1.4   mycroft 		return -1;
    978   1.1       cgd 	}
    979   1.4   mycroft 	flag = 0;
    980   1.4   mycroft 	if (ioctl(fd, DIOCWLABEL, &flag) < 0)
    981  1.16      phil 		warn("DIOCWLABEL");
    982   1.1       cgd 	return 0;
    983   1.1       cgd }
    984   1.4   mycroft 
    985   1.4   mycroft int
    986   1.4   mycroft yesno(str)
    987   1.4   mycroft 	char *str;
    988   1.4   mycroft {
    989   1.1       cgd 	int ch, first;
    990   1.1       cgd 
    991   1.1       cgd 	printf("%s [n] ", str);
    992   1.4   mycroft 
    993   1.4   mycroft 	first = ch = getchar();
    994   1.4   mycroft 	while (ch != '\n' && ch != EOF)
    995   1.4   mycroft 		ch = getchar();
    996   1.1       cgd 	return (first == 'y' || first == 'Y');
    997   1.1       cgd }
    998   1.5   mycroft 
    999   1.5   mycroft void
   1000   1.4   mycroft decimal(str, num)
   1001   1.5   mycroft 	char *str;
   1002   1.1       cgd 	int *num;
   1003   1.8       cgd {
   1004   1.4   mycroft 	int acc = 0;
   1005   1.1       cgd 	char *cp;
   1006   1.5   mycroft 
   1007   1.5   mycroft 	for (;; printf("%s is not a valid decimal number.\n", lbuf)) {
   1008   1.1       cgd 		printf("Supply a decimal value for \"%s\" [%d] ", str, *num);
   1009   1.1       cgd 
   1010   1.7   mycroft 		fgets(lbuf, LBUF, stdin);
   1011   1.7   mycroft 		lbuf[strlen(lbuf)-1] = '\0';
   1012   1.7   mycroft 		cp = lbuf;
   1013   1.7   mycroft 
   1014   1.7   mycroft 		cp += strspn(cp, " \t");
   1015   1.5   mycroft 		if (*cp == '\0')
   1016   1.1       cgd 			return;
   1017   1.7   mycroft 
   1018   1.7   mycroft 		if (!isdigit(*cp))
   1019   1.5   mycroft 			continue;
   1020   1.7   mycroft 		acc = strtol(lbuf, &cp, 10);
   1021   1.5   mycroft 
   1022   1.5   mycroft 		cp += strspn(cp, " \t");
   1023   1.5   mycroft 		if (*cp != '\0')
   1024   1.1       cgd 			continue;
   1025   1.5   mycroft 
   1026   1.5   mycroft 		*num = acc;
   1027   1.1       cgd 		return;
   1028   1.1       cgd 	}
   1029   1.1       cgd 
   1030   1.1       cgd }
   1031   1.4   mycroft 
   1032   1.4   mycroft int
   1033   1.4   mycroft type_match(key, item)
   1034   1.4   mycroft 	const void *key, *item;
   1035   1.4   mycroft {
   1036   1.4   mycroft 	const int *typep = key;
   1037   1.4   mycroft 	const struct part_type *ptr = item;
   1038   1.4   mycroft 
   1039   1.4   mycroft 	if (*typep < ptr->type)
   1040   1.4   mycroft 		return (-1);
   1041   1.4   mycroft 	if (*typep > ptr->type)
   1042   1.4   mycroft 		return (1);
   1043   1.4   mycroft 	return (0);
   1044   1.4   mycroft }
   1045   1.4   mycroft 
   1046   1.4   mycroft char *
   1047   1.4   mycroft get_type(type)
   1048   1.4   mycroft 	int type;
   1049   1.4   mycroft {
   1050   1.4   mycroft 	struct part_type *ptr;
   1051   1.4   mycroft 
   1052   1.4   mycroft 	ptr = bsearch(&type, part_types,
   1053   1.4   mycroft 	    sizeof(part_types) / sizeof(struct part_type),
   1054   1.4   mycroft 	    sizeof(struct part_type), type_match);
   1055   1.4   mycroft 	if (ptr == 0)
   1056  1.16      phil 		return ("unknown");
   1057   1.1       cgd 	return (ptr->name);
   1058                 }
   1059