From timon@netherworld.ru  Mon Jul 15 07:06:54 2002
Return-Path: <timon@netherworld.ru>
Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125])
	by hub.freebsd.org (Postfix) with ESMTP id C1C7A37B400
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 15 Jul 2002 07:06:54 -0700 (PDT)
Received: from netherworld.ru (memphis.mephi.ru [194.67.67.234])
	by mx1.FreeBSD.org (Postfix) with ESMTP id 3EB9243E67
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 15 Jul 2002 07:06:53 -0700 (PDT)
	(envelope-from timon@netherworld.ru)
Received: from netherworld.ru (localhost [127.0.0.1])
	by netherworld.ru (8.12.3/8.12.3) with ESMTP id g6FDwlQ8004753
	for <FreeBSD-gnats-submit@freebsd.org>; Mon, 15 Jul 2002 17:58:47 +0400 (MSD)
	(envelope-from timon@netherworld.ru)
Received: (from timon@localhost)
	by netherworld.ru (8.12.3/8.12.3/Submit) id g6FDwlHg004752;
	Mon, 15 Jul 2002 17:58:47 +0400 (MSD)
Message-Id: <200207151358.g6FDwlHg004752@netherworld.ru>
Date: Mon, 15 Jul 2002 17:58:47 +0400 (MSD)
From: "Artem 'Zazoobr' Ignatjev" <timon@netherworld.ru>
Reply-To: "Artem 'Zazoobr' Ignatjev" <timon@netherworld.ru>
To: FreeBSD-gnats-submit@freebsd.org
Cc:
Subject: add /sbin/fdisk ability of showing extended partition tables
X-Send-Pr-Version: 3.113
X-GNATS-Notify:

>Number:         40597
>Category:       bin
>Synopsis:       [patch] add fdisk(8) ability of showing extended partition tables
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          update
>Submitter-Id:   current-users
>Arrival-Date:   Mon Jul 15 07:10:01 PDT 2002
>Closed-Date:    
>Last-Modified:  Fri Jun 15 23:48:51 GMT 2007
>Originator:     Artem 'Zazoobr' Ignatjev
>Release:        FreeBSD 4.6-RELEASE i386
>Organization:
>Environment:
System: FreeBSD netherworld.ru 4.6-RELEASE FreeBSD 4.6-RELEASE #0: Fri Jun 14 12:49:08 MSD 2002 root@netherworld.ru:/usr/obj/usr/src/sys/NETHER i386


	
>Description:
	following patch lets /sbin/fdisk traverse through extended partitions on 
	hdd's of i386 compatible machines, dumping information about partitions it i
	founds.
	
>How-To-Repeat:
	
>Fix:

--- sbin/i386/fdisk/fdisk.c	Mon Jul 15 13:54:04 2002
+++ sbin/i386/fdisk/fdisk.c	Mon Jul 15 17:41:06 2002
@@ -190,6 +190,7 @@
 
 static void print_s0(int which);
 static void print_part(int i);
+static void dump_part_table(void);
 static void init_sector0(unsigned long start);
 static void init_boot(void);
 static void change_part(int i);
@@ -203,6 +204,7 @@
 static ssize_t write_disk(off_t sector, void *buf);
 static int get_params();
 static int read_s0();
+static int read_sect_into_mboot(u_int32_t sect, struct mboot *mboot);
 static int write_s0();
 static int ok(char *str);
 static int decimal(char *str, int *num, int deflt);
@@ -386,9 +388,11 @@
 	    printf("Media sector size is %d\n", secsize);
 	    printf("Warning: BIOS sector numbering starts with sector 1\n");
 	    printf("Information from DOS bootblock is:\n");
-	    if (partition == -1)
-		for (i = 1; i <= NDOSPART; i++)
-		    change_part(i);
+            if (partition == -1) 
+		if(!i_flag && ! u_flag) dump_part_table();
+	    	else 
+	                for (i = 1; i <= NDOSPART; i++)
+			    change_part(i);
 	    else
 		change_part(partition);
 
@@ -435,8 +439,9 @@
 	print_params();
 	printf("Information from DOS bootblock is:\n");
 	if (which == -1)
-		for (i = 1; i <= NDOSPART; i++)
-			printf("%d: ", i), print_part(i);
+/*		for (i = 1; i <= NDOSPART; i++)
+			printf("%d: ", i), print_part(i);*/
+		dump_part_table();
 	else
 		print_part(which);
 }
@@ -476,6 +481,62 @@
 		,partp->dp_ehd
 		,DPSECT(partp->dp_esect));
 }
+static void
+dump_part_table(void)
+{
+#define MAX_MBR_PARTS 4
+#define MAX_EXT_PARTS 2
+/* Extended partitions are of type 0x0f/0x05 */
+#define is_ext_type(type) (((type)==0x0F) || ((type)== 0x05))
+	struct	  dos_partition *partp;
+	struct    mboot mboot = {{0}, NULL, 0};
+	int 	i;
+	u_int64_t part_mb;
+	u_int64_t first_ext_offs = 0, curr_ext_offs=0;
+/* maximum partitions depends on whether we're in MBR or somewhere in
+ * extended partition. If we're in MBR, then max partitions count is 4,
+ * else 2
+ */
+#define MAX_PARTS_NOW ((first_ext_offs)?MAX_EXT_PARTS:MAX_MBR_PARTS)
+	read_sect_into_mboot(0, &mboot);
+	for(i = 0; i < MAX_PARTS_NOW ; i++) { 
+		partp = ((struct dos_partition *) &mboot.parts) + i;
+	
+		if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
+			printf("<UNUSED>\n");
+			return;
+		}
+		/*
+		 * Be careful not to overflow.
+		 */
+		part_mb = partp->dp_size;
+		part_mb *= secsize;
+		part_mb /= (1024 * 1024);
+		printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
+		printf("    start %lu, size %lu (%qd Meg), flag %x%s\n",
+			(u_long)partp->dp_start,
+			(u_long)partp->dp_size, 
+			part_mb,
+			partp->dp_flag,
+			partp->dp_flag == ACTIVE ? " (active)" : "");
+		printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n"
+			,DPCYL(partp->dp_scyl, partp->dp_ssect)
+			,partp->dp_shd
+			,DPSECT(partp->dp_ssect)
+			,DPCYL(partp->dp_ecyl, partp->dp_esect)
+			,partp->dp_ehd
+			,DPSECT(partp->dp_esect));
+		if(is_ext_type(partp->dp_typ)) {
+			if(first_ext_offs == 0) first_ext_offs = partp->dp_start;
+			curr_ext_offs = partp->dp_start;
+
+			printf("This extended partition at %lu contains:\n", partp->dp_start);
+			if(read_sect_into_mboot(curr_ext_offs, &mboot)) return;
+			i = 0; // Go to the next extended - restart for() cycle
+		}
+	}
+}
+
 
 
 static void
@@ -795,6 +856,31 @@
 	memcpy(mboot.parts, &mboot.bootinst[DOSPARTOFF], sizeof(mboot.parts));
 	return 0;
 }
+
+static int
+read_sect_into_mboot(u_int32_t sect, struct mboot * mboot)
+{
+	mboot->bootinst_size = secsize;
+	if (mboot->bootinst != NULL)
+		free(mboot->bootinst);
+	if ((mboot->bootinst = malloc(mboot->bootinst_size)) == NULL) {
+		warnx("unable to allocate buffer to read fdisk "
+		      "partition table");
+		return -1;
+	}
+	if (read_disk(sect , mboot->bootinst) == -1) {
+		warnx("can't read fdisk partition table");
+		return -1;
+	}
+	if (*(uint16_t *)&mboot->bootinst[MBRSIGOFF] != BOOT_MAGIC) {
+		warnx("invalid fdisk partition table found");
+		/* So should we initialize things */
+		return -1;
+	}
+	memcpy(mboot->parts, &mboot->bootinst[DOSPARTOFF], sizeof(mboot->parts));
+	return 0;
+}
+
 
 static int
 write_s0()
	


>Release-Note:
>Audit-Trail:

From: "Artem 'Zazoobr' Ignatjev" <timon@netherworld.ru>
To: freebsd-bugs@FreeBSD.org, FreeBSD-gnats-submit@FreeBSD.org
Cc:  
Subject: Re: bin/40597: add /sbin/fsck ability of showing extended partition tables
Date: Mon, 15 Jul 2002 19:43:02 +0400 (MSD)

 Ooopss... My previous posting contains wrong patch - I realized that as soon as i've got to host where freebsd slice is adNs9 :-( 
 This one works:
 ==== Begin patch-fdisk ====
 
 --- sbin/i386/fdisk/fdisk.c	Mon Jul 15 13:54:04 2002
 +++ sbin/i386/fdisk/fdisk.c	Mon Jul 15 19:35:08 2002
 @@ -190,6 +190,7 @@
  
  static void print_s0(int which);
  static void print_part(int i);
 +static void dump_part_table(void);
  static void init_sector0(unsigned long start);
  static void init_boot(void);
  static void change_part(int i);
 @@ -203,6 +204,7 @@
  static ssize_t write_disk(off_t sector, void *buf);
  static int get_params();
  static int read_s0();
 +static int read_sect_into_mboot(u_int32_t sect, struct mboot *mboot);
  static int write_s0();
  static int ok(char *str);
  static int decimal(char *str, int *num, int deflt);
 @@ -386,9 +388,11 @@
  	    printf("Media sector size is %d\n", secsize);
  	    printf("Warning: BIOS sector numbering starts with sector 1\n");
  	    printf("Information from DOS bootblock is:\n");
 -	    if (partition == -1)
 -		for (i = 1; i <= NDOSPART; i++)
 -		    change_part(i);
 +            if (partition == -1) 
 +		if(!i_flag && ! u_flag) dump_part_table();
 +	    	else 
 +	                for (i = 1; i <= NDOSPART; i++)
 +			    change_part(i);
  	    else
  		change_part(partition);
  
 @@ -435,8 +439,9 @@
  	print_params();
  	printf("Information from DOS bootblock is:\n");
  	if (which == -1)
 -		for (i = 1; i <= NDOSPART; i++)
 -			printf("%d: ", i), print_part(i);
 +/*		for (i = 1; i <= NDOSPART; i++)
 +			printf("%d: ", i), print_part(i);*/
 +		dump_part_table();
  	else
  		print_part(which);
  }
 @@ -476,6 +481,67 @@
  		,partp->dp_ehd
  		,DPSECT(partp->dp_esect));
  }
 +static void
 +dump_part_table(void)
 +{
 +#define MAX_MBR_PARTS 4
 +#define MAX_EXT_PARTS 2
 +/* Extended partitions are of type 0x0f/0x05 */
 +#define is_ext_type(type) (((type)==0x0F) || ((type)== 0x05))
 +	struct	  dos_partition *partp;
 +	struct    mboot mboot = {{0}, NULL, 0};
 +	int 	i;
 +	u_int64_t part_mb;
 +	u_int64_t first_ext_offs = 0, curr_ext_offs=0;
 +/* maximum partitions depends on whether we're in MBR or somewhere in
 + * extended partition. If we're in MBR, then max partitions count is 4,
 + * else 2
 + */
 +#define MAX_PARTS_NOW ((first_ext_offs)?MAX_EXT_PARTS:MAX_MBR_PARTS)
 +	read_sect_into_mboot(0, &mboot);
 +	for(i = 0; i < MAX_PARTS_NOW ; i++) { 
 +		partp = ((struct dos_partition *) &mboot.parts) + i;
 +	
 +		if (!bcmp(partp, &mtpart, sizeof (struct dos_partition))) {
 +			printf("<UNUSED>\n");
 +			return;
 +		}
 +		if(is_ext_type(partp->dp_typ))
 +			partp->dp_start += first_ext_offs;
 +		else
 +			partp->dp_start += curr_ext_offs;
 +		/*
 +		 * Be careful not to overflow.
 +		 */
 +		part_mb = partp->dp_size;
 +		part_mb *= secsize;
 +		part_mb /= (1024 * 1024);
 +		printf("sysid %d,(%s)\n", partp->dp_typ, get_type(partp->dp_typ));
 +		printf("    start %lu, size %lu (%qd Meg), flag %x%s\n",
 +			(u_long)partp->dp_start,
 +			(u_long)partp->dp_size, 
 +			part_mb,
 +			partp->dp_flag,
 +			partp->dp_flag == ACTIVE ? " (active)" : "");
 +		printf("\tbeg: cyl %d/ head %d/ sector %d;\n\tend: cyl %d/ head %d/ sector %d\n"
 +			,DPCYL(partp->dp_scyl, partp->dp_ssect)
 +			,partp->dp_shd
 +			,DPSECT(partp->dp_ssect)
 +			,DPCYL(partp->dp_ecyl, partp->dp_esect)
 +			,partp->dp_ehd
 +			,DPSECT(partp->dp_esect));
 +		if(is_ext_type(partp->dp_typ)) {
 +			if(first_ext_offs == 0) first_ext_offs = partp->dp_start;
 +			curr_ext_offs = partp->dp_start;
 +
 +			printf("This extended partition at %lu contains:\n", partp->dp_start);
 +			if(read_sect_into_mboot(curr_ext_offs, &mboot)) return;
 +			i = -1; // Go to the next extended - restart for() cycle
 +
 +		}
 +	}
 +}
 +
  
  
  static void
 @@ -795,6 +861,31 @@
  	memcpy(mboot.parts, &mboot.bootinst[DOSPARTOFF], sizeof(mboot.parts));
  	return 0;
  }
 +
 +static int
 +read_sect_into_mboot(u_int32_t sect, struct mboot * mboot)
 +{
 +	mboot->bootinst_size = secsize;
 +	if (mboot->bootinst != NULL)
 +		free(mboot->bootinst);
 +	if ((mboot->bootinst = malloc(mboot->bootinst_size)) == NULL) {
 +		warnx("unable to allocate buffer to read fdisk "
 +		      "partition table");
 +		return -1;
 +	}
 +	if (read_disk(sect , mboot->bootinst) == -1) {
 +		warnx("can't read fdisk partition table");
 +		return -1;
 +	}
 +	if (*(uint16_t *)&mboot->bootinst[MBRSIGOFF] != BOOT_MAGIC) {
 +		warnx("invalid fdisk partition table found");
 +		/* So should we initialize things */
 +		return -1;
 +	}
 +	memcpy(mboot->parts, &mboot->bootinst[DOSPARTOFF], sizeof(mboot->parts));
 +	return 0;
 +}
 +
  
  static int
  write_s0()
 ==== End patch-fdisk ====
>Unformatted:
