494 lines
12 KiB
Diff
494 lines
12 KiB
Diff
--- util-linux-2.13-pre6/fdisk/fdisk.c.gpt 2005-11-24 15:30:36.000000000 +0100
|
|
+++ util-linux-2.13-pre6/fdisk/fdisk.c 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -34,6 +34,8 @@
|
|
#include <linux/blkpg.h>
|
|
#endif
|
|
|
|
+#include "gpt.h"
|
|
+
|
|
static void delete_partition(int i);
|
|
|
|
#define hex_val(c) ({ \
|
|
@@ -2400,6 +2402,14 @@
|
|
}
|
|
|
|
static void
|
|
+gpt_warning(char *dev)
|
|
+{
|
|
+ if (gpt_probe_signature_devname(dev))
|
|
+ fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
|
|
+ "The util fdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
|
|
+}
|
|
+
|
|
+static void
|
|
try(char *device, int user_specified) {
|
|
int gb;
|
|
|
|
@@ -2409,6 +2419,7 @@
|
|
if (!user_specified)
|
|
if (is_ide_cdrom_or_tape(device))
|
|
return;
|
|
+ gpt_warning(device);
|
|
if ((fd = open(disk_device, type_open)) >= 0) {
|
|
gb = get_boot(try_only);
|
|
if (gb > 0) { /* I/O error */
|
|
@@ -2470,6 +2481,8 @@
|
|
printf(_("%c: unknown command\n"), c);
|
|
}
|
|
|
|
+
|
|
+
|
|
int
|
|
main(int argc, char **argv) {
|
|
int j, c;
|
|
@@ -2574,6 +2587,7 @@
|
|
|
|
for (j = optind; j < argc; j++) {
|
|
disk_device = argv[j];
|
|
+ gpt_warning(disk_device);
|
|
if ((fd = open(disk_device, type_open)) < 0)
|
|
fatal(unable_to_open);
|
|
if (disksize(fd, &size))
|
|
@@ -2594,6 +2608,7 @@
|
|
else
|
|
fatal(usage2);
|
|
|
|
+ gpt_warning(disk_device);
|
|
get_boot(fdisk);
|
|
|
|
if (osf_label) {
|
|
--- /dev/null 2005-11-14 15:52:26.044616250 +0100
|
|
+++ util-linux-2.13-pre6/fdisk/gpt.h 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -0,0 +1,9 @@
|
|
+
|
|
+#ifndef __GPT_H__
|
|
+#define __GPT_H__
|
|
+
|
|
+extern int gpt_probe_signature_fd(int fd);
|
|
+extern int gpt_probe_signature_devname(char *devname);
|
|
+
|
|
+#endif /* __GPT_H__ */
|
|
+
|
|
--- util-linux-2.13-pre6/fdisk/Makefile.am.gpt 2005-10-16 14:12:52.000000000 +0200
|
|
+++ util-linux-2.13-pre6/fdisk/Makefile.am 2005-11-24 15:31:42.000000000 +0100
|
|
@@ -5,13 +5,13 @@
|
|
sbin_PROGRAMS = fdisk
|
|
man_MANS = fdisk.8
|
|
fdisk_SOURCES = fdisk.c disksize.c fdiskbsdlabel.c fdisksgilabel.c \
|
|
- fdisksunlabel.c fdiskaixlabel.c i386_sys_types.c partname.c
|
|
+ fdisksunlabel.c fdiskaixlabel.c i386_sys_types.c partname.c gpt.c
|
|
|
|
if !SPARC
|
|
|
|
sbin_PROGRAMS += sfdisk
|
|
man_MANS += sfdisk.8
|
|
-sfdisk_SOURCES = sfdisk.c disksize.c i386_sys_types.c partname.c
|
|
+sfdisk_SOURCES = sfdisk.c disksize.c i386_sys_types.c partname.c gpt.c
|
|
|
|
if USE_SLANG
|
|
sbin_PROGRAMS += cfdisk
|
|
--- util-linux-2.13-pre6/fdisk/fdisk.8.gpt 2005-11-24 15:30:36.000000000 +0100
|
|
+++ util-linux-2.13-pre6/fdisk/fdisk.8 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -42,6 +42,11 @@
|
|
partition tables.
|
|
It understands DOS type partition tables and BSD or SUN type disklabels.
|
|
|
|
+.B fdisk
|
|
+doesn't understand GUID Partition Table (GPT) and
|
|
+it is not designed for large partitions. In particular case use more advanced GNU
|
|
+.B parted(8).
|
|
+
|
|
The
|
|
.I device
|
|
is usually one of the following:
|
|
--- util-linux-2.13-pre6/fdisk/sfdisk.8.gpt 2004-12-31 17:28:30.000000000 +0100
|
|
+++ util-linux-2.13-pre6/fdisk/sfdisk.8 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -18,6 +18,11 @@
|
|
on a device, check the partitions on a device, and - very dangerous -
|
|
repartition a device.
|
|
|
|
+.B sfdisk
|
|
+doesn't understand GUID Partition Table (GPT) and
|
|
+it is not designed for large partitions. In particular case use more advanced GNU
|
|
+.B parted(8).
|
|
+
|
|
.SS "List Sizes"
|
|
.BI "sfdisk \-s " partition
|
|
gives the size of
|
|
--- /dev/null 2005-11-14 15:52:26.044616250 +0100
|
|
+++ util-linux-2.13-pre6/fdisk/gpt.c 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -0,0 +1,287 @@
|
|
+/*
|
|
+ GPT (GUID Partition Table) signature detection. Based on libparted and
|
|
+ util-linux/partx.
|
|
+
|
|
+ Warning: this code doesn't do all GPT checks (CRC32, Protective MBR, ..). It's
|
|
+ really GPT signature detection only.
|
|
+
|
|
+ -- Karel Zak <kzak@redhat.com> (Jun-2-2005)
|
|
+
|
|
+*/
|
|
+
|
|
+#include <stdio.h>
|
|
+#include <string.h>
|
|
+#include <stdlib.h>
|
|
+#include <inttypes.h>
|
|
+#include <sys/stat.h>
|
|
+#include <sys/ioctl.h>
|
|
+#include <sys/utsname.h>
|
|
+#include <sys/types.h>
|
|
+#include <fcntl.h>
|
|
+#include <unistd.h>
|
|
+#include <errno.h>
|
|
+#include <linux/fs.h>
|
|
+
|
|
+#include "gpt.h"
|
|
+
|
|
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
|
|
+#define SECTOR_SIZE 512 /* default */
|
|
+
|
|
+#define _GET_BYTE(x, n) ( ((x) >> (8 * (n))) & 0xff )
|
|
+
|
|
+#define _PED_SWAP64(x) ( (_GET_BYTE(x, 0) << 56) \
|
|
+ + (_GET_BYTE(x, 1) << 48) \
|
|
+ + (_GET_BYTE(x, 2) << 40) \
|
|
+ + (_GET_BYTE(x, 3) << 32) \
|
|
+ + (_GET_BYTE(x, 4) << 24) \
|
|
+ + (_GET_BYTE(x, 5) << 16) \
|
|
+ + (_GET_BYTE(x, 6) << 8) \
|
|
+ + (_GET_BYTE(x, 7) << 0) )
|
|
+
|
|
+#define PED_SWAP64(x) ((uint64_t) _PED_SWAP64( (uint64_t) (x) ))
|
|
+
|
|
+#if __BYTE_ORDER == __LITTLE_ENDIAN
|
|
+# define CPU_TO_LE64(x) (x)
|
|
+#else
|
|
+# define CPU_TO_LE64(x) PED_SWAP64(x)
|
|
+#endif
|
|
+
|
|
+#define BLKSSZGET _IO(0x12,104) /* get block device sector size */
|
|
+#define BLKGETLASTSECT _IO(0x12,108) /* get last sector of block device */
|
|
+#define BLKGETSIZE _IO(0x12,96) /* return device size */
|
|
+#define BLKGETSIZE64 _IOR(0x12,114,size_t) /* return device size in bytes (u64 *arg) */
|
|
+
|
|
+#define GPT_HEADER_SIGNATURE 0x5452415020494645LL
|
|
+#define GPT_PRIMARY_PARTITION_TABLE_LBA 1
|
|
+
|
|
+typedef struct {
|
|
+ uint32_t time_low;
|
|
+ uint16_t time_mid;
|
|
+ uint16_t time_hi_and_version;
|
|
+ uint8_t clock_seq_hi_and_reserved;
|
|
+ uint8_t clock_seq_low;
|
|
+ uint8_t node[6];
|
|
+} /* __attribute__ ((packed)) */ efi_guid_t;
|
|
+/* commented out "__attribute__ ((packed))" to work around gcc bug (fixed
|
|
+ * in gcc3.1): __attribute__ ((packed)) breaks addressing on initialized
|
|
+ * data. It turns out we don't need it in this case, so it doesn't break
|
|
+ * anything :)
|
|
+ */
|
|
+
|
|
+typedef struct _GuidPartitionTableHeader_t {
|
|
+ uint64_t Signature;
|
|
+ uint32_t Revision;
|
|
+ uint32_t HeaderSize;
|
|
+ uint32_t HeaderCRC32;
|
|
+ uint32_t Reserved1;
|
|
+ uint64_t MyLBA;
|
|
+ uint64_t AlternateLBA;
|
|
+ uint64_t FirstUsableLBA;
|
|
+ uint64_t LastUsableLBA;
|
|
+ efi_guid_t DiskGUID;
|
|
+ uint64_t PartitionEntryLBA;
|
|
+ uint32_t NumberOfPartitionEntries;
|
|
+ uint32_t SizeOfPartitionEntry;
|
|
+ uint32_t PartitionEntryArrayCRC32;
|
|
+ uint8_t Reserved2[512 - 92];
|
|
+} __attribute__ ((packed)) GuidPartitionTableHeader_t;
|
|
+
|
|
+struct blkdev_ioctl_param {
|
|
+ unsigned int block;
|
|
+ size_t content_length;
|
|
+ char * block_contents;
|
|
+};
|
|
+
|
|
+static int
|
|
+_get_linux_version (void)
|
|
+{
|
|
+ static int kver = -1;
|
|
+ struct utsname uts;
|
|
+ int major;
|
|
+ int minor;
|
|
+ int teeny;
|
|
+
|
|
+ if (kver != -1)
|
|
+ return kver;
|
|
+ if (uname (&uts))
|
|
+ return kver = 0;
|
|
+ if (sscanf (uts.release, "%u.%u.%u", &major, &minor, &teeny) != 3)
|
|
+ return kver = 0;
|
|
+ return kver = KERNEL_VERSION (major, minor, teeny);
|
|
+}
|
|
+
|
|
+static unsigned int
|
|
+_get_sector_size (int fd)
|
|
+{
|
|
+ unsigned int sector_size;
|
|
+
|
|
+ if (_get_linux_version() < KERNEL_VERSION (2,3,0))
|
|
+ return SECTOR_SIZE;
|
|
+ if (ioctl (fd, BLKSSZGET, §or_size))
|
|
+ return SECTOR_SIZE;
|
|
+ return sector_size;
|
|
+}
|
|
+
|
|
+static uint64_t
|
|
+_get_num_sectors(int fd)
|
|
+{
|
|
+ int version = _get_linux_version();
|
|
+ unsigned long size;
|
|
+ uint64_t bytes=0;
|
|
+
|
|
+ if (version >= KERNEL_VERSION(2,5,4) ||
|
|
+ (version < KERNEL_VERSION(2,5,0) &&
|
|
+ version >= KERNEL_VERSION (2,4,18)))
|
|
+ {
|
|
+ if (ioctl(fd, BLKGETSIZE64, &bytes) == 0)
|
|
+ return bytes / _get_sector_size(fd);
|
|
+ }
|
|
+ if (ioctl (fd, BLKGETSIZE, &size))
|
|
+ return 0;
|
|
+ return size;
|
|
+}
|
|
+
|
|
+static uint64_t
|
|
+last_lba(int fd)
|
|
+{
|
|
+ int rc;
|
|
+ uint64_t sectors = 0;
|
|
+ struct stat s;
|
|
+
|
|
+ memset(&s, 0, sizeof (s));
|
|
+ rc = fstat(fd, &s);
|
|
+ if (rc == -1)
|
|
+ {
|
|
+ fprintf(stderr, "last_lba() could not stat: %s\n",
|
|
+ strerror(errno));
|
|
+ return 0;
|
|
+ }
|
|
+ if (S_ISBLK(s.st_mode))
|
|
+ sectors = _get_num_sectors(fd);
|
|
+ else
|
|
+ {
|
|
+ fprintf(stderr,
|
|
+ "last_lba(): I don't know how to handle files with mode %x\n",
|
|
+ s.st_mode);
|
|
+ sectors = 1;
|
|
+ }
|
|
+ return sectors - 1;
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
+read_lastoddsector(int fd, uint64_t lba, void *buffer, size_t count)
|
|
+{
|
|
+ int rc;
|
|
+ struct blkdev_ioctl_param ioctl_param;
|
|
+
|
|
+ if (!buffer) return 0;
|
|
+
|
|
+ ioctl_param.block = 0; /* read the last sector */
|
|
+ ioctl_param.content_length = count;
|
|
+ ioctl_param.block_contents = buffer;
|
|
+
|
|
+ rc = ioctl(fd, BLKGETLASTSECT, &ioctl_param);
|
|
+ if (rc == -1) perror("read failed");
|
|
+
|
|
+ return !rc;
|
|
+}
|
|
+
|
|
+static ssize_t
|
|
+read_lba(int fd, uint64_t lba, void *buffer, size_t bytes)
|
|
+{
|
|
+ int sector_size = _get_sector_size(fd);
|
|
+ off_t offset = lba * sector_size;
|
|
+ ssize_t bytesread;
|
|
+
|
|
+ lseek(fd, offset, SEEK_SET);
|
|
+ bytesread = read(fd, buffer, bytes);
|
|
+
|
|
+ /* Kludge. This is necessary to read/write the last
|
|
+ block of an odd-sized disk, until Linux 2.5.x kernel fixes.
|
|
+ This is only used by gpt.c, and only to read
|
|
+ one sector, so we don't have to be fancy.
|
|
+ */
|
|
+ if (!bytesread && !(last_lba(fd) & 1) && lba == last_lba(fd))
|
|
+ bytesread = read_lastoddsector(fd, lba, buffer, bytes);
|
|
+ return bytesread;
|
|
+}
|
|
+
|
|
+static GuidPartitionTableHeader_t *
|
|
+alloc_read_gpt_header(int fd, uint64_t lba)
|
|
+{
|
|
+ GuidPartitionTableHeader_t *gpt =
|
|
+ (GuidPartitionTableHeader_t *) malloc(sizeof (GuidPartitionTableHeader_t));
|
|
+ if (!gpt)
|
|
+ return NULL;
|
|
+ memset(gpt, 0, sizeof (*gpt));
|
|
+ if (!read_lba(fd, lba, gpt, sizeof (GuidPartitionTableHeader_t)))
|
|
+ {
|
|
+ free(gpt);
|
|
+ return NULL;
|
|
+ }
|
|
+ return gpt;
|
|
+}
|
|
+
|
|
+static int
|
|
+gpt_check_signature(int fd, uint64_t lba)
|
|
+{
|
|
+ GuidPartitionTableHeader_t *gpt;
|
|
+ int res=0;
|
|
+
|
|
+ if ((gpt = alloc_read_gpt_header(fd, lba)))
|
|
+ {
|
|
+ if (gpt->Signature == CPU_TO_LE64(GPT_HEADER_SIGNATURE))
|
|
+ res = 1;
|
|
+ free(gpt);
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+/* returns:
|
|
+ * 0 not found GPT
|
|
+ * 1 for valid primary GPT header
|
|
+ * 2 for valid alternative GPT header
|
|
+ */
|
|
+int
|
|
+gpt_probe_signature_fd(int fd)
|
|
+{
|
|
+ int res = 0;
|
|
+
|
|
+ /* check primary GPT header */
|
|
+ if (gpt_check_signature(fd, GPT_PRIMARY_PARTITION_TABLE_LBA))
|
|
+ res = 1;
|
|
+ else
|
|
+ {
|
|
+ /* check alternative GPT header */
|
|
+ uint64_t lastlba = last_lba(fd);
|
|
+ if (gpt_check_signature(fd, lastlba))
|
|
+ res = 2;
|
|
+ }
|
|
+ return res;
|
|
+}
|
|
+
|
|
+int
|
|
+gpt_probe_signature_devname(char *devname)
|
|
+{
|
|
+ int res, fd;
|
|
+ if ((fd = open(devname, O_RDONLY)) < 0)
|
|
+ return 0;
|
|
+ res = gpt_probe_signature_fd(fd);
|
|
+ close(fd);
|
|
+ return res;
|
|
+}
|
|
+
|
|
+#ifdef GPT_TEST_MAIN
|
|
+int
|
|
+main(int argc, char **argv)
|
|
+{
|
|
+ if (argc!=2)
|
|
+ {
|
|
+ fprintf(stderr, "usage: %s <dev>\n", argv[0]);
|
|
+ exit(EXIT_FAILURE);
|
|
+ }
|
|
+ if (gpt_probe_signature_devname(argv[1]))
|
|
+ printf("GPT (GUID Partition Table) detected on %s\n", argv[1]);
|
|
+ exit(EXIT_SUCCESS);
|
|
+}
|
|
+#endif
|
|
--- util-linux-2.13-pre6/fdisk/sfdisk.c.gpt 2005-10-16 14:18:32.000000000 +0200
|
|
+++ util-linux-2.13-pre6/fdisk/sfdisk.c 2005-11-24 15:30:36.000000000 +0100
|
|
@@ -50,6 +50,8 @@
|
|
#include "nls.h"
|
|
#include "common.h"
|
|
|
|
+#include "gpt.h"
|
|
+
|
|
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
|
|
|
|
/*
|
|
@@ -2457,6 +2459,23 @@
|
|
return NULL;
|
|
}
|
|
|
|
+static void
|
|
+gpt_warning(char *dev, int warn_only)
|
|
+{
|
|
+ if (force)
|
|
+ warn_only = 1;
|
|
+
|
|
+ if (gpt_probe_signature_devname(dev)) {
|
|
+ fflush(stdout);
|
|
+ fprintf(stderr, _("\nWARNING: GPT (GUID Partition Table) detected on '%s'! "
|
|
+ "The util sfdisk doesn't support GPT. Use GNU Parted.\n\n"), dev);
|
|
+ if (!warn_only) {
|
|
+ fprintf(stderr, _("Use the --force flag to overrule this check.\n"));
|
|
+ exit(1);
|
|
+ }
|
|
+ }
|
|
+}
|
|
+
|
|
static void do_list(char *dev, int silent);
|
|
static void do_size(char *dev, int silent);
|
|
static void do_geom(char *dev, int silent);
|
|
@@ -2602,6 +2621,7 @@
|
|
while ((dev = nextproc()) != NULL) {
|
|
if (is_ide_cdrom_or_tape(dev))
|
|
continue;
|
|
+ gpt_warning(dev, 1);
|
|
if (opt_out_geom)
|
|
do_geom(dev, 1);
|
|
if (opt_out_pt_geom)
|
|
@@ -2629,6 +2649,7 @@
|
|
|
|
if (opt_list || opt_out_geom || opt_out_pt_geom || opt_size || verify) {
|
|
while (optind < argc) {
|
|
+ gpt_warning(argv[optind], 1);
|
|
if (opt_out_geom)
|
|
do_geom(argv[optind], 0);
|
|
if (opt_out_pt_geom)
|
|
@@ -2657,6 +2678,7 @@
|
|
fatal(_("usage: sfdisk --change-id device partition-number Id\n"));
|
|
else if (optind != argc-3 && optind != argc-2)
|
|
fatal(_("usage: sfdisk --id device partition-number [Id]\n"));
|
|
+ gpt_warning(argv[optind], 0);
|
|
do_change_id(argv[optind], argv[optind+1],
|
|
(optind == argc-2) ? 0 : argv[optind+2]);
|
|
exit(exit_status);
|
|
@@ -2666,6 +2688,8 @@
|
|
fatal(_("can specify only one device (except with -l or -s)\n"));
|
|
dev = argv[optind];
|
|
|
|
+ gpt_warning(dev, 0);
|
|
+
|
|
if (opt_reread)
|
|
do_reread(dev);
|
|
else if (restore_sector_file)
|
|
@@ -2842,6 +2866,8 @@
|
|
|
|
z = &oldp;
|
|
|
|
+ gpt_warning(dev, 0);
|
|
+
|
|
rw = (!no_write && (arg || ac > 1));
|
|
fd = my_open(dev, rw, 0);
|
|
|
|
@@ -2943,6 +2969,8 @@
|
|
|
|
z = &oldp;
|
|
|
|
+ gpt_warning(dev, 0);
|
|
+
|
|
rw = !no_write;
|
|
fd = my_open(dev, rw, 0);
|
|
|