*BSD News Article 6618


Return to BSD News archive

Newsgroups: comp.unix.bsd
Path: sserve!manuel.anu.edu.au!munnari.oz.au!uunet!think.com!ames!agate!tfs.com!tfs.com!julian
From: julian@tfs.com (Julian Elischer)
Subject: sources and manpage for FDISK for 386bsd.
Message-ID: <1992Oct16.035143.2141@tfs.com>
Organization: TRW Financial Systems
Date: Fri, 16 Oct 1992 03:51:43 GMT
Lines: 976

Hopefully this program will take some of the sweat out of partitioning
up disks for 386bsd and other operating systems.

This fdisk program is derived from part of the MACH 'diskutil' program

It differs from that program's fdisk phase in the following ways:

1/ it allows the user to specify the geometry with which the BIOS
 sector cylinder calculations are to be made with.

2/ When the user elects to manually over-ride the calculated values,
it allows the user to enter full track/cylinder/sector numbers
and internally translates them to BIOS format rather than
making the user do the translation on a piece of scrap paper
(the usual method)

3/ obviously, by default it produces a 386bsd partition rather than 
a mach partition

4/ when printing the partitions, it prints out the actual name
of the o/s that owns that partition, as well as the number.
(it it knows that o/s.. it has an internal table)


# This is a shell archive.  Save it in a file, remove anything before
# this line, and then unpack it by entering "sh file".  Note, it may
# create directories; files and directories will be owned by you and
# have default permissions.
#
# This archive contains:
#
#	Makefile
#	fdisk.0
#	fdisk.c
#
echo x - Makefile
sed 's/^X//' >Makefile << 'END-of-Makefile'
X#
X#CFLAGS=	-O
XCFLAGS=	-g
XLIBC=	/lib/libc.a
XSRCS=fdisk.c 
XALL= fdisk
X
Xall: ${ALL}
X
Xfdisk: fdisk.c
X	cc ${CLFLGS} -o fdisk fdisk.c
X
Xclean: FRC
X	rm -f ${ALL} ${OBJS} core
X
Xdepend: ${SRCS} FRC
X	mkdep ${CFLAGS} ${SRCS}
X
Xinstall: FRC
X	install -c -s -o bin -g bin -m 755 fdisk ${DESTDIR}/sbin
X	install -c -o bin -g bin -m 444 fdisk.0 ${DESTDIR}/usr/share/man/cat8
X
Xlint: ${SRCS} FRC
X	lint ${CFLAGS} ${SRCS}
X
Xtags: ${SRCS} FRC
X	ctags ${SRCS}
X
XFRC:
X
X# DO NOT DELETE THIS LINE -- mkdep uses it.
X# DO NOT PUT ANYTHING AFTER THIS LINE, IT WILL GO AWAY.
END-of-Makefile
echo x - fdisk.0
sed 's/^X//' >fdisk.0 << 'END-of-fdisk.0'
X
X
X
XFDISK(8)	    UNIX Programmer's Manual		 FDISK(8)
X
X
X
XNNAAMMEE
X     fdisk - DOS partition maintainance program
X
XSSYYNNOOPPSSIISS
X     ffddiisskk [ -_i_u ]
X
XPPRROOLLOOGGUUEE
X     In order for BIOS to boot the kernel, certain conventions
X     must be adhered to.  Sector 0 of the disk must contain boot
X     code, a partition table, and a magic number.  BIOS parti-
X     tions can be used to break the disk up into several pieces.
X     BIOS brings in sector 0 (does it really use the code?) and
X     verifies the magic number.  It then searches the 4 BIOS par-
X     titions described by sector 0 to determine which of them is
X     _a_c_t_i_v_e.  This boot then brings in the secondary boot block
X     from the _a_c_t_i_v_e partition and runs it.  Under DOS, you could
X     have one or more partitions with one _a_c_t_i_v_e.  The DOS ffddiisskk
X     program can be used to divide space on the disk into parti-
X     tions and set one _a_c_t_i_v_e.
X
XDDEESSCCRRIIPPTTIIOONN
X     The 386bsd program ffddiisskk serves a similar purpose to the DOS
X     program.  When called with no arguments, it prints the sec-
X     tor 0 partition table.  An example follows:
X	
X
X		******* Working on device /dev/rwd0d *******
X		parameters extracted from in-core disklabel are:
X		cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
X		
X		parameters to be used for BIOS calculations are:
X		cylinders=769 heads=15 sectors/track=33 (495 blks/cyl)
X		
X		Warning: BIOS sector numbering starts with sector 1
X		Information from DOS bootblock is:
X		The data for partition 0 is:
X		sysid 165,(386BSD)
X    		    start 495, size 380160 (185 Meg), flag 0
X			beg: cyl 1/ sector 1/ head 0;
X			end: cyl 768/ sector 33/ head 14
X		The data for partition 1 is:
X		sysid 164,(unknown)
X    		    start 378180, size 2475 (1 Meg), flag 0
X			beg: cyl 764/ sector 1/ head 0;
X			end: cyl 768/ sector 33/ head 14
X		The data for partition 2 is:
X		<UNUSED>
X		The data for partition 3 is:
X		sysid 99,(ISC UNIX, other System V/386, GNU HURD or Mach)
X    		    start 380656, size 224234 (109 Meg), flag 80
X			beg: cyl 769/ sector 2/ head 0;
X			end: cyl 197/ sector 33/ head 14
X
X
X
X     The disk is divided into three parititions that happen to fill
X     the disk. The second partition overlaps the  end of the first.
X     (Used for debugging purposes)
X
XPrinted 2/12/90               local				1
X
X
X
X
X
X
XFDISK(8)	    UNIX Programmer's Manual		 FDISK(8)
X
X
X
X
X
X     _s_t_a_r_t and _s_i_z_e
X	  fields provide the start address and size of a parition
X	  in sectors.
X
X     _b_o_o_t_i_d _8_0
X	  specifies that this is the active partition.
X
X     _s_y_s_i_d
X	  is used to label the partition.  386bsd reserves the
X	  magic number 165 decimal (A5 in hex).
X
X     _c_y_l, _s_e_c_t_o_r, and _h_e_a_d
X	  fields are used to specify the beginning address 
X	  and end address for the parititon.
X	   Note:
X	  these numbers are calculated using BIOS's understanding of
X	  the disk geometry and saved in the bootblock.
X
X     The flags _i or _u are used to indicate that the paritition
X     data is to be updated.  The ffddiisskk program will enter a
X     conversational mode.  This mode is designed not to change
X     any data unless you explicitly tell it to.  ffddiisskk selects
X     defaults for its questions to guarantee the above behaviour.
X
X     It displays each partition and ask if you want to edit it.
X     If you say yes, it will step through each field showing the
X     old value and asking for a new one.  When you are done with
X     a partition, ddiisskk will display it and ask if it is correct.
X     ddiisskk will then procede to the next entry.
X
X	  Getting the _c_y_l, _s_e_c_t_o_r, and _h_e_a_d fields correct is
X	  tricky.  So by default, they will be calculated for
X	  you; you can specify them if you choose.
X
X     After all the partitions are processed, you are given the
X     option to change the _a_c_t_i_v_e partition.  Finally, when the
X     all the data for the first sector has been accumulated,  you
X     are asked if you really want to rewrite sector 0.	Only if
X     you answer yes, will the data be written to disk.
X
X	  The difference between the _u flag and _i flag is that
X	  the _u flag just edits the fields as they appear on the
X	  disk.  While the _i flag is used to "initialize" sector
X	  0;  it will setup the last BIOS partition to use the
X	  whole disk for 386bsd; and make it active.
X
X
X
X
XPrinted 2/12/90               local				2
X
X
X
X
X
X
XFDISK(8)	    UNIX Programmer's Manual		 FDISK(8)
X
X
X
XNNOOTTEESS
X	The automatic calculation of starting cylinder etc. uses
X	a set of figures that represent what the BIOS thinks is the
X	geometry of the drive. These figures are by default taken
X	from the incore disklabel, but the program initially gives you
X	an oportunity to change them. This allows the user
X	to create a bootblock that can work with drives
X	that use geometry translation under the BIOS.
X
X     If you hand craft your disk layout, please make sure that the
X     386bsd partition starts on a cylinder boundary.  A number of
X     decisions made later may assume this.	(This might not be neces-
X     sary later.)
X
X     Editing an existing partition will most likely cause you to
X     lose all the data in that partition.
X
X     You should run this program interactively once or twice to
X     see how it works.	This is completely safe as long as you
X     answer the last question in the negative.	There are
X     subtleties that the program detects that are not fully
X     explained in this manual page.
X
XSSEEEE AALLSSOO
X     ddiisskkllaabbeell ((88))
X
XBBUUGGSS
X     probably
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
X
XPrinted 2/12/90               local				3
X
X
X
END-of-fdisk.0
echo x - fdisk.c
sed 's/^X//' >fdisk.c << 'END-of-fdisk.c'
X/* 
X * Mach Operating System
X * Copyright (c) 1992 Carnegie Mellon University
X * All Rights Reserved.
X * 
X * Permission to use, copy, modify and distribute this software and its
X * documentation is hereby granted, provided that both the copyright
X * notice and this permission notice appear in all copies of the
X * software, derivative works or modified versions, and any portions
X * thereof, and that both notices appear in supporting documentation.
X * 
X * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
X * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
X * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
X * 
X * Carnegie Mellon requests users of this software to return to
X * 
X *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
X *  School of Computer Science
X *  Carnegie Mellon University
X *  Pittsburgh PA 15213-3890
X * 
X * any improvements or extensions that they make and grant Carnegie Mellon
X * the rights to redistribute these changes.
X */
X
X#include <sys/types.h>
X#include <sys/disklabel.h>
X#include <stdio.h>
X#include <sys/stat.h>
X#include <sys/ioctl.h>
X#include <fcntl.h>
X
Xint iotest;
X
X#define LBUF 100
Xstatic char lbuf[LBUF];
X
X/*
X *
X * Ported to 386bsd by Julian Elischer  Thu Oct 15 20:26:46 PDT 1992
X *
X * 14-Dec-89  Robert Baron (rvb) at Carnegie-Mellon University
X *	Copyright (c) 1989	Robert. V. Baron
X *	Created.
X */
X
X#define Decimal(str, ans, tmp) if (decimal(str, &tmp, ans)) ans = tmp
X#define Hex(str, ans, tmp) if (hex(str, &tmp, ans)) ans = tmp
X#define String(str, ans, len) {char *z = ans; char **dflt = &z; if (string(str, dflt)) strncpy(ans, *dflt, len); }
X
X#define RoundCyl(x) ((((x) + cylsecs - 1) / cylsecs) * cylsecs)
X
X#define SECSIZE 512
X
Xchar *disk = "/dev/rwd0d";
Xchar *name;
X
Xstruct disklabel disklabel;		/* disk parameters */
X
Xint cyls, sectors, heads, cylsecs, disksecs;
X
Xstruct mboot
X{
X	unsigned char padding[2]; /* force the longs to be long alligned */
X	unsigned char bootinst[DOSPARTOFF];
X	struct	dos_partition parts[4];
X	unsigned short int	signature;
X};
Xstruct mboot mboot;
X
X#define ACTIVE 0x80
X#define BOOT_MAGIC 0xAA55
X
Xint dos_cyls;
Xint dos_heads;
Xint dos_sectors;
Xint dos_cylsecs;
X
X#define DOSSECT(s,c) ((s & 0x3f) | ((c >> 2) & 0xc0))
X#define DOSCYL(c)	(c & 0xff)
Xstatic int dos();
Xchar *get_type();
Xstatic int partition = -1;
X
X
Xstatic int a_flag  = 0;		/* set active partition */
Xstatic int i_flag  = 0;		/* replace partition data */
Xstatic int u_flag  = 0;		/* update partition data */
X
Xstatic unsigned char bootcode[] = {
X0x33, 0xc0, 0xfa, 0x8e, 0xd0, 0xbc, 0x00, 0x7c, 0x8e, 0xc0, 0x8e, 0xd8, 0xfb, 0x8b, 0xf4, 0xbf, 
X0x00, 0x06, 0xb9, 0x00, 0x02, 0xfc, 0xf3, 0xa4, 0xea, 0x1d, 0x06, 0x00, 0x00, 0xb0, 0x04, 0xbe, 
X0xbe, 0x07, 0x80, 0x3c, 0x80, 0x74, 0x0c, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x75, 0xf4, 0xbe, 0xbd, 
X0x06, 0xeb, 0x43, 0x8b, 0xfe, 0x8b, 0x14, 0x8b, 0x4c, 0x02, 0x83, 0xc6, 0x10, 0xfe, 0xc8, 0x74, 
X0x0a, 0x80, 0x3c, 0x80, 0x75, 0xf4, 0xbe, 0xbd, 0x06, 0xeb, 0x2b, 0xbd, 0x05, 0x00, 0xbb, 0x00, 
X0x7c, 0xb8, 0x01, 0x02, 0xcd, 0x13, 0x73, 0x0c, 0x33, 0xc0, 0xcd, 0x13, 0x4d, 0x75, 0xef, 0xbe, 
X0x9e, 0x06, 0xeb, 0x12, 0x81, 0x3e, 0xfe, 0x7d, 0x55, 0xaa, 0x75, 0x07, 0x8b, 0xf7, 0xea, 0x00, 
X0x7c, 0x00, 0x00, 0xbe, 0x85, 0x06, 0x2e, 0xac, 0x0a, 0xc0, 0x74, 0x06, 0xb4, 0x0e, 0xcd, 0x10, 
X0xeb, 0xf4, 0xfb, 0xeb, 0xfe,
X'M', 'i', 's', 's', 'i', 'n', 'g', ' ',
X	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
X'E', 'r', 'r', 'o', 'r', ' ', 'l', 'o', 'a', 'd', 'i', 'n', 'g', ' ', 
X	'o', 'p', 'e', 'r', 'a', 't', 'i', 'n', 'g', ' ', 's', 'y', 's', 't', 'e', 'm', 0,
X'I', 'n', 'v', 'a', 'l', 'i', 'd', ' ',
X	'p', 'a', 'r', 't', 'i', 't', 'i', 'o', 'n', ' ', 't', 'a', 'b', 'l', 'e', 0,
X'A', 'u', 't', 'h', 'o', 'r', ' ', '-', ' ',
X	'S', 'i', 'e', 'g', 'm', 'a', 'r', ' ', 'S', 'c', 'h', 'm', 'i', 'd', 't', 0,0,0, 
X
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0, 
X  0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0,   0 
X};
X
Xstruct part_type
X{
X unsigned char type;
X char *name;
X}part_types[] =
X{
X	 {0x00, "unused"}   
X	,{0x01, "Primary DOS with 12 bit FAT"}   
X	,{0x02, "XENIX / filesystem"}  
X	,{0x03, "XENIX /usr filesystem"}  
X	,{0x04, "Primary DOS with 16 bit FAT"}   
X	,{0x05, "Extended DOS"}   
X	,{0x06, "Primary 'big' DOS (> 32MB)"}   
X	,{0x07, "OS/2 HPFS, QNX or Advanced UNIX"}  
X	,{0x08, "AIX filesystem"}   
X	,{0x09, "AIX boot partition or Coherent"}  
X	,{0x0A, "OS/2 Boot Manager or OPUS"}  
X	,{0x10, "OPUS"}   
X	,{0x40, "VENIX 286"}  
X	,{0x50, "DM"}   
X	,{0x51, "DM"}   
X	,{0x52, "CP/M or Microport SysV/AT"}  
X	,{0x56, "GB"}   
X	,{0x61, "Speed"}   
X	,{0x63, "ISC UNIX, other System V/386, GNU HURD or Mach"}  
X	,{0x64, "Novell Netware 2.xx"}      
X	,{0x65, "Novell Netware 3.xx"} 
X	,{0x75, "PCIX"}  
X	,{0x80, "Minix 1.1 ... 1.4a"} 
X	,{0x81, "Minix 1.4b ... 1.5.10"}   
X	,{0x82, "Linux"}   
X	,{0x93, "Amoeba filesystem"} 
X	,{0x94, "Amoeba bad block table"} 
X	,{0xA5, "386BSD"} 
X	,{0xB7, "BSDI BSD/386 filesystem"} 
X	,{0xB8, "BSDI BSD/386 swap"} 
X	,{0xDB, "Concurrent CPM or C.DOS or CTOS"}  
X	,{0xE1, "Speed"}   
X	,{0xE3, "Speed"}   
X	,{0xE4, "Speed"}   
X	,{0xF1, "Speed"}   
X	,{0xF2, "DOS 3.3+ Secondary"}   
X	,{0xF4, "Speed"}   
X	,{0xFF, "BBT (Bad Blocks Table)"}  
X};
X
X
Xmain(argc, argv)
Xchar **argv;
X{
Xint	i;
X
X	name = *argv;
X	{register char *cp = name;
X		while (*cp) if (*cp++ == '/') name = cp;
X	}
X
X	for ( argv++ ; --argc ; argv++ ) { register char *token = *argv;
X		if (*token++ != '-' || !*token)
X			break;
X		else { register int flag;
X			for ( ; flag = *token++ ; ) {
X				switch (flag) {
X				case '0':
X					partition = 0;
X					break;
X				case '1':
X					partition = 1;
X					break;
X				case '2':
X					partition = 2;
X					break;
X				case '3':
X					partition = 3;
X					break;
X				case 'a':
X					a_flag = 1;
X					break;
X				case 'i':
X					i_flag = 1;
X				case 'u':
X					u_flag = 1;
X					break;
X				default:
X					goto usage;
X				}
X			}
X		}
X	}
X
X	if (argc > 0)
X		disk = argv[0];
X	
X	if (open_disk(u_flag) < 0)
X		exit(1);
X
X	printf("******* Working on device %s *******\n",disk);
X	if(u_flag)
X	{
X		get_params_to_use();
X	}
X	else
X	{
X		print_params();
X	}
X
X	if (read_s0())
X		init_sector0(1);
X
X	printf("Warning: BIOS sector numbering starts with sector 1\n");
X	printf("Information from DOS bootblock is:\n");
X	if (partition == -1)
X		for (i = 0; i < NDOSPART; i++)
X			change_part(i);
X	else
X		change_part(partition);
X
X	if (u_flag || a_flag)
X		change_active(partition);
X
X	if (u_flag || a_flag) {
X		printf("\nWe haven't changed the partition table yet.  ");
X		printf("This is your last chance.\n");
X		print_s0(-1);
X		if (ok("Should we write new partition table?"))
X			write_s0();
X	}
X
X	exit(0);
X
Xusage:
X	printf("fdisk {-a|-i|-r} {disk}\n");
X}
X
Xprint_s0(which)
X{
Xint	i;
X
X	print_params();
X	printf("Information from DOS bootblock is:\n");
X	if (which == -1)
X		for (i = 0; i < NDOSPART; i++)
X			printf("%d: ", i), print_part(i);
X	else
X		print_part(which);
X}
X
Xstatic struct dos_partition mtpart = { 0 };
X
Xprint_part(i)
X{
Xstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
X
X
X	if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
X		printf("<UNUSED>\n");
X		return;
X	}
X	printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
X	printf("    start %d, size %d (%d Meg), flag %x\n",
X		partp->dp_start,
X		partp->dp_size, partp->dp_size * 512 / (1024 * 1024),
X		partp->dp_flag);
X	printf("\tbeg: cyl %d/ sector %d/ head %d;\n\tend: cyl %d/ sector %d/ head %d\n"
X		,DPCYL(partp->dp_scyl, partp->dp_ssect)
X		,DPSECT(partp->dp_ssect)
X		,partp->dp_shd
X		,DPCYL(partp->dp_ecyl, partp->dp_esect)
X		,DPSECT(partp->dp_esect)
X		,partp->dp_ehd);
X}
X
Xinit_sector0(start)
X{
Xstruct dos_partition *partp = (struct dos_partition *) (&mboot.parts[3]);
Xint size = disksecs - start;
Xint rest;
X
X	memcpy(mboot.bootinst, bootcode, sizeof(bootcode)); 
X	mboot.signature = BOOT_MAGIC;
X
X	partp->dp_typ = DOSPTYP_386BSD;
X	partp->dp_flag = ACTIVE;
X	partp->dp_start = start;
X	partp->dp_size = size;
X
X	dos(partp->dp_start, &partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
X	dos(partp->dp_start+partp->dp_size, &partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
X}
X
Xchange_part(i)
X{
Xstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts) + i;
X
X    printf("The data for partition %d is:\n", i);
X    print_part(i);
X
X    if (u_flag && ok("Do you want to change it?")) {
X	int tmp;
X
X	if (i_flag) {
X		bzero((char *)partp, sizeof (struct dos_partition));
X		if (i == 3) {
X			init_sector0(1);
X			printf("\nThe static data for the DOS partition 3 has been reinitialized to:\n");
X			print_part(i);
X		}
X	}
X
X	do {
X		Decimal("sysid", partp->dp_typ, tmp);
X		Decimal("start", partp->dp_start, tmp);
X		Decimal("size", partp->dp_size, tmp);
X
X		if (ok("Explicitly specifiy beg/end address ?"))
X		{
X			int	tsec,tcyl,thd;
X			tcyl = DPCYL(partp->dp_scyl,partp->dp_ssect);
X			thd = partp->dp_shd;
X			tsec = DPSECT(partp->dp_ssect);
X			Decimal("beginning cylinder", tcyl, tmp);
X			Decimal("beginning head", thd, tmp);
X			Decimal("beginning sector", tsec, tmp);
X			partp->dp_scyl = DOSCYL(tcyl);
X			partp->dp_ssect = DOSSECT(tsec,tcyl);
X			partp->dp_shd = thd;
X
X			tcyl = DPCYL(partp->dp_ecyl,partp->dp_esect);
X			thd = partp->dp_ehd;
X			tsec = DPSECT(partp->dp_esect);
X			Decimal("ending cylinder", tcyl, tmp);
X			Decimal("ending head", thd, tmp);
X			Decimal("ending sector", tsec, tmp);
X			partp->dp_ecyl = DOSCYL(tcyl);
X			partp->dp_esect = DOSSECT(tsec,tcyl);
X			partp->dp_ehd = thd;
X		} else {
X			dos(partp->dp_start,
X				&partp->dp_scyl, &partp->dp_ssect, &partp->dp_shd);
X			dos(partp->dp_start+partp->dp_size - 1,
X				&partp->dp_ecyl, &partp->dp_esect, &partp->dp_ehd);
X		}
X	    
X		print_part(i);
X	} while (!ok("Are we happy with this entry?"));
X    }
X}
X
Xprint_params()
X{
X	printf("parameters extracted from in-core disklabel are:\n");
X	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
X			,cyls,heads,sectors,cylsecs);
X	if((dos_sectors > 63) || (dos_cyls > 1023) || (dos_heads > 255))
X		printf(" Figures below won't work with BIOS for partitions not in cyl 1\n");
X	printf("parameters to be used for BIOS calculations are:\n");
X	printf("cylinders=%d heads=%d sectors/track=%d (%d blks/cyl)\n\n"
X		,dos_cyls,dos_heads,dos_sectors,dos_cylsecs);
X}
X
Xchange_active(which)
X{
Xint i;
Xint active = 3, tmp;
Xstruct dos_partition *partp = ((struct dos_partition *) &mboot.parts);
X
X	if (a_flag && which != -1)
X		active = which;
X	if (ok("Do you want to change the active partition?")) {
X		do
X			Decimal("active partition", active, tmp);
X		while(!ok("Are you happy with this choice"));
X	}
X	for (i = 0; i < NDOSPART; i++)
X		partp[i].dp_flag = 0;
X	partp[active].dp_flag = ACTIVE;
X}
X
Xget_params_to_use()
X{
X	int	tmp;
X	print_params();
X	if (ok("Do you want to change our idea of what BIOS thinks ?"))
X	{
X		do
X		{
X			Decimal("BIOS's idea of #cylinders", dos_cyls, tmp);
X			Decimal("BIOS's idea of #heads", dos_heads, tmp);
X			Decimal("BIOS's idea of #sectors", dos_sectors, tmp);
X			dos_cylsecs = dos_heads * dos_sectors;
X			print_params();
X		}
X		while(!ok("Are you happy with this choice"));
X	}
X}
X
X/***********************************************\
X* Change real numbers into strange dos numbers	*
X\***********************************************/
Xstatic
Xdos(sec, c, s, h)
Xint sec;
Xunsigned char *c, *s, *h;
X{
Xint cy;
Xint hd;
X
X	cy = sec / ( dos_cylsecs );
X	sec = sec - cy * ( dos_cylsecs );
X
X	hd = sec / dos_sectors;
X	sec = (sec - hd * dos_sectors) + 1;
X
X	*h = hd;
X	*c = cy & 0xff;
X	*s = (sec & 0x3f) | ( (cy & 0x300) >> 2);
X}
X
Xint fd;
X
X	/* Getting device status */
X
Xopen_disk(u_flag)
X{
Xstruct stat 	st;
X
X	if (stat(disk, &st) == -1) {		
X		fprintf(stderr, "%s: Can't get file status of %s\n",
X			name, disk);
X		return -1;
X	} else if ( !(st.st_mode & S_IFCHR) ) {
X		fprintf(stderr,"%s: Device %s is not character special\n",
X			name, disk);
X		return -1;
X	}
X	if ((fd = open(disk, u_flag?O_RDWR:O_RDONLY)) == -1) {
X		fprintf(stderr,"%s: Can't open device %s\n", name, disk);
X		return -1;
X	}
X	if (get_params(0) == -1) {
X		fprintf(stderr, "%s: Can't get disk parameters on %s\n",
X			name, disk);
X		return -1;
X	}
X	return fd;
X}
X
X
Xread_disk(sector, buf)
X{
X	lseek(fd,(sector * 512), 0);
X	return read(fd, buf, 512);
X}
X
Xwrite_disk(sector, buf)
X{
X	lseek(fd,(sector * 512), 0);
X	return write(fd, buf, 512);
X}
X
Xget_params(verbose)
X{
X
X    if (ioctl(fd, DIOCGDINFO, &disklabel) == -1) {
X	return -1;
X    }
X
X    dos_cyls = cyls = disklabel.d_ncylinders;
X    dos_heads = heads = disklabel.d_ntracks;
X    dos_sectors = sectors = disklabel.d_nsectors;
X    dos_cylsecs = cylsecs = heads * sectors;
X    disksecs = cyls * heads * sectors;
X
X    return (disksecs);
X}
X
X
Xread_s0()
X{
X	if (read_disk(0, (char *) mboot.bootinst) == -1) { 
X		fprintf(stderr, "%s: Can't read fdisk partition table\n", name);
X		return -1;
X	}
X	if (mboot.signature != BOOT_MAGIC) {
X		fprintf(stderr, "%s: Invalid fdisk partition table found\n",
X			name);
X		/* So should we initialize things */
X		return -1;
X	}
X	return 0;
X}
X
Xwrite_s0()
X{
X	if (iotest) {
X		print_s0(-1);
X		return 0;
X	}
X	if (write_disk(0, (char *) mboot.bootinst) == -1) { 
X		fprintf(stderr, "%s: Can't write fdisk partition table\n",
X			name);
X		return -1;
X	}
X}
X
X
X
Xok(str)
Xchar *str;
X{
X	printf("%s [n] ", str);
X	fgets(lbuf, LBUF, stdin);
X	lbuf[strlen(lbuf)-1] = 0;
X
X	if (*lbuf &&
X		(!strcmp(lbuf, "yes") || !strcmp(lbuf, "YES") ||
X		 !strcmp(lbuf, "y") || !strcmp(lbuf, "Y")))
X		return 1;
X	else
X		return 0;
X}
X
Xdecimal(str, num, deflt)
Xchar *str;
Xint *num;
X{
Xint acc = 0, c;
Xchar *cp;
X
X	while (1) {
X		printf("Supply a decimal value for \"%s\" [%d] ", str, deflt);
X		fgets(lbuf, LBUF, stdin);
X		lbuf[strlen(lbuf)-1] = 0;
X
X		if (!*lbuf)
X			return 0;
X
X		cp = lbuf;
X		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
X		if (!c)
X			return 0;
X		while (c = *cp++) {
X			if (c <= '9' && c >= '0')
X				acc = acc * 10 + c - '0';
X			else
X				break;
X		}
X		if (c == ' ' || c == '\t')
X			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
X		if (!c) {
X			*num = acc;
X			return 1;
X		} else
X			printf("%s is an invalid decimal number.  Try again\n",
X				lbuf);
X	}
X
X}
X
Xhex(str, num, deflt)
Xchar *str;
Xint *num;
X{
Xint acc = 0, c;
Xchar *cp;
X
X	while (1) {
X		printf("Supply a hex value for \"%s\" [%x] ", str, deflt);
X		fgets(lbuf, LBUF, stdin);
X		lbuf[strlen(lbuf)-1] = 0;
X
X		if (!*lbuf)
X			return 0;
X
X		cp = lbuf;
X		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
X		if (!c)
X			return 0;
X		while (c = *cp++) {
X			if (c <= '9' && c >= '0')
X				acc = (acc << 4) + c - '0';
X			else if (c <= 'f' && c >= 'a')
X				acc = (acc << 4) + c - 'a' + 10;
X			else if (c <= 'F' && c >= 'A')
X				acc = (acc << 4) + c - 'A' + 10;
X			else
X				break;
X		}
X		if (c == ' ' || c == '\t')
X			while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
X		if (!c) {
X			*num = acc;
X			return 1;
X		} else
X			printf("%s is an invalid hex number.  Try again\n",
X				lbuf);
X	}
X
X}
X
Xstring(str, ans)
Xchar *str;
Xchar **ans;
X{
Xint c;
Xchar *cp = lbuf;
X
X	while (1) {
X		printf("Supply a string value for \"%s\" [%s] ", str, *ans);
X		fgets(lbuf, LBUF, stdin);
X		lbuf[strlen(lbuf)-1] = 0;
X
X		if (!*lbuf)
X			return 0;
X
X		while ((c = *cp) && (c == ' ' || c == '\t')) cp++;
X		if (c == '"') {
X			c = *++cp;
X			*ans = cp;
X			while ((c = *cp) && c != '"') cp++;
X		} else {
X			*ans = cp;
X			while ((c = *cp) && c != ' ' && c != '\t') cp++;
X		}
X
X		if (c)
X			*cp = 0;
X		return 1;
X	}
X}
X
Xchar *get_type(type)
Xint	type;
X{
X	int	numentries = (sizeof(part_types)/sizeof(struct part_type));
X	int	counter = 0;
X	struct	part_type *ptr = part_types;
X
X	
X	while(counter < numentries)
X	{
X		if(ptr->type == type)
X		{
X			return(ptr->name);
X		}
X		ptr++;
X		counter++;
X	}
X	return("unknown");
X}
END-of-fdisk.c
exit