Subject: changes to Fdisk to support extended partitions
To: None <tech-userlevel@netbsd.org>
From: Rafal Boni <rafal@raptor.com>
List: tech-userlevel
Date: 06/10/1999 18:12:19
This is a multi-part message in MIME format.
--------------D322C0970868C0867E5D83B6
Content-Type: text/plain; charset=us-ascii
Content-Transfer-Encoding: 7bit
Folks:
I've hacked together some changes to fdisk to make it support
editing/viewing of extended partitions. It still probably needs
support for adding new extended partitions (It will most likely
fail to initialize the new extended partitions' partition table),
but otherwise should be functional.
I'd like people to take a look at it and comment on the
following:
(1) Is this something that we would want to put in
the tree?
(2) Missing functionality related to extended
partitions
(3) Incorrect results.
If you've got a machine to play around with this on, please do
and send any feedback you have.
I've got this to the point where it does what I want, but I'd
like to finish out the functionality set and submit it to TNF.
The diffs vs. rev 1.37 of src/sbin/fdisk.c are attached.
Thanks!
--rafal
--
Rafal Boni rafal@raptor.com
Raptor Systems, Waltham, MA http://www.raptor.com/ 781.530.2200
--------------D322C0970868C0867E5D83B6
Content-Type: text/plain; charset=us-ascii;
name="fdisk.diffs"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="fdisk.diffs"
--- fdisk.c Sat Jun 5 04:12:24 1999
+++ fdisk.c.new Thu Jun 10 14:55:01 1999
@@ -29,7 +29,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: fdisk.c,v 1.37 1999/06/04 18:59:15 thorpej Exp $");
+__RCSID("$NetBSD: fdisk.c,v 1.36 1999/05/02 12:17:48 fvdl Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -69,6 +69,7 @@
struct disklabel disklabel; /* disk parameters */
+unsigned long ext_offset = 0;
int cylinders, sectors, heads, cylindersectors, disksectors;
struct mboot {
@@ -77,7 +78,11 @@
struct mbr_partition parts[NMBRPART];
u_int16_t signature;
};
-struct mboot mboot;
+
+#define MAX_PARTITION 100
+#define get_part_ptr(num) (&(ptbl[(num) / NMBRPART].parts[(num) % NMBRPART]))
+#define IS_EXTENDED(type) ((type) == 0x05 || (type) == 0x0F || ((type) == 0x85))
+struct mboot ptbl[MAX_PARTITION];
#ifdef __i386__
@@ -99,9 +104,9 @@
#define DEFAULT_BOOTCODE "/usr/mdec/mbr"
#define DEFAULT_BOOTSELCODE "/usr/mdec/mbr_bootsel"
-#define OPTIONS "0123BSafius:b:c:"
+#define OPTIONS "0123BSafirus:b:c:"
#else
-#define OPTIONS "0123Safius:b:c:"
+#define OPTIONS "0123Safirus:b:c:"
#endif
#define ACTIVE 0x80
@@ -115,6 +120,7 @@
#define DOSCYL(c) ((c) & 0xff)
#define MAXCYL 1024
+int maxpart = 4;
int partition = -1;
int a_flag; /* set active partition */
@@ -122,6 +128,7 @@
int u_flag; /* update partition data */
int sh_flag; /* Output data as shell defines */
int f_flag; /* force --not interactive */
+int r_flag; /* recurse on extended partition types */
int s_flag; /* set id,offset,size */
int b_flag; /* Set cyl, heads, secs (as c/h/s) */
int B_flag; /* Edit/install bootselect code */
@@ -264,17 +271,20 @@
int try_heads __P((quad_t, quad_t, quad_t, quad_t, quad_t, quad_t, quad_t,
quad_t));
int try_sectors __P((quad_t, quad_t, quad_t, quad_t, quad_t));
-void change_part __P((int, int, int, int));
+void change_part __P((int, unsigned long, unsigned long, unsigned long));
void print_params __P((void));
void change_active __P((int));
void get_params_to_use __P((void));
void dos __P((int, unsigned char *, unsigned char *, unsigned char *));
int open_disk __P((int));
-int read_disk __P((int, void *));
-int write_disk __P((int, void *));
+int read_disk __P((unsigned long, void *));
+int write_disk __P((unsigned long, void *));
int get_params __P((void));
int read_s0 __P((void));
+int read_extended_partitions __P((void));
+int read_chain __P((struct mboot*, int, unsigned long));
int write_s0 __P((void));
+int write_chain __P((struct mboot*, int, unsigned long));
int yesno __P((char *));
void decimal __P((char *, int *));
int type_match __P((const void *, const void *));
@@ -302,7 +312,8 @@
int csysid, cstart, csize; /* For the b_flag. */
- a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
+ r_flag = a_flag = i_flag = u_flag = sh_flag = f_flag =
+ s_flag = b_flag = 0;
csysid = cstart = csize = 0;
while ((ch = getopt(argc, argv, OPTIONS)) != -1)
switch (ch) {
@@ -335,6 +346,9 @@
case 'i':
i_flag = 1;
break;
+ case 'r':
+ r_flag = 1;
+ break;
case 'u':
u_flag = 1;
break;
@@ -396,6 +410,8 @@
intuit_translated_geometry();
#endif
+ if (r_flag)
+ read_extended_partitions();
if ((i_flag || u_flag) && (!f_flag || b_flag))
get_params_to_use();
@@ -407,8 +423,9 @@
if (u_flag) {
if (!f_flag)
printf("Partition table:\n");
+
if (partition == -1)
- for (part = 0; part < NMBRPART; part++)
+ for (part = 0; part < maxpart; part++)
change_part(part,-1, -1, -1);
else
change_part(partition, csysid, cstart, csize);
@@ -459,7 +476,10 @@
if (!sh_flag)
printf("Partition table:\n");
if (which == -1) {
- for (part = 0; part < NMBRPART; part++) {
+ for (part = 0; part < maxpart; part++) {
+ if (!sh_flag && part && part % NMBRPART == 0) {
+ printf("\nExtended partition %d\n", part / NMBRPART);
+ }
if (!sh_flag)
printf("%d: ", part);
print_part(part);
@@ -517,7 +537,7 @@
struct mbr_partition *partp;
int empty;
- partp = &mboot.parts[part];
+ partp = get_part_ptr(part);
empty = (partp->mbrp_typ == 0);
if (sh_flag) {
@@ -602,12 +622,12 @@
sizeof bootcode);
#endif
- memcpy(mboot.bootinst, bootcode, sizeof(mboot.bootinst));
- putshort(&mboot.signature, MBR_MAGIC);
+ memcpy(ptbl[0].bootinst, bootcode, sizeof(ptbl[0].bootinst));
+ putshort(&ptbl[0].signature, MBR_MAGIC);
if (dopart)
for (i=0; i<4; i++)
- memset(&mboot.parts[i], 0, sizeof(struct mbr_partition));
+ memset(get_part_ptr(i), 0, sizeof(struct mbr_partition));
}
@@ -709,13 +729,13 @@
configure_bootsel()
{
struct mbr_bootsel *mbs =
- (struct mbr_bootsel *)&mboot.bootinst[MBR_BOOTSELOFF];
+ (struct mbr_bootsel *)&ptbl[0].bootinst[MBR_BOOTSELOFF];
int i, nused, firstpart = -1, item;
char desc[10], *p;
int timo, entry_changed = 0;
for (i = nused = 0; i < NMBRPART; i++) {
- if (mboot.parts[i].mbrp_typ != 0) {
+ if (ptbl[0].parts[i].mbrp_typ != 0) {
if (firstpart == -1)
firstpart = i;
nused++;
@@ -734,7 +754,7 @@
}
bootsize = read_boot(DEFAULT_BOOTSELCODE, bootcode,
sizeof bootcode);
- memcpy(mboot.bootinst, bootcode, sizeof(mboot.bootinst));
+ memcpy(ptbl[0].bootinst, bootcode, sizeof(ptbl[0].bootinst));
bootsel_modified = 1;
mbs->flags |= BFL_SELACTIVE;
} else {
@@ -760,7 +780,7 @@
}
printf("\n\nPartition table:\n");
- for (i = 0; i < NMBRPART; i++) {
+ for (i = 0; i < maxpart; i++) {
printf("%d: ", i);
print_part(i);
}
@@ -785,7 +805,7 @@
printf("Invalid entry number\n");
continue;
}
- if (mboot.parts[item].mbrp_typ == 0) {
+ if (ptbl[0].parts[item].mbrp_typ == 0) {
printf("The matching partition entry is unused\n");
continue;
}
@@ -870,8 +890,8 @@
done:
for (i = 0; i < NMBRPART; i++) {
- if (mboot.parts[i].mbrp_typ != 0 &&
- mboot.parts[i].mbrp_start >=
+ if (ptbl[0].parts[i].mbrp_typ != 0 &&
+ ptbl[0].parts[i].mbrp_start >=
(dos_cylinders * dos_heads * dos_sectors)) {
mbs->flags |= BFL_EXTINT13;
break;
@@ -975,7 +995,7 @@
int i, *cylinder, *head, *sector;
long *absolute;
{
- struct mbr_partition *part = &mboot.parts[i / 2];
+ struct mbr_partition *part = &ptbl[0].parts[i / 2];
if (part->mbrp_typ == 0)
return -1;
@@ -996,11 +1016,12 @@
void
change_part(part, csysid, cstart, csize)
- int part, csysid, cstart, csize;
+ int part;
+ unsigned long csysid, cstart, csize;
{
struct mbr_partition *partp;
- partp = &mboot.parts[part];
+ partp = get_part_ptr(part);
if (s_flag) {
if (csysid == 0 && cstart == 0 && csize == 0)
@@ -1116,35 +1137,50 @@
change_active(which)
int which;
{
+ int i, active, gotactive;
struct mbr_partition *partp;
- int part;
- int active = 4;
-
- partp = &mboot.parts[0];
if (a_flag && which != -1)
active = which;
else {
- for (part = 0; part < NMBRPART; part++)
- if (partp[part].mbrp_flag & ACTIVE)
- active = part;
+ printf ("Choosing -1 will leave active flags unchanged.\n");
+ do {
+ decimal("Partition number to change", &active);
+
+ if (active < 0)
+ return;
+
+ if (active > maxpart - 1)
+ printf("Partition number must be between 0 and %d!\n", maxpart - 1);
+ } while (1);
}
+
if (!f_flag) {
- if (yesno("Do you want to change the active partition?")) {
- printf ("Choosing 4 will make no partition active.\n");
- do {
- decimal("active partition", &active);
- } while (!yesno("Are you happy with this choice?"));
- } else
+ if (!yesno("Are you happy with this choice?"))
return;
- } else
- if (active != 4)
+ }
+
+ partp = get_part_ptr(active);
+
+ if (partp->mbrp_flag & ACTIVE) {
+ printf ("De-activating partition %d.\n", active);
+ partp->mbrp_flag &= ~ACTIVE;
+ } else {
printf ("Making partition %d active.\n", active);
+ partp->mbrp_flag |= ACTIVE;
+ }
- for (part = 0; part < NMBRPART; part++)
- partp[part].mbrp_flag &= ~ACTIVE;
- if (active < 4)
- partp[active].mbrp_flag |= ACTIVE;
+ if (active < 4) {
+ partp = get_part_ptr(0);
+ for (i = 0, gotactive = 0; i < NMBRPART; i++) {
+ if (partp[i].mbrp_flag & ACTIVE) {
+ if (gotactive++)
+ warnx("More than one active"
+ "partition in master boot"
+ "record!");
+ }
+ }
+ }
}
void
@@ -1239,10 +1275,20 @@
int
read_disk(sector, buf)
- int sector;
+ unsigned long sector;
void *buf;
{
+ unsigned long dos_size, size;
+ size = cylinders * heads * sectors;
+ dos_size = dos_cylinders * dos_heads * dos_sectors;
+
+#if 0
+ if (sector > size && sector > dos_size) {
+ warnx("attempt to read outside of disk boundary!");
+ return (-1);
+ }
+#endif
if (lseek(fd, (off_t)(sector * 512), 0) == -1)
return (-1);
return (read(fd, buf, 512));
@@ -1250,10 +1296,20 @@
int
write_disk(sector, buf)
- int sector;
+ unsigned long sector;
void *buf;
{
+ unsigned long dos_size, size;
+ size = cylinders * heads * sectors;
+ dos_size = dos_cylinders * dos_heads * dos_sectors;
+
+#if 0
+ if (sector > size && sector > dos_size) {
+ warnx("attempt to write outside of disk boundary!");
+ return (-1);
+ }
+#endif
if (lseek(fd, (off_t)(sector * 512), 0) == -1)
return (-1);
return (write(fd, buf, 512));
@@ -1280,15 +1336,37 @@
int
read_s0()
{
-
- if (read_disk(0, mboot.bootinst) == -1) {
+ if (read_disk(0, ptbl[0].bootinst) == -1) {
warn("can't read fdisk partition table");
return (-1);
}
- if (getshort(&mboot.signature) != MBR_MAGIC) {
+ if (getshort(&ptbl[0].signature) != MBR_MAGIC) {
warnx("invalid fdisk partition table found");
return (-1);
}
+
+ return (0);
+}
+
+int
+read_extended_partitions()
+{
+ int part;
+ int gotext = 0;
+ struct mbr_partition *partp;
+
+ partp = get_part_ptr(0);
+ for(part = 0; part < NMBRPART; part++) {
+ if (IS_EXTENDED(partp[part].mbrp_typ)) {
+ if (!gotext) {
+ ext_offset = getlong(&partp[part].mbrp_start);
+ read_chain(ptbl, part, 0);
+ gotext++;
+ } else
+ warnx("multiple extended partition table chains");
+ }
+ }
+
return (0);
}
@@ -1296,6 +1374,7 @@
write_s0()
{
int flag, i;
+ struct mbr_partition *partp;
/*
* write enable label sector before write (if necessary),
@@ -1306,7 +1385,7 @@
flag = 1;
if (ioctl(fd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
- if (write_disk(0, mboot.bootinst) == -1) {
+ if (write_disk(0, ptbl[0].bootinst) == -1) {
warn("can't write fdisk partition table");
return -1;
}
@@ -1318,6 +1397,15 @@
flag = 0;
if (ioctl(fd, DIOCWLABEL, &flag) < 0)
warn("DIOCWLABEL");
+
+ if (r_flag && ext_offset) {
+ partp = get_part_ptr(0);
+ for(i = 0; i < NMBRPART; i++) {
+ if (IS_EXTENDED(partp[i].mbrp_typ))
+ write_chain(&ptbl[0], i, 0);
+ }
+ }
+
return 0;
}
@@ -1394,4 +1482,80 @@
if (ptr == 0)
return ("unknown");
return (ptr->name);
+}
+
+int
+read_chain(parent, which, offset)
+ struct mboot* parent;
+ int which;
+ unsigned long offset;
+{
+ int i, gotext;
+ unsigned long myoffset;
+ struct mbr_partition *partp;
+ struct mboot* ptable = parent + 1;
+
+ if (maxpart + 4 > MAX_PARTITION)
+ warn("more than %d partitions, dropping extra partitions", MAX_PARTITION);
+
+ printf("read_chain: parent = %p, ptable = %p, offset = %lu\n",
+ parent, ptable, offset + ext_offset);
+
+ if (read_disk(ext_offset + offset, &ptable->bootinst) == -1) {
+ warn("can't read extended partition table");
+ return (-1);
+ }
+
+ if (getshort(&ptable->signature) != MBR_MAGIC) {
+ warnx("invalid fdisk partition table found");
+ return (-1);
+ }
+
+ /* We've read in the table sucesfully, up partition count */
+ maxpart += NMBRPART;
+
+ /* The assumption is that if we've gotten here, -r has been specified */
+ gotext = 0;
+ partp = &ptable->parts[0];
+ for(i = 0; i < NMBRPART; i++) {
+ if (IS_EXTENDED(partp[i].mbrp_typ)) {
+ if (!gotext) {
+ myoffset = getlong(&partp[i].mbrp_start);
+ read_chain(ptable, i, myoffset);
+ gotext++;
+ } else
+ warnx("multiple extended partition table chains");
+ }
+ }
+
+ return 0;
+}
+
+int
+write_chain(parent, which, offset)
+ struct mboot* parent;
+ int which;
+ unsigned long offset;
+{
+ int i;
+ unsigned long myoffset;
+ struct mbr_partition *partp;
+ struct mboot* ptable = parent + 1;
+
+ printf("write_chain: parent = %p, ptable = %p, offset = %lu\n",
+ parent, ptable, offset + ext_offset);
+
+ if (write_disk(offset + ext_offset, &ptable->bootinst) == -1)
+ errx(1, "can't write extended partition table");
+
+ partp = &ptable->parts[0];
+ for(i = 0; i < NMBRPART; i++) {
+ if (IS_EXTENDED(partp[i].mbrp_typ)) {
+ myoffset = getlong(&partp[i].mbrp_start);
+ if (write_chain(ptable, i, myoffset) < 0)
+ errx(1, "failed to write extended partitions");
+ }
+ }
+
+ return 0;
}
--------------D322C0970868C0867E5D83B6--