tech-userlevel archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: fdisk behavior on a gpt partitioned disks
Alan Barrett <apb%cequrux.com@localhost> wrote:
> On Fri, 29 May 2009, Mike M. Volokhov wrote:
> > To be honest, the fdisk patch will delete GPT headers only, leaving
> > GUID tables intact. So, it should be possible to reconstruct GPT
> > partitioning back :)
>
> It might make sense to just destroy a magic number, leaving most of the
> GPT headers intact; this would make it easy to recover if somebody makes
> a mistake.
Why not? It's done with new patch. Thanks for idea.
I also updated fdisk man page. I'd be grateful if someone could proofread it.
--
Mishka.
Index: Makefile
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/Makefile,v
retrieving revision 1.38
diff -u -r1.38 Makefile
--- Makefile 29 Nov 2007 23:19:25 -0000 1.38
+++ Makefile 30 May 2009 21:38:04 -0000
@@ -18,7 +18,7 @@
.if (${HOSTPROG:U} == "")
SUBDIR= mbr
-DPADD+= ${LIBUTIL}
-LDADD+= -lutil
+DPADD+= ${LIBUTIL} ${LIBZ}
+LDADD+= -lutil -lz
.include <bsd.subdir.mk>
.endif
Index: fdisk.8
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.8,v
retrieving revision 1.59
diff -u -r1.59 fdisk.8
--- fdisk.8 20 Jan 2008 15:04:09 -0000 1.59
+++ fdisk.8 30 May 2009 21:38:04 -0000
@@ -1,6 +1,6 @@
.\" $NetBSD: fdisk.8,v 1.59 2008/01/20 15:04:09 dsl Exp $
.\"
-.Dd January 20, 2008
+.Dd June 1, 2009
.Dt FDISK 8
.Os
.Sh NAME
@@ -125,6 +125,14 @@
.Nm
selects defaults for its questions to guarantee that behaviour.
.Pp
+If partition data is going to be updated, and disk carries GUID Partition
+Tables the
+.Nm
+will remove both primary and backup GPT headers from the disk.
+See
+.Xr gpt 8
+for information on how to manipulate GUID Partition Tables.
+.Pp
.Nm
will calculate the correct
.Em cylinder ,
@@ -559,6 +567,7 @@
.Xr disktab 5 ,
.Xr boot 8 ,
.Xr disklabel 8 ,
+.Xr gpt 8 ,
.Xr installboot 8 ,
.Xr mbr 8 ,
.Xr mbrlabel 8
Index: fdisk.c
===================================================================
RCS file: /cvsroot/src/sbin/fdisk/fdisk.c,v
retrieving revision 1.116.6.1
diff -u -r1.116.6.1 fdisk.c
--- fdisk.c 20 Apr 2009 23:16:45 -0000 1.116.6.1
+++ fdisk.c 30 May 2009 21:38:05 -0000
@@ -61,13 +61,16 @@
#if !HAVE_NBTOOL_CONFIG_H
#include <sys/disklabel.h>
+#include <sys/disklabel_gpt.h>
#include <sys/bootblock.h>
#include <sys/ioctl.h>
#include <sys/sysctl.h>
#include <disktab.h>
#include <util.h>
+#include <zlib.h>
#else
#include <nbinclude/sys/disklabel.h>
+#include <nbinclude/sys/disklabel_gpt.h>
#include <nbinclude/sys/bootblock.h>
#include "../../include/disktab.h"
/* We enforce -F, so none of these possibly undefined items can be needed */
@@ -207,6 +210,8 @@
int F_flag = 1;
#endif
+struct gpt_hdr gpt1, gpt2; /* GUID partition tables */
+
struct mbr_sector bootcode[8192 / sizeof (struct mbr_sector)];
int bootsize; /* actual size of bootcode */
int boot_installed; /* 1 if we've copied code into the mbr */
@@ -245,6 +250,8 @@
int get_params(void);
int read_s0(daddr_t, struct mbr_sector *);
int write_mbr(void);
+int read_gpt(daddr_t, struct gpt_hdr *);
+int delete_gpt(struct gpt_hdr *);
int yesno(const char *, ...);
int decimal(const char *, int, int, int, int);
#define DEC_SEC 1 /* asking for a sector number */
@@ -298,7 +305,8 @@
int csysid; /* For the b_flag. */
unsigned int cstart, csize;
- a_flag = i_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
+ a_flag = u_flag = sh_flag = f_flag = s_flag = b_flag = 0;
+ i_flag = B_flag = 0;
v_flag = 0;
E_flag = 0;
csysid = cstart = csize = 0;
@@ -444,6 +452,9 @@
/* must have been a blank disk */
init_sector0(1);
+ read_gpt(GPT_HDR_BLKNO, &gpt1);
+ read_gpt(disksectors - 1, &gpt2);
+
#if (defined(__i386__) || defined(__x86_64__)) && !HAVE_NBTOOL_CONFIG_H
get_geometry();
#else
@@ -509,10 +520,23 @@
"yet. This is your last chance.\n");
if (u_flag)
print_s0(-1);
- if (yesno("Should we write new partition table?"))
+ if (gpt1.hdr_size != 0 || gpt2.hdr_size != 0)
+ printf("\nWARNING: The disk is carrying "
+ "GUID Partition Tables.\n"
+ " If you continue, "
+ "GPT headers will be deleted.\n\n");
+ if (yesno("Should we write new partition table?")) {
+ delete_gpt(&gpt1);
+ delete_gpt(&gpt2);
write_mbr();
- } else
+ }
+ } else {
+ if (delete_gpt(&gpt1) > 0)
+ warnx("Primary GPT header was deleted");
+ if (delete_gpt(&gpt2) > 0)
+ warnx("Secondary GPT header was deleted");
write_mbr();
+ }
}
exit(0);
@@ -2777,3 +2801,75 @@
return ("unknown");
return (ptr->name);
}
+
+int
+read_gpt(daddr_t offset, struct gpt_hdr *gptp)
+{
+ struct gpt_hdr *buf;
+ const char *tabletype =
+ offset == GPT_HDR_BLKNO ? "primary" : "secondary";
+
+ if ((buf = malloc(512)) == NULL)
+ err(1, "Malloc failed");
+ if (read_disk(offset, buf) == -1) {
+ warn("Can't read %s GPT header", tabletype);
+ return -1;
+ }
+ memcpy(gptp, buf, GPT_HDR_SIZE);
+
+ /* GPT CRC should be calculated with CRC field preset to zero */
+ buf->hdr_crc_self = 0;
+
+ if (memcmp(gptp->hdr_sig, GPT_HDR_SIG, sizeof(gptp->hdr_sig))
+ || gptp->hdr_lba_self != offset
+ || crc32(0, (void *)buf, gptp->hdr_size)
+ != gptp->hdr_crc_self)
+ /* not a GPT */
+ memset(gptp, 0, GPT_HDR_SIZE);
+
+ if (v_flag && gptp->hdr_size != 0)
+ printf("Found %s GPT header CRC %"PRIu32" "
+ "at sector %"PRIdaddr", backup at %"PRIdaddr"\n",
+ tabletype, gptp->hdr_crc_self,
+ offset, gptp->hdr_lba_alt);
+ free(buf);
+ return gptp->hdr_size;
+
+}
+
+int
+delete_gpt(struct gpt_hdr *gptp)
+{
+ struct gpt_hdr *buf;
+
+ if (gptp->hdr_size == 0)
+ return 0;
+
+ /* don't accidently overwrite something important */
+ if (gptp->hdr_lba_self != GPT_HDR_BLKNO &&
+ gptp->hdr_lba_self != disksectors - 1) {
+ warn("given GPT header location doesn't seem correct");
+ return -1;
+ }
+
+ if ((buf = malloc(512)) == NULL)
+ err(1, "Malloc failed");
+ memcpy(buf, gptp, GPT_HDR_SIZE);
+
+ /*
+ * Don't really delete GPT, just "disable" it, so it can
+ * be recovered later in case of mistake or something
+ */
+ memset(buf->hdr_sig, 0, sizeof(gptp->hdr_sig));
+ if (write_disk(gptp->hdr_lba_self, buf) == -1) {
+ warn("can't delete %s GPT header",
+ gptp->hdr_lba_self == GPT_HDR_BLKNO ?
+ "primary" : "secondary");
+ free(buf);
+ return -1;
+ }
+
+ memset(gptp, 0, GPT_HDR_SIZE);
+ free(buf);
+ return 1;
+}
Home |
Main Index |
Thread Index |
Old Index