diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:16:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-15 19:16:35 +0000 |
commit | 0658a8b1efc58836eb6674a1b0aadfbdf0e54755 (patch) | |
tree | e1d58d026a886d854c9e01cb4a683ad81fcb6e59 /debian/patches | |
parent | Adding upstream version 3.6. (diff) | |
download | parted-0658a8b1efc58836eb6674a1b0aadfbdf0e54755.tar.xz parted-0658a8b1efc58836eb6674a1b0aadfbdf0e54755.zip |
Adding debian version 3.6-3.debian/3.6-3
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'debian/patches')
-rw-r--r-- | debian/patches/align-new-partitions-on-fresh-disks.patch | 45 | ||||
-rw-r--r-- | debian/patches/doc-package.patch | 25 | ||||
-rw-r--r-- | debian/patches/freebsd-geli.patch | 38 | ||||
-rw-r--r-- | debian/patches/freebsd-ufs.patch | 291 | ||||
-rw-r--r-- | debian/patches/freebsd-zvol.patch | 83 | ||||
-rw-r--r-- | debian/patches/gptsync.patch | 466 | ||||
-rw-r--r-- | debian/patches/kfreebsd-gnu.patch | 1434 | ||||
-rw-r--r-- | debian/patches/kfreebsd_lvm.patch | 55 | ||||
-rw-r--r-- | debian/patches/link-libuuid.patch | 32 | ||||
-rw-r--r-- | debian/patches/preserve-hidden-parts.patch | 45 | ||||
-rw-r--r-- | debian/patches/probe-lvs-again.patch | 34 | ||||
-rw-r--r-- | debian/patches/series | 13 | ||||
-rw-r--r-- | debian/patches/udevadm-settle.patch | 105 | ||||
-rw-r--r-- | debian/patches/zfs.patch | 145 |
14 files changed, 2811 insertions, 0 deletions
diff --git a/debian/patches/align-new-partitions-on-fresh-disks.patch b/debian/patches/align-new-partitions-on-fresh-disks.patch new file mode 100644 index 0000000..c37bfe0 --- /dev/null +++ b/debian/patches/align-new-partitions-on-fresh-disks.patch @@ -0,0 +1,45 @@ +From 8b6f34acaadd78d11415144dccf5c4750e3e1d0e Mon Sep 17 00:00:00 2001 +From: Colin Watson <cjwatson@ubuntu.com> +Date: Wed, 6 Aug 2014 16:07:28 +0200 +Subject: Align new partitions created on fresh disks + +Commit fa815ad05db248d78ef214ea79a78c22772a9ffe arranged to skip +partition alignment while reading disks, but also has the effect of +skipping partition alignment when creating a partition on a fresh disk, +which is incorrect. + +The proper upstream fix probably involves adding a new member to PedDisk +to keep track of whether we're in the middle of the initial read in +ped_disk_new or not. To avoid changing ABI, we instead take this hacky +approach of overloading an extra bit on PedDisk.needs_clobber. + +Bug-Ubuntu: https://bugs.launchpad.net/bugs/1352252 +Forwarded: no +Last-Update: 2023-06-26 + +Patch-Name: align-new-partitions-on-fresh-disks.patch +--- + libparted/disk.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/libparted/disk.c b/libparted/disk.c +index 0db7b5c9..2d6b9d49 100644 +--- a/libparted/disk.c ++++ b/libparted/disk.c +@@ -198,6 +198,7 @@ ped_disk_new (PedDevice* dev) + disk = ped_disk_new_fresh (dev, type); + if (!disk) + goto error_close_dev; ++ disk->needs_clobber |= 2; + if (!type->ops->read (disk)) + goto error_destroy_disk; + disk->needs_clobber = 0; +@@ -951,7 +952,7 @@ _partition_align (PedPartition* part, const PedConstraint* constraint) + PED_ASSERT (disk_type->ops->partition_align != NULL); + PED_ASSERT (part->disk->update_mode); + +- if (part->disk->needs_clobber) ++ if ((part->disk->needs_clobber & 2) != 0 || !constraint) + return 1; /* do not attempt to align partitions while reading them */ + return disk_type->ops->partition_align (part, constraint); + } diff --git a/debian/patches/doc-package.patch b/debian/patches/doc-package.patch new file mode 100644 index 0000000..d4dc59a --- /dev/null +++ b/debian/patches/doc-package.patch @@ -0,0 +1,25 @@ +From 2bf67dffffb5b09ce5b3deca65d279f8526a6033 Mon Sep 17 00:00:00 2001 +From: Timshel Knoll <timshel@debian.org> +Date: Fri, 28 Mar 2014 17:09:39 +0000 +Subject: Small documentation fixes + +Forwarded: not-needed + +Patch-Name: doc-package.patch +--- + doc/C/parted.8 | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/doc/C/parted.8 b/doc/C/parted.8 +index 3069c335..18abf537 100644 +--- a/doc/C/parted.8 ++++ b/doc/C/parted.8 +@@ -160,7 +160,7 @@ The \fIparted\fP program is fully documented in the + .BR info(1) + format + .IR "GNU partitioning software" +-manual. ++manual which is distributed with the parted-doc Debian package. + .SH AUTHOR + This manual page was written by Timshel Knoll <timshel@debian.org>, + for the Debian GNU/Linux system (but may be used by others). diff --git a/debian/patches/freebsd-geli.patch b/debian/patches/freebsd-geli.patch new file mode 100644 index 0000000..0e71090 --- /dev/null +++ b/debian/patches/freebsd-geli.patch @@ -0,0 +1,38 @@ +From 981a6a2a87a90b25b83ecfc76f5c82c0fadcbbf8 Mon Sep 17 00:00:00 2001 +From: Robert Millan <rmh@debian.org> +Date: Fri, 28 Mar 2014 17:09:51 +0000 +Subject: Detection of GEOM encryption devices (GELI) + +Bug-Debian: http://bugs.debian.org/635393 +Forwarded: no +Last-Update: 2011-07-30 + +Patch-Name: freebsd-geli.patch +--- + libparted/arch/freebsd.c | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/libparted/arch/freebsd.c b/libparted/arch/freebsd.c +index a60b43f8..b78d2bb0 100644 +--- a/libparted/arch/freebsd.c ++++ b/libparted/arch/freebsd.c +@@ -1096,6 +1096,8 @@ _probe_kern_disks () + { + size_t listsize; + char *disklist, *pdisklist, *psave; ++ char buf[PATH_MAX]; ++ struct stat st; + + if (sysctlbyname("kern.disks", NULL, &listsize, NULL, 0) != 0) { + ped_exception_throw ( +@@ -1129,6 +1131,10 @@ _probe_kern_disks () + strncat (dev_name, token, sizeof(dev_name) - strlen(_PATH_DEV) - 1); + dev_name[sizeof(dev_name) - 1] = '\0'; + _ped_device_probe (dev_name); ++ ++ snprintf (buf, sizeof (buf), "%s.eli", dev_name); ++ if (stat (buf, &st) == 0) ++ _ped_device_probe (buf); + } + + free(disklist); diff --git a/debian/patches/freebsd-ufs.patch b/debian/patches/freebsd-ufs.patch new file mode 100644 index 0000000..2484d07 --- /dev/null +++ b/debian/patches/freebsd-ufs.patch @@ -0,0 +1,291 @@ +From 1bb66d74adb068f467668aa6f2cd36775cb63fee Mon Sep 17 00:00:00 2001 +From: Aurelien Jarno <aurelien@aurel32.net> +Date: Fri, 28 Mar 2014 17:09:46 +0000 +Subject: Add FreeBSD UFS support + +This patch adds support for detection of FreeBSD UFS file systems and +creation of the partition on DOS and GPT labels. It doesn't use the +system of slices used by default on FreeBSD and places the partition +directly in the dos label. This is something supported by the FreeBSD +kernel, and the default on Debian GNU/kFreeBSD. Even on plain FreeBSD, +some persons prefer to not use slices. + +This patch is used by debian-installer on Debian GNU/kFreeBSD for some +months already. + +Last-Update: 2023-06-12 + +Patch-Name: freebsd-ufs.patch +--- + libparted/fs/ufs/ufs.c | 103 ++++++++++++++++++++++++++++++++++--- + libparted/labels/dos.c | 3 ++ + libparted/labels/gpt.c | 9 ++++ + tests/Makefile.am | 1 + + tests/t2500-freebsd-ufs.sh | 44 ++++++++++++++++ + 5 files changed, 153 insertions(+), 7 deletions(-) + create mode 100644 tests/t2500-freebsd-ufs.sh + +diff --git a/libparted/fs/ufs/ufs.c b/libparted/fs/ufs/ufs.c +index d2bf4214..08ed5603 100644 +--- a/libparted/fs/ufs/ufs.c ++++ b/libparted/fs/ufs/ufs.c +@@ -45,6 +45,7 @@ + #define UFS_MAGIC_LFN 0x00095014 + #define UFS_MAGIC_FEA 0x00195612 + #define UFS_MAGIC_4GB 0x05231994 ++#define UFS2_MAGIC 0x19540119 + + struct __attribute__ ((packed)) ufs_csum { + uint32_t cs_ndir; /* number of directories */ +@@ -129,13 +130,50 @@ struct __attribute__ ((packed)) ufs_super_block { + int8_t fs_clean; /* file system is clean flag */ + int8_t fs_ronly; /* mounted read-only flag */ + int8_t fs_flags; /* currently unused flag */ +- int8_t fs_fsmnt[UFS_MAXMNTLEN]; /* name mounted on */ +-/* these fields retain the current block allocation info */ +- uint32_t fs_cgrotor; /* last cg searched */ +- uint32_t fs_csp[UFS_MAXCSBUFS]; /* list of fs_cs info buffers */ +- uint32_t fs_maxcluster; +- uint32_t fs_cpc; /* cyl per cycle in postbl */ +- uint16_t fs_opostbl[16][8]; /* old rotation block list head */ ++ union { ++ struct { ++ int8_t fs_fsmnt[UFS_MAXMNTLEN]; /* name mounted on */ ++ /* these fields retain the current block allocation info */ ++ uint32_t fs_cgrotor; /* last cg searched */ ++ uint32_t fs_csp[UFS_MAXCSBUFS]; /* list of fs_cs info buffers */ ++ uint32_t fs_maxcluster; ++ uint32_t fs_cpc; /* cyl per cycle in postbl */ ++ uint16_t fs_opostbl[16][8]; /* old rotation block list head */ ++ } fs_u1; ++ struct { ++ int8_t fs_fsmnt[468]; ++ uint8_t fs_volname[32]; ++ uint64_t fs_swuid; ++ int32_t fs_pad; ++ uint32_t fs_cgrotor; ++ uint32_t fs_ocsp[28]; ++ uint32_t fs_contigdirs; ++ uint32_t fs_csp; ++ uint32_t fs_maxcluster; ++ uint32_t fs_active; ++ int32_t fs_old_cpc; ++ int32_t fs_maxbsize; ++ int64_t fs_sparecon64[17]; ++ int64_t fs_sblockloc; ++ struct ufs2_csum_total { ++ uint64_t cs_ndir; ++ uint64_t cs_nbfree; ++ uint64_t cs_nifree; ++ uint64_t cs_nffree; ++ uint64_t cs_numclusters; ++ uint64_t cs_spare[3]; ++ } fs_cstotal; ++ struct ufs_timeval { ++ int32_t tv_sec; ++ int32_t tv_usec; ++ } fs_time; ++ int64_t fs_size; ++ int64_t fs_dsize; ++ uint64_t fs_csaddr; ++ int64_t fs_pendingblocks; ++ int32_t fs_pendinginodes; ++ } __attribute__((packed)) fs_u2; ++ } fs_u11; + union { + struct { + int32_t fs_sparecon[53];/* reserved for future constants */ +@@ -244,6 +282,45 @@ ufs_probe_hp (PedGeometry* geom) + return NULL; + } + ++static PedGeometry* ++ufs_probe_freebsd (PedGeometry* geom) ++{ ++ int offsets[] = { 0, 16, 128, 512 }; ++ char *buf = alloca (3 * geom->dev->sector_size); ++ struct ufs_super_block *sb; ++ PedSector block_size; ++ PedSector block_count; ++ int i; ++ ++ if (geom->length < 5) ++ return 0; ++ ++ /* The UFS superblock could be on four different positions */ ++ for (i = 0; i < 4; i++) { ++ if (!ped_geometry_read (geom, buf, offsets[i], 3)) ++ return 0; ++ ++ sb = (struct ufs_super_block *)buf; ++ ++ /* Little endian is more likely on FreeBSD boxes */ ++ if (PED_LE32_TO_CPU(sb->fs_magic) == UFS2_MAGIC) { ++ block_size = PED_LE32_TO_CPU(sb->fs_fsize) / geom->dev->sector_size; ++ block_count = PED_LE32_TO_CPU(sb->fs_u11.fs_u2.fs_size); ++ return ped_geometry_new (geom->dev, geom->start, ++ block_size * block_count); ++ } ++ ++ /* Then try big endian */ ++ if (PED_BE32_TO_CPU(sb->fs_magic) == UFS2_MAGIC) { ++ block_size = PED_BE32_TO_CPU(sb->fs_fsize) / geom->dev->sector_size; ++ block_count = PED_BE32_TO_CPU(sb->fs_u11.fs_u2.fs_size); ++ return ped_geometry_new (geom->dev, geom->start, ++ block_size * block_count); ++ } ++ } ++ return NULL; ++} ++ + static PedFileSystemOps ufs_ops_sun = { + probe: ufs_probe_sun, + }; +@@ -252,6 +329,10 @@ static PedFileSystemOps ufs_ops_hp = { + probe: ufs_probe_hp, + }; + ++static PedFileSystemOps ufs_ops_freebsd = { ++ probe: ufs_probe_freebsd, ++}; ++ + static PedFileSystemType ufs_type_sun = { + next: NULL, + ops: &ufs_ops_sun, +@@ -264,6 +345,12 @@ static PedFileSystemType ufs_type_hp = { + name: "hp-ufs", + }; + ++static PedFileSystemType ufs_type_freebsd_ufs = { ++ next: NULL, ++ ops: &ufs_ops_freebsd, ++ name: "freebsd-ufs" ++}; ++ + void + ped_file_system_ufs_init () + { +@@ -271,11 +358,13 @@ ped_file_system_ufs_init () + + ped_file_system_type_register (&ufs_type_sun); + ped_file_system_type_register (&ufs_type_hp); ++ ped_file_system_type_register (&ufs_type_freebsd_ufs); + } + + void + ped_file_system_ufs_done () + { ++ ped_file_system_type_unregister (&ufs_type_freebsd_ufs); + ped_file_system_type_unregister (&ufs_type_hp); + ped_file_system_type_unregister (&ufs_type_sun); + } +diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c +index 256f365d..95737d56 100644 +--- a/libparted/labels/dos.c ++++ b/libparted/labels/dos.c +@@ -89,6 +89,7 @@ static const char MBR_BOOT_CODE[] = { + #define PARTITION_IRST 0x84 + #define PARTITION_LINUX_EXT 0x85 + #define PARTITION_LINUX_LVM 0x8e ++#define PARTITION_FREEBSD_UFS 0xa5 + #define PARTITION_HFS 0xaf + #define PARTITION_SUN_UFS 0xbf + #define PARTITION_DELL_DIAG 0xde +@@ -1610,6 +1611,8 @@ msdos_partition_set_system (PedPartition* part, + dos_data->system = PARTITION_UDF; + else if (!strcmp (fs_type->name, "sun-ufs")) + dos_data->system = PARTITION_SUN_UFS; ++ else if (!strcmp (fs_type->name, "freebsd-ufs")) ++ dos_data->system = PARTITION_FREEBSD_UFS; + else if (is_linux_swap (fs_type->name)) + dos_data->system = PARTITION_LINUX_SWAP; + else +diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c +index 780fb705..130b9bd1 100644 +--- a/libparted/labels/gpt.c ++++ b/libparted/labels/gpt.c +@@ -169,6 +169,10 @@ typedef struct + ((efi_guid_t) { PED_CPU_TO_LE32 (0x933ac7e1), PED_CPU_TO_LE16 (0x2eb4), \ + PED_CPU_TO_LE16 (0x4f13), 0xb8, 0x44, \ + { 0x0e, 0x14, 0xe2, 0xae, 0xf9, 0x15 }}) ++#define PARTITION_FREEBSD_UFS_GUID \ ++ ((efi_guid_t) { PED_CPU_TO_LE32 (0x516e7cb6), PED_CPU_TO_LE16 (0x6ecf), \ ++ PED_CPU_TO_LE16 (0x11d6), 0x8f, 0xf8, \ ++ { 0x00, 0x02, 0x2d, 0x09, 0x71, 0x2b }}) + + struct flag_uuid_mapping_t + { +@@ -1490,6 +1494,11 @@ gpt_partition_set_system (PedPartition *part, + gpt_part_data->type = PARTITION_SWAP_GUID; + return 1; + } ++ if (strstr (fs_type->name, "freebsd-ufs")) ++ { ++ gpt_part_data->type = PARTITION_FREEBSD_UFS_GUID; ++ return 1; ++ } + } + + gpt_part_data->type = PARTITION_LINUX_DATA_GUID; +diff --git a/tests/Makefile.am b/tests/Makefile.am +index fa27b44d..da093119 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -57,6 +57,7 @@ TESTS = \ + t2320-dos-extended-noclobber.sh \ + t2400-dos-hfs-partition-type.sh \ + t2410-dos-udf-partition-type.sh \ ++ t2500-freebsd-ufs.sh \ + t2500-probe-corrupt-hfs.sh \ + t3000-resize-fs.sh \ + t3200-resize-partition.sh \ +diff --git a/tests/t2500-freebsd-ufs.sh b/tests/t2500-freebsd-ufs.sh +new file mode 100644 +index 00000000..5a46263d +--- /dev/null ++++ b/tests/t2500-freebsd-ufs.sh +@@ -0,0 +1,44 @@ ++#!/bin/sh ++# Probe FreeBSD UFS file system ++ ++# Copyright (C) 2010 Free Software Foundation, Inc. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++if test "$VERBOSE" = yes; then ++ set -x ++ parted --version ++fi ++ ++: ${srcdir=.} ++. $srcdir/t-lib.sh ++require_512_byte_sector_size_ ++ ++dev=loop-file ++ss=$sector_size_ ++n_sectors=8000 ++ ++fail=0 ++ ++( type mkfs.ufs ) >/dev/null 2>&1 || skip_test_ "no freebsd-ufs support" ++ ++# create a freebsd-ufs file system ++dd if=/dev/zero of=$dev bs=1024 count=4096 >/dev/null || fail=1 ++mkfs.ufs `pwd`/$dev >/dev/null || fail=1 ++ ++# probe the freebsd-ufs file system ++parted -m -s $dev u s print >out 2>&1 || fail=1 ++grep '^1:.*:freebsd-ufs::;$' out || fail=1 ++ ++Exit $fail diff --git a/debian/patches/freebsd-zvol.patch b/debian/patches/freebsd-zvol.patch new file mode 100644 index 0000000..b7826bc --- /dev/null +++ b/debian/patches/freebsd-zvol.patch @@ -0,0 +1,83 @@ +From 3b19f4af4398d71eb3dd58041d4aff94e05efb6d Mon Sep 17 00:00:00 2001 +From: Robert Millan <rmh@debian.org> +Date: Fri, 28 Mar 2014 17:09:50 +0000 +Subject: Detection of ZFS volumes (ZVOL) + +ZFS volumes (ZVOL) are the ZFS equivalent of Logical Volumes in LVM. + +They implement a block device which can be used for swap or legacy +filesystems. + +Bug-Debian: http://bugs.debian.org/635384 +Forwarded: no +Last-Update: 2011-07-30 + +Patch-Name: freebsd-zvol.patch +--- + libparted/arch/freebsd.c | 40 ++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 40 insertions(+) + +diff --git a/libparted/arch/freebsd.c b/libparted/arch/freebsd.c +index 4c690e5f..a60b43f8 100644 +--- a/libparted/arch/freebsd.c ++++ b/libparted/arch/freebsd.c +@@ -23,6 +23,7 @@ + #include <parted/debug.h> + + #include <ctype.h> ++#include <dirent.h> + #include <errno.h> + #include <fcntl.h> + #include <stdint.h> +@@ -1134,12 +1135,51 @@ _probe_kern_disks () + return 1; + } + ++static int ++_probe_zfs_volumes () ++{ ++ DIR* pool_dir; ++ DIR* zvol_dir; ++ struct dirent* pool_dent; ++ struct dirent* zvol_dent; ++ char buf[PATH_MAX]; ++ struct stat st; ++ ++ pool_dir = opendir ("/dev/zvol"); ++ if (!pool_dir) ++ return 0; ++ ++ while ((pool_dent = readdir (pool_dir))) { ++ if (strcmp (pool_dent->d_name, ".") == 0 || strcmp (pool_dent->d_name, "..") == 0) ++ continue; ++ ++ snprintf (buf, sizeof (buf), "/dev/zvol/%s", pool_dent->d_name); ++ zvol_dir = opendir (buf); ++ ++ while ((zvol_dent = readdir (zvol_dir))) { ++ if (strcmp (zvol_dent->d_name, ".") == 0 || strcmp (zvol_dent->d_name, "..") == 0) ++ continue; ++ ++ snprintf (buf, sizeof (buf), "/dev/zvol/%s/%s", pool_dent->d_name, zvol_dent->d_name); ++ if (stat (buf, &st) != 0) ++ continue; ++ _ped_device_probe (buf); ++ } ++ closedir (zvol_dir); ++ } ++ closedir (pool_dir); ++ ++ return 1; ++} ++ + static void + freebsd_probe_all () + { + _probe_standard_devices (); + + _probe_kern_disks (); ++ ++ _probe_zfs_volumes (); + } + + static char* diff --git a/debian/patches/gptsync.patch b/debian/patches/gptsync.patch new file mode 100644 index 0000000..27820fe --- /dev/null +++ b/debian/patches/gptsync.patch @@ -0,0 +1,466 @@ +From aa55572c980da038e675fc963d98a90964a2ce33 Mon Sep 17 00:00:00 2001 +From: Matthew Garrett <mjg59@srcf.ucam.org> +Date: Fri, 28 Mar 2014 17:10:01 +0000 +Subject: GPT syncing for Intel Macs + +On Intel Mac systems, write a synced MBR rather than a protective MBR. + +From: Colin Watson <cjwatson@ubuntu.com> +Forwarded: no +Last-Update: 2022-04-19 + +Patch-Name: gptsync.patch +--- + libparted/labels/gpt.c | 205 +++++++++++++++++++++++++++++++++++++++-- + tests/Makefile.am | 1 + + tests/t0290-gptsync.sh | 175 +++++++++++++++++++++++++++++++++++ + 3 files changed, 371 insertions(+), 10 deletions(-) + create mode 100644 tests/t0290-gptsync.sh + +diff --git a/libparted/labels/gpt.c b/libparted/labels/gpt.c +index 130b9bd1..bebedb47 100644 +--- a/libparted/labels/gpt.c ++++ b/libparted/labels/gpt.c +@@ -369,6 +369,40 @@ typedef struct _GPTPartitionData + + static PedDiskType gpt_disk_type; + ++ ++#if (defined(__i386__) || defined(__x86_64__)) && defined(__linux__) ++# define USE_DMI ++#endif ++ ++#define APPLE_DMI "Apple Computer, Inc." ++#define APPLE_DMI_2 "Apple Inc." ++static int is_apple = 0; ++ ++static char * ++dmi_system_manufacturer (void) ++{ ++#ifdef USE_DMI ++ FILE *dmidecode; ++ char *manufacturer = NULL; ++ size_t manufacturer_len = 0; ++ ++ dmidecode = popen ("dmidecode -s system-manufacturer 2>/dev/null", "r"); ++ if (getline (&manufacturer, &manufacturer_len, dmidecode) < 0) { ++ /* ignore; will return NULL */ ++ } ++ pclose (dmidecode); ++ if (manufacturer) { ++ char *newline = strchr (manufacturer, '\n'); ++ if (newline) ++ *newline = '\0'; ++ } ++ return manufacturer; ++#else /* !USE_DMI */ ++ return NULL; ++#endif /* USE_DMI */ ++} ++ ++ + static inline uint32_t + pth_get_size (const PedDevice *dev) + { +@@ -544,16 +578,19 @@ gpt_probe (const PedDevice *dev) + if (dev->length <= 1) + return 0; + +- void *label; +- if (!ptt_read_sector (dev, 0, &label)) +- return 0; +- +- if (!_pmbr_is_valid (label)) ++ if (!is_apple) + { ++ void *label; ++ if (!ptt_read_sector (dev, 0, &label)) ++ return 0; ++ ++ if (!_pmbr_is_valid (label)) ++ { ++ free (label); ++ return 0; ++ } + free (label); +- return 0; + } +- free (label); + + void *pth_raw = ped_malloc (pth_get_size (dev)); + if (ped_device_read (dev, pth_raw, 1, GPT_HEADER_SECTORS) +@@ -973,6 +1010,10 @@ gpt_read_headers (PedDisk const *disk, + * warn if it's not there, and treat the disk as MSDOS, with a note + * for users to use Parted to "fix up" their disk if they + * really want it to be considered GPT. ++ * ++ * Of course, this is incompatible with how Apple handle things. For ++ * legacy BIOS compatibility on Apple machines, we need a valid legacy MBR ++ * rather than a protective one. Aren't standards wonderful? + ************************************************************/ + static int + gpt_read (PedDisk *disk) +@@ -1181,6 +1222,129 @@ _write_pmbr (PedDevice *dev, bool pmbr_boot) + return write_ok; + } + ++static void ++fill_raw_part (PartitionRecord_t* raw_part, PedPartition *part, PedSector offset, int number) ++{ ++ GPTPartitionData* gpt_part_data = part->disk_specific; ++ ++ if (part->fs_type) { ++ if (strncmp (part->fs_type->name, "fat", 3) == 0) ++ raw_part->OSType = 0x0b; ++ else if (strncmp (part->fs_type->name, "ntfs", 4) == 0) ++ raw_part->OSType = 0x07; ++ else if (strncmp (part->fs_type->name, "hfs", 3) == 0) ++ raw_part->OSType = 0xaf; ++ else if (strncmp (part->fs_type->name, "linux-swap", 10) == 0) ++ raw_part->OSType = 0x82; ++ else ++ raw_part->OSType = 0x83; ++ } else ++ raw_part->OSType = 0xda; ++ ++ /* Apple's firmware appears to become unhappy if the second partition ++ isn't bootable */ ++ ++ if (number == 2) ++ raw_part->BootIndicator = 0x80; ++ ++ raw_part->StartingLBA = PED_CPU_TO_LE32 ((part->geom.start - offset) ++ / (part->disk->dev->sector_size / 512)); ++ ++ raw_part->SizeInLBA = PED_CPU_TO_LE32 (part->geom.length ++ / (part->disk->dev->sector_size / 512)); ++ ++ /* EFI system partitions will have a FAT filesystem and ++ PARTITION_SYSTEM_GUID; however, it is not wise to rely on filesystem ++ probing */ ++ ++ if (number == 1) { ++ if (!guid_cmp (gpt_part_data->type, PARTITION_SYSTEM_GUID) || ++ !guid_cmp (gpt_part_data->type, PARTITION_BIOS_GRUB_GUID)) { ++ raw_part->OSType = EFI_PMBR_OSTYPE_EFI; ++ raw_part->OSType = EFI_PMBR_OSTYPE_EFI; ++ } ++ } ++ ++ /* Apple's firmware also appears to be unhappy if the EFI system ++ partition doesn't extend all the way to the start of the disk */ ++ ++ if (number == 1 && raw_part->OSType == EFI_PMBR_OSTYPE_EFI) { ++ raw_part->StartSector = 1; ++ raw_part->SizeInLBA += raw_part->StartingLBA - 1; ++ raw_part->StartingLBA = 1; ++ } else { ++ raw_part->StartHead = 0xfe; ++ raw_part->StartSector = 0xff; ++ raw_part->StartTrack = 0xff; ++ } ++ ++ raw_part->EndHead = 0xfe; ++ raw_part->EndSector = 0xff; ++ raw_part->EndTrack = 0xff; ++} ++ ++static int ++_gptsync (const PedDisk *disk) ++{ ++ void *s0; ++ PedPartition* part; ++ int i; ++ ++ if (!ptt_read_sector (disk->dev, GPT_PMBR_LBA, &s0)) ++ return 0; ++ LegacyMBR_t *pmbr = s0; ++ ++ int ok = 0; ++ ++ memset(&pmbr->PartitionRecord, 0, sizeof(pmbr->PartitionRecord)); ++ pmbr->Signature = PED_CPU_TO_LE16(MSDOS_MBR_SIGNATURE); ++ ++ bool prot = false; /* have we found a protective partition? */ ++ for (i=1; i<=4; i++) { ++ part = ped_disk_get_partition (disk, i); ++ if (!part) ++ continue; ++ ++ fill_raw_part (&pmbr->PartitionRecord [i - 1], part, 0, i); ++ if (pmbr->PartitionRecord[i - 1].OSType == EFI_PMBR_OSTYPE_EFI) ++ prot = true; ++ } ++ ++ if (!prot) { /* create one covering the gpt entries */ ++ uint32_t prot_size; ++ for (i=2; i>=0; i--) ++ pmbr->PartitionRecord[i + 1] = pmbr->PartitionRecord[i]; ++ memset (&pmbr->PartitionRecord[0], 0, sizeof pmbr->PartitionRecord[0]); ++ pmbr->PartitionRecord[0].OSType = EFI_PMBR_OSTYPE_EFI; ++ pmbr->PartitionRecord[0].StartSector = 1; ++ pmbr->PartitionRecord[0].EndHead = 0xfe; ++ pmbr->PartitionRecord[0].EndSector = 0xff; ++ pmbr->PartitionRecord[0].EndTrack = 0xff; ++ pmbr->PartitionRecord[0].StartingLBA = PED_CPU_TO_LE32 (1); ++ if ((disk->dev->length - 1ULL) > 0xFFFFFFFFULL) ++ prot_size = 0xFFFFFFFF; ++ else ++ prot_size = disk->dev->length - 1UL; ++ for (i=1; i<=3; i++) { ++ if (pmbr->PartitionRecord[i].StartingLBA) { ++ uint32_t starting_lba = ++ PED_LE32_TO_CPU (pmbr->PartitionRecord[i].StartingLBA); ++ if (starting_lba - 1 < prot_size) ++ prot_size = starting_lba - 1; ++ } ++ } ++ pmbr->PartitionRecord[0].SizeInLBA = PED_CPU_TO_LE32 (prot_size); ++ } ++ ++ if (!ped_device_write (disk->dev, pmbr, GPT_PMBR_LBA, GPT_PMBR_SECTORS)) ++ goto error; ++ ++ ok = ped_device_sync (disk->dev); ++error: ++ free (s0); ++ return ok; ++} ++ + static int + _generate_header (const PedDisk *disk, int alternate, uint32_t ptes_crc, + GuidPartitionTableHeader_t **gpt_p) +@@ -1287,9 +1451,15 @@ gpt_write (const PedDisk *disk) + + ptes_crc = efi_crc32 (ptes, ptes_bytes); + +- /* Write protective MBR */ +- if (!_write_pmbr (disk->dev, gpt_disk_data->pmbr_boot)) +- goto error_free_ptes; ++ if (is_apple) { ++ /* Write synced MBR */ ++ if (!_gptsync (disk)) ++ goto error_free_ptes; ++ } else { ++ /* Write protective MBR */ ++ if (!_write_pmbr (disk->dev, gpt_disk_data->pmbr_boot)) ++ goto error_free_ptes; ++ } + + /* Write PTH and PTEs */ + /* FIXME: Caution: this code is nearly identical to what's just below. */ +@@ -1938,6 +2108,21 @@ void + ped_disk_gpt_init () + { + ped_disk_type_register (&gpt_disk_type); ++ ++ char *force_gpt_apple = getenv ("PARTED_GPT_APPLE"); ++ if (force_gpt_apple) { ++ if (strcmp (force_gpt_apple, "1") == 0) ++ is_apple = 1; ++ } else { ++ char *manufacturer = dmi_system_manufacturer (); ++ if (manufacturer && ++ (strncasecmp (APPLE_DMI, manufacturer, ++ strlen (APPLE_DMI)) == 0 || ++ strncasecmp (APPLE_DMI_2, manufacturer, ++ strlen (APPLE_DMI_2)) == 0)) ++ is_apple = 1; ++ free (manufacturer); ++ } + } + + void +diff --git a/tests/Makefile.am b/tests/Makefile.am +index da093119..3c1f929a 100644 +--- a/tests/Makefile.am ++++ b/tests/Makefile.am +@@ -32,6 +32,7 @@ TESTS = \ + t0282-gpt-move-backup.sh \ + t0283-overlap-partitions.sh \ + t0290-gpt-name.sh \ ++ t0290-gptsync.sh \ + t0300-dos-on-gpt.sh \ + t0301-overwrite-gpt-pmbr.sh \ + t0350-mac-PT-increases-sector-size.sh \ +diff --git a/tests/t0290-gptsync.sh b/tests/t0290-gptsync.sh +new file mode 100644 +index 00000000..367d61bd +--- /dev/null ++++ b/tests/t0290-gptsync.sh +@@ -0,0 +1,175 @@ ++#!/bin/sh ++# test GPT -> hybrid MBR syncing for Apple systems ++# http://www.rodsbooks.com/gdisk/hybrid.html ++ ++# Copyright (C) 2012 Canonical Ltd. ++ ++# This program is free software; you can redistribute it and/or modify ++# it under the terms of the GNU General Public License as published by ++# the Free Software Foundation; either version 3 of the License, or ++# (at your option) any later version. ++ ++# This program is distributed in the hope that it will be useful, ++# but WITHOUT ANY WARRANTY; without even the implied warranty of ++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++# GNU General Public License for more details. ++ ++# You should have received a copy of the GNU General Public License ++# along with this program. If not, see <http://www.gnu.org/licenses/>. ++ ++if test "$VERBOSE" = yes; then ++ set -x ++ parted --version ++fi ++ ++: ${srcdir=.} ++. $srcdir/t-lib.sh ++ ++require_root_ ++require_scsi_debug_module_ ++ ++ss=$sector_size_ ++# must be big enough for a 32MiB partition in order to be big enough for FAT16 ++n_sectors=131072 ++bootcode_size=446 ++mbr_table_size=$((512 - $bootcode_size)) ++ ++dump_mbr_table () { ++ dd if=$dev bs=1 skip=$bootcode_size count=$mbr_table_size 2>/dev/null | od -v -An -tx1 ++} ++ ++# create memory-backed device ++sectors_per_MiB=$((1024 * 1024 / $ss)) ++n_MiB=$((($n_sectors + $sectors_per_MiB - 1) / $sectors_per_MiB)) ++scsi_debug_setup_ dev_size_mb=$n_MiB > dev-name || ++ skip_test_ 'failed to create scsi_debug device' ++dev=$(cat dev-name) ++ ++# force Apple mode ++export PARTED_GPT_APPLE=1 ++ ++# create gpt label ++parted -s $dev mklabel gpt > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++ ++# print the empty table ++parted -m -s $dev unit s print > t 2>&1 || fail=1 ++sed "s,.*/$dev:,$dev:," t > out || fail=1 ++ ++# check for expected output ++printf "BYT;\n$dev:${n_sectors}s:scsi:$sector_size_:$sector_size_:gpt:Linux scsi_debug;\n" \ ++ > exp || fail=1 ++compare exp out || fail=1 ++ ++# the empty table should have a MBR containing only a protective entry ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff ff 01 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# create a 32MiB FAT16 EFI System Partition ++parted -s $dev mkpart p1 fat16 2048s 67583s set 1 boot on > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++mkfs.vfat -F 16 ${dev}1 >/dev/null || skip_ "mkfs.vfat failed" ++ ++# this is represented as a protective partition, but now it only extends as ++# far as the end of the first partition rather than covering the whole disk ++# (matching refit gptsync's strategy); it still starts at sector one ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff 07 01 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# add a 2MiB ext3 partition ++parted -s $dev mkpart p2 ext3 67584s 71679s > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++mkfs.ext3 ${dev}2 >/dev/null 2>&1 || skip_ "mkfs.ext3 failed" ++ ++# this should have an MBR representing both partitions; the second partition ++# should be marked bootable ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff 07 01 00 ++ 80 fe ff ff 83 fe ff ff 00 08 01 00 00 10 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# add a 1MiB partition with no filesystem ++parted -s $dev mkpart p3 71680s 73727s > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++ ++# the new partition should be represented as 0xda (Non-FS data) ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff 07 01 00 ++ 80 fe ff ff 83 fe ff ff 00 08 01 00 00 10 00 00 ++ 00 fe ff ff da fe ff ff 00 18 01 00 00 08 00 00 ++ 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# add two more 1MiB partitions ++parted -s $dev mkpart p4 73728s 75775s > empty 2>&1 || fail=1 ++parted -s $dev mkpart p5 75776s 77823s > empty 2>&1 || fail=1 ++ ++# only the first four partitions will be represented ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff 07 01 00 ++ 80 fe ff ff 83 fe ff ff 00 08 01 00 00 10 00 00 ++ 00 fe ff ff da fe ff ff 00 18 01 00 00 08 00 00 ++ 00 fe ff ff da fe ff ff 00 20 01 00 00 08 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# convert first partition to a BIOS Boot Partition ++parted -s $dev set 1 boot off set 1 bios_grub on > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++ ++# this should be represented in the same way as an EFI System Partition ++dump_mbr_table > out || fail=1 ++compare exp out || fail=1 ++ ++# convert first partition to an ordinary FAT partition ++parted -s $dev set 1 bios_grub off > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++ ++# this should result in a protective partition covering the GPT data up to ++# the start of the first partition, and then representations of the first ++# three partitions ++dump_mbr_table > out || fail=1 ++cat <<EOF > exp || fail=1 ++ 00 00 01 00 ee fe ff ff 01 00 00 00 ff 07 00 00 ++ 00 fe ff ff 0b fe ff ff 00 08 00 00 00 00 01 00 ++ 80 fe ff ff 83 fe ff ff 00 08 01 00 00 10 00 00 ++ 00 fe ff ff da fe ff ff 00 18 01 00 00 08 00 00 ++ 55 aa ++EOF ++compare exp out || fail=1 ++ ++# convert third partition to a BIOS Boot Partition ++parted -s $dev set 3 bios_grub on > empty 2>&1 || fail=1 ++compare /dev/null empty || fail=1 ++ ++# since this isn't the first partition, it shouldn't become a protective ++# partition or have its starting LBA address set to 1 (and GRUB doesn't care ++# whether it's in the hybrid MBR anyway) ++dump_mbr_table > out || fail=1 ++compare exp out || fail=1 ++ ++Exit $fail diff --git a/debian/patches/kfreebsd-gnu.patch b/debian/patches/kfreebsd-gnu.patch new file mode 100644 index 0000000..609a2a8 --- /dev/null +++ b/debian/patches/kfreebsd-gnu.patch @@ -0,0 +1,1434 @@ +From c55385989caf6e0fcdeb2a2157fbf2a3f3b59459 Mon Sep 17 00:00:00 2001 +From: Viktor Vasilev <Viktor Vasilev> +Date: Fri, 28 Mar 2014 17:09:42 +0000 +Subject: Add GNU/kFreeBSD support + +Author: Robert Millan <rmh@aybabtu.com> +Author: Colin Watson <cjwatson@debian.org> +Author: Jeff Epler <jepler@unpythonic.net> +Bug-Debian: http://bugs.debian.org/363381 +Bug-Debian: http://bugs.debian.org/693510 +Forwarded: no +Last-Update: 2019-10-11 + +Patch-Name: kfreebsd-gnu.patch +--- + configure.ac | 10 +- + libparted/Makefile.am | 3 +- + libparted/arch/freebsd.c | 1292 ++++++++++++++++++++++++++++++ + libparted/architecture.c | 3 + + libparted/fs/xfs/platform_defs.h | 6 +- + libparted/labels/bsd.c | 1 + + libparted/labels/sun.c | 1 + + 7 files changed, 1311 insertions(+), 5 deletions(-) + create mode 100644 libparted/arch/freebsd.c + +diff --git a/configure.ac b/configure.ac +index cf9fb8a5..d838c32c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -62,7 +62,8 @@ case "$host_os" in + linux*|uclinux*) OS=linux ;; + gnu*) OS=gnu ;; + beos*) OS=beos ;; +- *) AC_MSG_ERROR([Unknown or unsupported OS "$host_os". Only "linux", "uclinux", "gnu" and "beos" are supported in this version of GNU Parted.]) ;; ++ freebsd* | kfreebsd*-gnu) OS=freebsd ;; ++ *) AC_MSG_ERROR([Unknown or unsupported OS "$host_os". Only "linux", "gnu" and "beos" are supported in this version of GNU Parted.]) ;; + esac + AC_SUBST([OS]) + +@@ -256,6 +257,7 @@ AC_CHECK_SIZEOF([off_t], [64], [ + #include <sys/types.h> + #include <unistd.h> + ]) ++AC_CHECK_TYPE([loff_t], [long long]) + + AC_ENABLE_SHARED([]) + if test "$OS" = linux && test $ac_cv_sizeof_off_t -lt 8; then +@@ -454,7 +456,7 @@ If you can't find one try: + http://web.mit.edu/tytso/www/linux/e2fsprogs.html])] + ) + +-AC_CHECK_HEADERS([getopt.h]) ++AC_CHECK_HEADERS([getopt.h endian.h sys/endian.h]) + AC_CHECK_HEADERS([linux/ext2_fs.h]) + + dnl required for libparted/llseek.c (TODO: make linux-x86 only) +@@ -513,7 +515,9 @@ AC_C_CONST + AC_C_RESTRICT + + dnl Checks for library functions. +-AC_CHECK_FUNCS([sigaction]) ++if test "$OS" != freebsd; then ++ AC_CHECK_FUNCS([sigaction]) ++fi + AC_CHECK_FUNCS([getuid]) + + dnl NOTE: We need to remove the gl_cv_ignore_unused_libraries flag if we +diff --git a/libparted/Makefile.am b/libparted/Makefile.am +index db29a189..b2b910e1 100644 +--- a/libparted/Makefile.am ++++ b/libparted/Makefile.am +@@ -48,7 +48,8 @@ libparted_la_SOURCES = debug.c \ + EXTRA_libparted_la_SOURCES = arch/linux.c \ + arch/linux.h \ + arch/gnu.c \ +- arch/beos.c ++ arch/beos.c \ ++ arch/freebsd.c + + libparted_la_LIBADD = \ + fs/libfs.la \ +diff --git a/libparted/arch/freebsd.c b/libparted/arch/freebsd.c +new file mode 100644 +index 00000000..4c690e5f +--- /dev/null ++++ b/libparted/arch/freebsd.c +@@ -0,0 +1,1292 @@ ++/* ++ libparted - a library for manipulating disk partitions ++ Copyright (C) 1999 - 2009 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 2 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program; if not, write to the Free Software ++ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA ++*/ ++ ++#include "config.h" ++ ++#include <parted/parted.h> ++#include <parted/debug.h> ++ ++#include <ctype.h> ++#include <errno.h> ++#include <fcntl.h> ++#include <stdint.h> ++#include <stdio.h> ++#include <string.h> ++#include <unistd.h> ++#include <paths.h> ++#include <sys/param.h> ++#include <sys/mount.h> ++#include <sys/ioctl.h> ++#include <sys/sysctl.h> ++#include <sys/stat.h> ++#include <sys/disk.h> ++#include <sys/ata.h> ++#include <cam/cam.h> ++#include <cam/scsi/scsi_pass.h> ++ ++#include "../architecture.h" ++ ++#if ENABLE_NLS ++# include <libintl.h> ++# define _(String) dgettext (PACKAGE, String) ++#else ++# define _(String) (String) ++#endif /* ENABLE_NLS */ ++ ++#if !defined(__FreeBSD_version) && defined(__FreeBSD_kernel_version) ++#define __FreeBSD_version __FreeBSD_kernel_version ++#endif ++ ++#define FREEBSD_SPECIFIC(dev) ((FreeBSDSpecific*) (dev)->arch_specific) ++ ++typedef struct _FreeBSDSpecific FreeBSDSpecific; ++ ++struct _FreeBSDSpecific { ++ int fd; ++ long long phys_sector_size; ++}; ++ ++static char* _device_get_part_path (PedDevice* dev, int num); ++static int _partition_is_mounted_by_path (const char* path); ++ ++static int ++_device_stat (PedDevice* dev, struct stat * dev_stat) ++{ ++ PED_ASSERT (dev != NULL); ++ PED_ASSERT (!dev->external_mode); ++ ++ while (1) { ++ if (!stat (dev->path, dev_stat)) { ++ return 1; ++ } else { ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_CANCEL, ++ _("Could not stat device %s - %s."), ++ dev->path, ++ strerror (errno)) ++ != PED_EXCEPTION_RETRY) ++ return 0; ++ } ++ } ++} ++ ++static int ++_device_probe_type (PedDevice* dev) ++{ ++ struct stat dev_stat; ++ char *np; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ return 0; ++ ++ if (!S_ISCHR(dev_stat.st_mode)) { ++ dev->type = PED_DEVICE_FILE; ++ return 1; ++ } ++ ++ np = strrchr(dev->path, '/'); ++ if (np == NULL) { ++ dev->type = PED_DEVICE_UNKNOWN; ++ return 0; ++ } ++ np += 1; /* advance past '/' */ ++ ++ if (strncmp(np, "ada", 3) == 0) { ++ dev->type = PED_DEVICE_SCSI; ++ } else if (strncmp(np, "ad", 2) == 0) { ++ dev->type = PED_DEVICE_IDE; ++ } else if (strncmp(np, "da", 2) == 0) { ++ dev->type = PED_DEVICE_SCSI; ++ } else if (strncmp(np, "acd", 2) == 0 || ++ strncmp(np, "cd", 2) == 0) { ++ /* ignore CD-ROM drives */ ++ dev->type = PED_DEVICE_UNKNOWN; ++ return 0; ++ } else { ++ dev->type = PED_DEVICE_UNKNOWN; ++ } ++ ++ return 1; ++} ++ ++static void ++_device_set_sector_size (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ int sector_size; ++ ++ dev->sector_size = PED_SECTOR_SIZE_DEFAULT; ++ dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT; ++ ++ PED_ASSERT (dev->open_count); ++ ++ if (ioctl (arch_specific->fd, DIOCGSECTORSIZE, §or_size)) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Could not determine sector size for %s: %s.\n" ++ "Using the default sector size (%lld)."), ++ dev->path, strerror (errno), PED_SECTOR_SIZE_DEFAULT); ++ } else { ++ dev->sector_size = (long long)sector_size;; ++ } ++ ++ if (arch_specific->phys_sector_size) ++ dev->phys_sector_size = arch_specific->phys_sector_size; ++ ++ if (sector_size != PED_SECTOR_SIZE_DEFAULT) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Device %s has a logical sector size of %lld. Not " ++ "all parts of GNU Parted support this at the moment, " ++ "and the working code is HIGHLY EXPERIMENTAL.\n"), ++ dev->path, dev->sector_size); ++ } ++} ++ ++static PedSector ++_device_get_length (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ off_t bytes = 0; ++ ++ PED_ASSERT (dev->open_count > 0); ++ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); ++ ++ if(ioctl(arch_specific->fd, DIOCGMEDIASIZE, &bytes) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_BUG, ++ PED_EXCEPTION_CANCEL, ++ _("Unable to determine the size of %s (%s)."), ++ dev->path, ++ strerror (errno)); ++ return 0; ++ } ++ ++ return bytes / dev->sector_size; ++} ++ ++ ++static int ++_device_probe_geometry (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ struct stat dev_stat; ++ struct ata_params params; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ return 0; ++ PED_ASSERT (S_ISCHR (dev_stat.st_mode)); ++ ++ _device_set_sector_size (dev); ++ ++ dev->length = _device_get_length (dev); ++ if (!dev->length) ++ return 0; ++ ++ dev->bios_geom.sectors = 63; ++ dev->bios_geom.heads = 255; ++ dev->bios_geom.cylinders ++ = dev->length / (63 * 255); ++ ++ if (ioctl (arch_specific->fd, IOCATAGPARM, ¶ms) != 0) { ++ dev->hw_geom.sectors = params.sectors; ++ dev->hw_geom.heads = params.heads; ++ dev->hw_geom.cylinders = params.cylinders; ++ } else { ++ dev->hw_geom = dev->bios_geom; ++ } ++ ++ return 1; ++} ++ ++static char* ++strip_name(char* str) ++{ ++ int i; ++ int end = 0; ++ ++ for (i = 0; str[i] != 0; i++) { ++ if (!isspace (str[i]) ++ || (isspace (str[i]) && !isspace (str[i+1]) && str[i+1])) { ++ str [end] = str[i]; ++ end++; ++ } ++ } ++ str[end] = 0; ++ return strdup (str); ++} ++ ++static int ++init_ide (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ struct stat dev_stat; ++ struct ata_params params; ++ PedExceptionOption ex_status; ++ char vendor_buf[64]; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ goto error; ++ ++ if (!ped_device_open (dev)) ++ goto error; ++ ++ if (ioctl (arch_specific->fd, IOCATAGPARM, ¶ms) != 0) { ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Could not get identity of device %s - %s"), ++ dev->path, strerror (errno)); ++ switch (ex_status) { ++ case PED_EXCEPTION_CANCEL: ++ goto error_close_dev; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_IGNORE: ++ dev->model = strdup(_("Generic IDE")); ++ break; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } else { ++ snprintf(vendor_buf, 64, "%.40s/%.8s", params.model, params.revision); ++ dev->model = strip_name (vendor_buf); ++ } ++ ++ if (!_device_probe_geometry (dev)) ++ goto error_close_dev; ++ ++ ped_device_close (dev); ++ return 1; ++ ++error_close_dev: ++ ped_device_close (dev); ++error: ++ return 0; ++} ++ ++static char * ++_scsi_pass_dev (PedDevice* dev) ++{ ++ union ccb ccb; ++ int fd; ++ char result[64]; ++ ++ if (sscanf (dev->path, "/dev/%2s%u", ccb.cgdl.periph_name, &ccb.cgdl.unit_number) != 2 && ++ sscanf (dev->path, "/dev/%3s%u", ccb.cgdl.periph_name, &ccb.cgdl.unit_number) != 2) ++ goto error; ++ ++ if ((fd = open("/dev/xpt0", O_RDWR)) < 0) ++ goto error; ++ ++ ccb.ccb_h.func_code = XPT_GDEVLIST; ++ if (ioctl(fd, CAMGETPASSTHRU, &ccb) != 0) ++ goto error_close_dev; ++ ++ snprintf(result, sizeof(result), "/dev/%s%d", ccb.cgdl.periph_name, ccb.cgdl.unit_number); ++ close(fd); ++ return strdup(result); ++ ++error_close_dev: ++ close(fd); ++error: ++ return NULL; ++} ++ ++static uint32_t ++local_ata_logical_sector_size(struct ata_params *ident_data) ++{ ++ if ((ident_data->pss & 0xc000) == 0x4000 && ++ (ident_data->pss & ATA_PSS_LSSABOVE512)) { ++ return ((u_int32_t)ident_data->lss_1 | ++ ((u_int32_t)ident_data->lss_2 << 16)); ++ } ++ return (512); ++} ++ ++static uint64_t ++local_ata_physical_sector_size(struct ata_params *ident_data) ++{ ++ if ((ident_data->pss & 0xc000) == 0x4000 && ++ (ident_data->pss & ATA_PSS_MULTLS)) { ++ return ((uint64_t)local_ata_logical_sector_size(ident_data) * ++ (1 << (ident_data->pss & ATA_PSS_LSPPS))); ++ } ++ return (512); ++} ++ ++static int ++init_scsi (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ PedExceptionOption ex_status; ++ struct stat dev_stat; ++ char* pass_dev; ++ int pass_fd; ++ union ccb ccb; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ goto error; ++ ++ if (!ped_device_open (dev)) ++ goto error; ++ ++ pass_dev = _scsi_pass_dev(dev); ++ if (!pass_dev) ++ goto error_close_dev; ++ ++ pass_fd = open(pass_dev, O_RDWR); ++ if (pass_fd < 0) { ++ dev->host = 0; ++ dev->did = 0; ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Error initialising SCSI device %s - %s"), ++ dev->path, strerror (errno)) ++ != PED_EXCEPTION_IGNORE) ++ goto error_close_dev; ++ if (!_device_probe_geometry (dev)) ++ goto error_close_dev; ++ ped_device_close (dev); ++ return 1; ++ } ++ ++ ccb.ccb_h.func_code = XPT_GDEVLIST; ++ if (ioctl(pass_fd, CAMGETPASSTHRU, &ccb) != 0) { ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Could not get ID of devices %s - %s"), ++ dev->path, strerror (errno)); ++ switch (ex_status) { ++ case PED_EXCEPTION_CANCEL: ++ goto error_close_fd_dev; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_IGNORE: ++ dev->host = 0; ++ dev->did = 0; ++ break; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ ++ dev->host = ccb.ccb_h.target_id; ++ dev->did = ccb.ccb_h.target_lun; ++ ++ ccb.ccb_h.func_code = XPT_GDEV_TYPE; ++ if (ioctl(pass_fd, CAMIOCOMMAND, &ccb) != 0) { ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Could not get identity of device %s - %s"), ++ dev->path, strerror (errno)); ++ switch (ex_status) { ++ case PED_EXCEPTION_CANCEL: ++ goto error_close_fd_dev; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_IGNORE: ++ dev->model = strdup(_("Generic SCSI")); ++ break; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } else { ++ size_t model_length = (8 + 16 + 2); ++ dev->model = (char*) ped_malloc (model_length); ++ if (!dev->model) ++ goto error_close_fd_dev; ++ if (ccb.cgd.protocol == PROTO_ATA && *ccb.cgd.ident_data.model) { ++ snprintf (dev->model, model_length, "%s", ccb.cgd.ident_data.model); ++ arch_specific->phys_sector_size = local_ata_physical_sector_size(&ccb.cgd.ident_data); ++ } else { ++ snprintf (dev->model, model_length, "%.8s %.16s", ccb.cgd.inq_data.vendor, ccb.cgd.inq_data.product); ++ } ++ } ++ ++ if (!_device_probe_geometry (dev)) ++ goto error_close_fd_dev; ++ ++ close (pass_fd); ++ ped_device_close (dev); ++ return 1; ++ ++error_close_fd_dev: ++ close (pass_fd); ++error_close_dev: ++ ped_device_close (dev); ++error: ++ return 0; ++} ++ ++static int ++init_file (PedDevice* dev) ++{ ++ struct stat dev_stat; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ goto error; ++ if (!ped_device_open (dev)) ++ goto error; ++ ++ if (S_ISCHR(dev_stat.st_mode)) ++ dev->length = _device_get_length (dev); ++ else ++ dev->length = dev_stat.st_size / 512; ++ if (dev->length <= 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_CANCEL, ++ _("The device %s is zero-length, and can't possibly " ++ "store a file system or partition table. Perhaps " ++ "you selected the wrong device?"), ++ dev->path); ++ goto error_close_dev; ++ } ++ ++ ped_device_close (dev); ++ ++ dev->bios_geom.cylinders = dev->length / 4 / 32; ++ dev->bios_geom.heads = 4; ++ dev->bios_geom.sectors = 32; ++ dev->hw_geom = dev->bios_geom; ++ dev->sector_size = PED_SECTOR_SIZE_DEFAULT; ++ dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT; ++ dev->model = strdup (""); ++ ++ return 1; ++ ++error_close_dev: ++ ped_device_close (dev); ++error: ++ return 0; ++} ++ ++static int ++init_generic (PedDevice* dev, char* model_name) ++{ ++ struct stat dev_stat; ++ PedExceptionOption ex_status; ++ ++ if (!_device_stat (dev, &dev_stat)) ++ goto error; ++ ++ if (!ped_device_open (dev)) ++ goto error; ++ ++ ped_exception_fetch_all (); ++ if (_device_probe_geometry (dev)) { ++ ped_exception_leave_all (); ++ } else { ++ /* hack to allow use of files, for testing */ ++ ped_exception_catch (); ++ ped_exception_leave_all (); ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Unable to determine geometry of " ++ "file/device. You should not use Parted " ++ "unless you REALLY know what you're doing!")); ++ switch (ex_status) { ++ case PED_EXCEPTION_CANCEL: ++ goto error_close_dev; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_IGNORE: ++ break; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ ++ /* what should we stick in here? */ ++ dev->length = dev_stat.st_size / PED_SECTOR_SIZE_DEFAULT; ++ dev->bios_geom.cylinders = dev->length / 4 / 32; ++ dev->bios_geom.heads = 4; ++ dev->bios_geom.sectors = 32; ++ dev->sector_size = PED_SECTOR_SIZE_DEFAULT; ++ dev->phys_sector_size = PED_SECTOR_SIZE_DEFAULT; ++ } ++ ++ dev->model = strdup (model_name); ++ ++ ped_device_close (dev); ++ return 1; ++ ++error_close_dev: ++ ped_device_close (dev); ++error: ++ return 0; ++} ++ ++static PedDevice* ++freebsd_new (const char* path) ++{ ++ PedDevice* dev; ++ ++ PED_ASSERT (path != NULL); ++ ++ dev = (PedDevice*) ped_malloc (sizeof (PedDevice)); ++ if (!dev) ++ goto error; ++ ++ dev->path = strdup (path); ++ if (!dev->path) ++ goto error_free_dev; ++ ++ dev->arch_specific ++ = (FreeBSDSpecific*) ped_malloc (sizeof (FreeBSDSpecific)); ++ if (!dev->arch_specific) ++ goto error_free_path; ++ ++ memset(dev->arch_specific, 0, sizeof(FreeBSDSpecific)); ++ ++ dev->open_count = 0; ++ dev->read_only = 0; ++ dev->external_mode = 0; ++ dev->dirty = 0; ++ dev->boot_dirty = 0; ++ ++ if (!_device_probe_type (dev)) ++ goto error_free_arch_specific; ++ ++ switch (dev->type) { ++ case PED_DEVICE_IDE: ++ if (!init_ide (dev)) ++ goto error_free_arch_specific; ++ break; ++ case PED_DEVICE_SCSI: ++ if (!init_scsi (dev)) ++ goto error_free_arch_specific; ++ break; ++ case PED_DEVICE_FILE: ++ if (!init_file (dev)) ++ goto error_free_arch_specific; ++ break; ++ case PED_DEVICE_UNKNOWN: ++ if (!init_generic (dev, _("Unknown"))) ++ goto error_free_arch_specific; ++ break; ++ ++ default: ++ ped_exception_throw (PED_EXCEPTION_NO_FEATURE, ++ PED_EXCEPTION_CANCEL, ++ _("ped_device_new() Unsupported device type")); ++ goto error_free_arch_specific; ++ } ++ return dev; ++ ++error_free_arch_specific: ++ free (dev->arch_specific); ++error_free_path: ++ free (dev->path); ++error_free_dev: ++ free (dev); ++error: ++ return NULL; ++} ++ ++static void ++freebsd_destroy (PedDevice* dev) ++{ ++ free (dev->arch_specific); ++ free (dev->path); ++ free (dev->model); ++ free (dev); ++} ++ ++static int ++freebsd_is_busy (PedDevice* dev) ++{ ++ int i; ++ char* part_name; ++ ++ if (_partition_is_mounted_by_path (dev->path)) ++ return 1; ++ ++ for (i = 0; i < 32; i++) { ++ int status; ++ ++ part_name = _device_get_part_path (dev, i); ++ if (!part_name) ++ return 1; ++ status = _partition_is_mounted_by_path (part_name); ++ free (part_name); ++ ++ if (status) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static void ++_flush_cache (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ ++ if (dev->read_only) ++ return; ++ dev->dirty = 0; ++ ++ if (dev->type == PED_DEVICE_FILE) { ++ if (fsync(arch_specific->fd) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Could not flush cache of file %s - %s."), ++ dev->path, ++ strerror (errno)); ++ return; ++ } ++ } else { ++ if (ioctl (arch_specific->fd, DIOCGFLUSH) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Could not flush cache of device %s - %s."), ++ dev->path, ++ strerror (errno)); ++ return; ++ } ++ } ++ ++ return; ++} ++ ++/* By default, kernel of FreeBSD does not allow overwriting MBR */ ++#define GEOM_SYSCTL "kern.geom.debugflags" ++ ++static int ++freebsd_open (PedDevice* dev) ++{ ++ int old_flags, flags; ++ size_t flagssize; ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ ++retry: ++ flagssize = sizeof (old_flags); ++ ++ if (sysctlbyname (GEOM_SYSCTL, &old_flags, &flagssize, NULL, 0) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Unable to get %s sysctl (%s)."), ++ GEOM_SYSCTL, ++ strerror (errno)); ++ } ++ ++ if ((old_flags & 0x10) == 0) { ++ /* "allow foot shooting", see geom(4) */ ++ flags = old_flags | 0x10; ++ ++ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &flags, sizeof (int)) != 0) { ++ flags = old_flags; ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Unable to set %s sysctl (%s)."), ++ GEOM_SYSCTL, ++ strerror (errno)); ++ } ++ } else ++ flags = old_flags; ++ ++ arch_specific->fd = open (dev->path, O_RDWR); ++ ++ if (flags != old_flags) { ++ if (sysctlbyname (GEOM_SYSCTL, NULL, NULL, &old_flags, sizeof (int)) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Unable to set %s sysctl (%s)."), ++ GEOM_SYSCTL, ++ strerror (errno)); ++ } ++ } ++ ++ if (arch_specific->fd == -1) { ++ char* rw_error_msg = strerror (errno); ++ ++ arch_specific->fd = open (dev->path, O_RDONLY); ++ ++ if (arch_specific->fd == -1) { ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_CANCEL, ++ _("Error opening %s: %s"), ++ dev->path, strerror (errno)) ++ != PED_EXCEPTION_RETRY) { ++ return 0; ++ } else { ++ goto retry; ++ } ++ } else { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Unable to open %s read-write (%s). %s has " ++ "been opened read-only."), ++ dev->path, rw_error_msg, dev->path); ++ dev->read_only = 1; ++ } ++ } else { ++ dev->read_only = 0; ++ } ++ ++ _flush_cache (dev); ++ ++ return 1; ++} ++ ++static int ++freebsd_refresh_open (PedDevice* dev) ++{ ++ return 1; ++} ++ ++static int ++freebsd_close (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ ++ if (dev->dirty) ++ _flush_cache (dev); ++ close (arch_specific->fd); ++ return 1; ++} ++ ++static int ++freebsd_refresh_close (PedDevice* dev) ++{ ++ if (dev->dirty) ++ _flush_cache (dev); ++ return 1; ++} ++ ++static int ++_device_seek (const PedDevice* dev, PedSector sector) ++{ ++ FreeBSDSpecific* arch_specific; ++ off_t pos; ++ ++ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); ++ PED_ASSERT (dev != NULL); ++ PED_ASSERT (!dev->external_mode); ++ ++ arch_specific = FREEBSD_SPECIFIC (dev); ++ ++ pos = sector * dev->sector_size; ++ return lseek (arch_specific->fd, pos, SEEK_SET) == pos; ++} ++ ++static int ++freebsd_read (const PedDevice* dev, void* buffer, PedSector start, ++ PedSector count) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ PedExceptionOption ex_status; ++ void* diobuf = NULL; ++ ++ PED_ASSERT (dev != NULL); ++ PED_ASSERT (dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); ++ ++ while (1) { ++ if (_device_seek (dev, start)) ++ break; ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_IGNORE_CANCEL, ++ _("%s during seek for read on %s"), ++ strerror (errno), dev->path); ++ ++ switch (ex_status) { ++ case PED_EXCEPTION_IGNORE: ++ return 1; ++ ++ case PED_EXCEPTION_RETRY: ++ break; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_CANCEL: ++ return 0; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ ++ size_t read_length = count * dev->sector_size; ++ if (posix_memalign (&diobuf, dev->sector_size, read_length) != 0) ++ return 0; ++ ++ while (1) { ++ ssize_t status = read (arch_specific->fd, diobuf, read_length); ++ if (status > 0) { ++ memcpy(buffer, diobuf, status); ++ } ++ if (status == (ssize_t) read_length) ++ break; ++ if (status > 0) { ++ read_length -= status; ++ buffer = (char *) buffer + status; ++ continue; ++ } ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_IGNORE_CANCEL, ++ _("%s during read on %s"), ++ strerror (errno), ++ dev->path); ++ ++ switch (ex_status) { ++ case PED_EXCEPTION_IGNORE: ++ return 1; ++ ++ case PED_EXCEPTION_RETRY: ++ break; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_CANCEL: ++ return 0; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ ++ free (diobuf); ++ ++ return 1; ++} ++ ++static int ++freebsd_write (PedDevice* dev, const void* buffer, PedSector start, ++ PedSector count) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ PedExceptionOption ex_status; ++ void* diobuf; ++ void* diobuf_start; ++ ++ PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0); ++ ++ if (dev->read_only) { ++ if (ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_IGNORE_CANCEL, ++ _("Can't write to %s, because it is opened read-only."), ++ dev->path) ++ != PED_EXCEPTION_IGNORE) ++ return 0; ++ else ++ return 1; ++ } ++ ++ while (1) { ++ if (_device_seek (dev, start)) ++ break; ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_ERROR, PED_EXCEPTION_RETRY_IGNORE_CANCEL, ++ _("%s during seek for write on %s"), ++ strerror (errno), dev->path); ++ ++ switch (ex_status) { ++ case PED_EXCEPTION_IGNORE: ++ return 1; ++ ++ case PED_EXCEPTION_RETRY: ++ break; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_CANCEL: ++ return 0; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ ++#ifdef READ_ONLY ++ printf ("ped_device_write (\"%s\", %p, %d, %d)\n", ++ dev->path, buffer, (int) start, (int) count); ++#else ++ size_t write_length = count * dev->sector_size; ++ dev->dirty = 1; ++ if (posix_memalign(&diobuf, dev->sector_size, write_length) != 0) ++ return 0; ++ memcpy(diobuf, buffer, write_length); ++ diobuf_start = diobuf; ++ while (1) { ++ ssize_t status = write (arch_specific->fd, diobuf, write_length); ++ if (status == count * PED_SECTOR_SIZE_DEFAULT) break; ++ if (status > 0) { ++ write_length -= status; ++ diobuf = (char *) diobuf + status; ++ continue; ++ } ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_IGNORE_CANCEL, ++ _("%s during write on %s"), ++ strerror (errno), dev->path); ++ ++ switch (ex_status) { ++ case PED_EXCEPTION_IGNORE: ++ return 1; ++ ++ case PED_EXCEPTION_RETRY: ++ break; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_CANCEL: ++ return 0; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ free(diobuf_start); ++#endif /* !READ_ONLY */ ++ return 1; ++} ++ ++/* returns the number of sectors that are ok. ++ */ ++static PedSector ++freebsd_check (PedDevice* dev, void* buffer, PedSector start, PedSector count) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ PedSector done = 0; ++ int status; ++ void* diobuf; ++ ++ if (!_device_seek (dev, start)) ++ return 0; ++ ++ if (posix_memalign(&diobuf, PED_SECTOR_SIZE_DEFAULT, ++ count * PED_SECTOR_SIZE_DEFAULT) != 0) ++ return 0; ++ ++ for (done = 0; done < count; done += status / dev->sector_size) { ++ status = read (arch_specific->fd, diobuf, ++ (size_t) ((count-done) * dev->sector_size)); ++ if (status > 0) ++ memcpy(buffer, diobuf, status); ++ if (status < 0) ++ break; ++ } ++ free(diobuf); ++ ++ return done; ++} ++ ++static int ++_do_fsync (PedDevice* dev) ++{ ++ FreeBSDSpecific* arch_specific = FREEBSD_SPECIFIC (dev); ++ int status; ++ PedExceptionOption ex_status; ++ ++ while (1) { ++ status = fsync (arch_specific->fd); ++ if (status >= 0) break; ++ ++ ex_status = ped_exception_throw ( ++ PED_EXCEPTION_ERROR, ++ PED_EXCEPTION_RETRY_IGNORE_CANCEL, ++ _("%s during write on %s"), ++ strerror (errno), dev->path); ++ ++ switch (ex_status) { ++ case PED_EXCEPTION_IGNORE: ++ return 1; ++ ++ case PED_EXCEPTION_RETRY: ++ break; ++ ++ case PED_EXCEPTION_UNHANDLED: ++ ped_exception_catch (); ++ case PED_EXCEPTION_CANCEL: ++ return 0; ++ default: ++ PED_ASSERT (0); ++ break; ++ } ++ } ++ return 1; ++} ++ ++static int ++freebsd_sync (PedDevice* dev) ++{ ++ PED_ASSERT (dev != NULL); ++ PED_ASSERT (!dev->external_mode); ++ ++ if (dev->read_only) ++ return 1; ++ if (!_do_fsync (dev)) ++ return 0; ++ _flush_cache (dev); ++ return 1; ++} ++ ++static int ++freebsd_sync_fast (PedDevice* dev) ++{ ++ PED_ASSERT (dev != NULL); ++ PED_ASSERT (!dev->external_mode); ++ ++ if (dev->read_only) ++ return 1; ++ if (!_do_fsync (dev)) ++ return 0; ++ /* no cache flush... */ ++ return 1; ++} ++ ++static int ++_probe_standard_devices () ++{ ++ /* Add standard devices that are not autodetected here. */ ++ return 1; ++} ++ ++static int ++_probe_kern_disks () ++{ ++ size_t listsize; ++ char *disklist, *pdisklist, *psave; ++ ++ if (sysctlbyname("kern.disks", NULL, &listsize, NULL, 0) != 0) { ++ ped_exception_throw ( ++ PED_EXCEPTION_WARNING, ++ PED_EXCEPTION_OK, ++ _("Could not get the list of devices through kern.disks sysctl.")); ++ return 0; ++ } ++ ++ if (listsize == 0) ++ return 0; ++ ++ disklist = ped_malloc(listsize + 1); ++ if (!disklist) ++ return 0; ++ ++ if (sysctlbyname("kern.disks", disklist, &listsize, NULL, 0) != 0) { ++ free(disklist); ++ return 0; ++ } ++ ++ for (pdisklist = disklist ; ; pdisklist = NULL) { ++ char dev_name [256]; ++ char *token; ++ ++ token = strtok_r(pdisklist, " ", &psave); ++ if (token == NULL) ++ break; ++ ++ strncpy (dev_name, _PATH_DEV, sizeof(dev_name)); ++ strncat (dev_name, token, sizeof(dev_name) - strlen(_PATH_DEV) - 1); ++ dev_name[sizeof(dev_name) - 1] = '\0'; ++ _ped_device_probe (dev_name); ++ } ++ ++ free(disklist); ++ return 1; ++} ++ ++static void ++freebsd_probe_all () ++{ ++ _probe_standard_devices (); ++ ++ _probe_kern_disks (); ++} ++ ++static char* ++_device_get_part_path (PedDevice* dev, int num) ++{ ++ int path_len = strlen (dev->path); ++ int result_len = path_len + 16; ++ int is_gpt; ++ char* result; ++ PedDisk* disk; ++ ++ disk = ped_disk_new (dev); ++ if (!disk) ++ return NULL; ++ ++ result = (char*) ped_malloc (result_len); ++ if (!result) ++ return NULL; ++ ++ is_gpt = !strcmp (disk->type->name, "gpt"); ++ ++ ped_disk_destroy (disk); ++ ++ /* append slice number (ad0, partition 1 => ad0s1)*/ ++ snprintf (result, result_len, is_gpt ? "%sp%d" : "%ss%d", dev->path, num); ++ ++ return result; ++} ++ ++static char* ++freebsd_partition_get_path (const PedPartition* part) ++{ ++ return _device_get_part_path (part->disk->dev, part->num); ++} ++ ++static int ++_partition_is_mounted_by_dev (dev_t dev) ++{ ++ struct stat mntdevstat; ++ struct statfs *mntbuf, *statfsp; ++ char *devname; ++ char device[256]; ++ int mntsize, i; ++ ++ mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); ++ for (i = 0; i < mntsize; i++) { ++ statfsp = &mntbuf[i]; ++ devname = statfsp->f_mntfromname; ++ if (*devname != '/') { ++ strcpy(device, _PATH_DEV); ++ strcat(device, devname); ++ strcpy(statfsp->f_mntfromname, device); ++ } ++ if (stat(devname, &mntdevstat) == 0 && ++ mntdevstat.st_rdev == dev) ++ return 1; ++ } ++ ++ return 0; ++} ++ ++static int ++_partition_is_mounted_by_path (const char *path) ++{ ++ struct stat part_stat; ++ if (stat (path, &part_stat) != 0) ++ return 0; ++ if (!S_ISCHR(part_stat.st_mode)) ++ return 0; ++ return _partition_is_mounted_by_dev (part_stat.st_rdev); ++} ++ ++static int ++_partition_is_mounted (const PedPartition *part) ++{ ++ int status; ++ char* part_name; ++ ++ if (!ped_partition_is_active (part)) ++ return 0; ++ part_name = _device_get_part_path (part->disk->dev, part->num); ++ if (!part_name) ++ return 0; ++ status = _partition_is_mounted_by_path (part_name); ++ free (part_name); ++ return status; ++} ++ ++static int ++freebsd_partition_is_busy (const PedPartition* part) ++{ ++ PedPartition* walk; ++ ++ PED_ASSERT (part != NULL); ++ ++ if (_partition_is_mounted (part)) ++ return 1; ++ if (part->type == PED_PARTITION_EXTENDED) { ++ for (walk = part->part_list; walk; walk = walk->next) { ++ if (freebsd_partition_is_busy (walk)) ++ return 1; ++ } ++ } ++ return 0; ++} ++ ++static int ++_kernel_reread_part_table (PedDevice* dev) ++{ ++ /* The FreeBSD kernel (at least the 7.x series) automatically ++ monitors the partition tables and re-read them if they ++ change. */ ++ return 1; ++} ++ ++static int ++freebsd_disk_commit (PedDisk* disk) ++{ ++ if (disk->dev->type != PED_DEVICE_FILE) ++ return _kernel_reread_part_table (disk->dev); ++ ++ return 1; ++} ++ ++static PedDeviceArchOps freebsd_dev_ops = { ++ _new: freebsd_new, ++ destroy: freebsd_destroy, ++ is_busy: freebsd_is_busy, ++ open: freebsd_open, ++ refresh_open: freebsd_refresh_open, ++ close: freebsd_close, ++ refresh_close: freebsd_refresh_close, ++ read: freebsd_read, ++ write: freebsd_write, ++ check: freebsd_check, ++ sync: freebsd_sync, ++ sync_fast: freebsd_sync_fast, ++ probe_all: freebsd_probe_all ++}; ++ ++PedDiskArchOps freebsd_disk_ops = { ++ partition_get_path: freebsd_partition_get_path, ++ partition_is_busy: freebsd_partition_is_busy, ++ disk_commit: freebsd_disk_commit ++}; ++ ++PedArchitecture ped_freebsd_arch = { ++ dev_ops: &freebsd_dev_ops, ++ disk_ops: &freebsd_disk_ops ++}; +diff --git a/libparted/architecture.c b/libparted/architecture.c +index 4020f98b..824ece69 100644 +--- a/libparted/architecture.c ++++ b/libparted/architecture.c +@@ -34,6 +34,9 @@ ped_set_architecture () + #elif defined(__BEOS__) + extern PedArchitecture ped_beos_arch; + const PedArchitecture* arch = &ped_beos_arch; ++#elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) ++ extern PedArchitecture ped_freebsd_arch; ++ const PedArchitecture* arch = &ped_freebsd_arch; + #else + extern PedArchitecture ped_gnu_arch; + const PedArchitecture* arch = &ped_gnu_arch; +diff --git a/libparted/fs/xfs/platform_defs.h b/libparted/fs/xfs/platform_defs.h +index a6ec8fb8..47a3a55f 100644 +--- a/libparted/fs/xfs/platform_defs.h ++++ b/libparted/fs/xfs/platform_defs.h +@@ -37,7 +37,11 @@ + #include <stdio.h> + #include <stdarg.h> + #include <assert.h> +-#include <endian.h> ++#if HAVE_ENDIAN_H ++# include <endian.h> ++#elif HAVE_SYS_ENDIAN_H ++# include <sys/endian.h> ++#endif + #include <fcntl.h> + #include <stddef.h> + #include <stdlib.h> +diff --git a/libparted/labels/bsd.c b/libparted/labels/bsd.c +index 38bc64c1..bd36babc 100644 +--- a/libparted/labels/bsd.c ++++ b/libparted/labels/bsd.c +@@ -27,6 +27,7 @@ + #include <parted/debug.h> + #include <parted/endian.h> + #include <stdbool.h> ++#include <sys/types.h> + + #if ENABLE_NLS + # include <libintl.h> +diff --git a/libparted/labels/sun.c b/libparted/labels/sun.c +index 5ed28869..09b82cbe 100644 +--- a/libparted/labels/sun.c ++++ b/libparted/labels/sun.c +@@ -26,6 +26,7 @@ + #include <parted/debug.h> + #include <parted/endian.h> + #include <stdbool.h> ++#include <sys/types.h> + + #if ENABLE_NLS + # include <libintl.h> diff --git a/debian/patches/kfreebsd_lvm.patch b/debian/patches/kfreebsd_lvm.patch new file mode 100644 index 0000000..145d050 --- /dev/null +++ b/debian/patches/kfreebsd_lvm.patch @@ -0,0 +1,55 @@ +From 10e3164ce61e959817683edf52c1f1206f82ef0c Mon Sep 17 00:00:00 2001 +From: Colin Watson <cjwatson@ubuntu.com> +Date: Fri, 28 Mar 2014 17:09:52 +0000 +Subject: Add LVM support on kFreeBSD + +Patch-Name: kfreebsd_lvm.patch +--- + libparted/arch/freebsd.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/libparted/arch/freebsd.c b/libparted/arch/freebsd.c +index b78d2bb0..f7061c74 100644 +--- a/libparted/arch/freebsd.c ++++ b/libparted/arch/freebsd.c +@@ -1178,6 +1178,31 @@ _probe_zfs_volumes () + return 1; + } + ++static int ++_probe_lvm_volumes () ++{ ++ DIR* lvm_dir; ++ struct dirent* lvm_dent; ++ char buf[PATH_MAX]; ++ struct stat st; ++ ++ lvm_dir = opendir ("/dev/linux_lvm"); ++ if (!lvm_dir) ++ return 0; ++ ++ while ((lvm_dent = readdir (lvm_dir))) { ++ if (strcmp (lvm_dent->d_name, ".") == 0 || strcmp (lvm_dent->d_name, "..") == 0) ++ continue; ++ snprintf (buf, sizeof (buf), "/dev/linux_lvm/%s", lvm_dent->d_name); ++ if (stat (buf, &st) != 0) ++ continue; ++ _ped_device_probe (buf); ++ } ++ closedir (lvm_dir); ++ ++ return 1; ++} ++ + static void + freebsd_probe_all () + { +@@ -1186,6 +1211,8 @@ freebsd_probe_all () + _probe_kern_disks (); + + _probe_zfs_volumes (); ++ ++ _probe_lvm_volumes (); + } + + static char* diff --git a/debian/patches/link-libuuid.patch b/debian/patches/link-libuuid.patch new file mode 100644 index 0000000..3b6e9ca --- /dev/null +++ b/debian/patches/link-libuuid.patch @@ -0,0 +1,32 @@ +From e7662734df72abed3e10dcb032d3fd7284e0e868 Mon Sep 17 00:00:00 2001 +From: Yegor Yefremov <yegorslists@googlemail.com> +Date: Thu, 11 May 2023 10:03:59 +0200 +Subject: parted: link to libuuid + +parted.c uses libuuid since 61b3a9733c0e0a79ccc43096642d378c8706add6. +Hence, add UUID_LIBS to PARTED_LIBS to avoid +"DSO missing from command line" error. + +Signed-off-by: Brian C. Lane <bcl@redhat.com> + +Origin: upstream, https://git.savannah.gnu.org/cgit/parted.git/commit/?id=d22c2d01f62139e0d386d90584cac0705857a571 +Last-Update: 2023-06-13 + +Patch-Name: link-libuuid.patch +--- + configure.ac | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/configure.ac b/configure.ac +index d838c32c..ea614430 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -300,6 +300,8 @@ Note: originally, libuuid was part of the e2fsprogs package. Later, it + moved to util-linux-ng-2.16, and that package is now the preferred source.])]) + AC_SUBST([UUID_LIBS]) + ++PARTED_LIBS="$PARTED_LIBS $UUID_LIBS" ++ + dnl Check for libdevmapper + DM_LIBS= + if test $ENABLE_DEVICE_MAPPER = yes; then diff --git a/debian/patches/preserve-hidden-parts.patch b/debian/patches/preserve-hidden-parts.patch new file mode 100644 index 0000000..e70378b --- /dev/null +++ b/debian/patches/preserve-hidden-parts.patch @@ -0,0 +1,45 @@ +From 028c790ccdd95ef57a0b53404a32606d2e6a84ba Mon Sep 17 00:00:00 2001 +From: Ben Hutchings <ben@decadent.org.uk> +Date: Fri, 28 Mar 2014 17:09:40 +0000 +Subject: Avoid overwriting empty or hidden partitions + +It changes the DOS partition rewriting code to avoid overwriting empty +or hidden primary partitions so long as their entries aren't reused. +This makes fatresize and similar front-ends safe to use in the presence +of hidden partitions. + +Forwarded: http://lists.gnu.org/archive/html/bug-parted/2008-10/msg00005.html +Bug-Debian: http://bugs.debian.org/491797 +Last-Update: 2010-02-02 + +Patch-Name: preserve-hidden-parts.patch +--- + libparted/labels/dos.c | 11 ++++++++--- + 1 file changed, 8 insertions(+), 3 deletions(-) + +diff --git a/libparted/labels/dos.c b/libparted/labels/dos.c +index e6a01059..256f365d 100644 +--- a/libparted/labels/dos.c ++++ b/libparted/labels/dos.c +@@ -1452,13 +1452,18 @@ msdos_write (const PedDisk* disk) + if (!table->mbr_signature) + table->mbr_signature = generate_random_uint32 (); + +- memset (table->partitions, 0, sizeof (table->partitions)); +- table->magic = PED_CPU_TO_LE16 (MSDOS_MAGIC); ++ if (table->magic != PED_CPU_TO_LE16 (MSDOS_MAGIC)) { ++ memset (table->partitions, 0, sizeof (table->partitions)); ++ table->magic = PED_CPU_TO_LE16 (MSDOS_MAGIC); ++ } + + for (i=1; i<=DOS_N_PRI_PARTITIONS; i++) { + part = ped_disk_get_partition (disk, i); +- if (!part) ++ if (!part) { ++ if (table->partitions [i - 1].type != PARTITION_EMPTY) ++ memset (&table->partitions [i - 1], 0, sizeof (DosRawPartition)); + continue; ++ } + + if (!fill_raw_part (&table->partitions [i - 1], part, 0)) + goto write_fail; diff --git a/debian/patches/probe-lvs-again.patch b/debian/patches/probe-lvs-again.patch new file mode 100644 index 0000000..77139c0 --- /dev/null +++ b/debian/patches/probe-lvs-again.patch @@ -0,0 +1,34 @@ +From 20f1477293d180b2141ae7f1047ff5df84d42826 Mon Sep 17 00:00:00 2001 +From: Colin Watson <cjwatson@ubuntu.com> +Date: Sat, 9 Aug 2014 16:23:26 +0200 +Subject: Probe LVM logical volumes again + +parted 3.2 stopped probing LVM logical volumes. This breaks +debian-installer, which wants to be able to "partition" these, at least +to the extent of being able to see them in the partitioner and operate +on them somewhat like ordinary partitions. Revert to the old behaviour. + +Bug-Debian: http://bugs.debian.org/757417 +Forwarded: no +Last-Update: 2014-08-11 + +Patch-Name: probe-lvs-again.patch +--- + libparted/arch/linux.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index f6f72360..3bad1e6e 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -608,8 +608,8 @@ _probe_dm_devices () + if (stat (buf, &st) != 0) + continue; + +- if (_is_dm_major(major(st.st_rdev)) && _is_dmraid_device (buf) +- && !_dm_is_part(buf)) ++ if (_is_dm_major(major(st.st_rdev)) ++ && !(_is_dmraid_device(buf) && _dm_is_part(buf))) + _ped_device_probe (buf); + } + closedir (mapper_dir); diff --git a/debian/patches/series b/debian/patches/series new file mode 100644 index 0000000..8d4f4b7 --- /dev/null +++ b/debian/patches/series @@ -0,0 +1,13 @@ +doc-package.patch +preserve-hidden-parts.patch +kfreebsd-gnu.patch +freebsd-ufs.patch +zfs.patch +freebsd-zvol.patch +freebsd-geli.patch +kfreebsd_lvm.patch +gptsync.patch +udevadm-settle.patch +align-new-partitions-on-fresh-disks.patch +probe-lvs-again.patch +link-libuuid.patch diff --git a/debian/patches/udevadm-settle.patch b/debian/patches/udevadm-settle.patch new file mode 100644 index 0000000..96cdbcf --- /dev/null +++ b/debian/patches/udevadm-settle.patch @@ -0,0 +1,105 @@ +From 3947abeeb92069705229bff681b28d8ac78aedaa Mon Sep 17 00:00:00 2001 +From: Colin Watson <cjwatson@ubuntu.com> +Date: Fri, 28 Mar 2014 17:10:16 +0000 +Subject: udev handling + +Run udevadm settle around partition table rereads, to avoid races. + +This should be replaced by a proper completion-notification mechanism +between the kernel and udev. + +Forwarded: no +Last-Update: 2019-10-11 + +Patch-Name: udevadm-settle.patch +--- + libparted/arch/linux.c | 56 ++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 54 insertions(+), 2 deletions(-) + +diff --git a/libparted/arch/linux.c b/libparted/arch/linux.c +index ccbba865..f6f72360 100644 +--- a/libparted/arch/linux.c ++++ b/libparted/arch/linux.c +@@ -26,6 +26,7 @@ + #include <parted/fdasd.h> + #endif + ++#include <stdlib.h> + #include <ctype.h> + #include <errno.h> + #include <fcntl.h> +@@ -3250,10 +3251,52 @@ _have_blkpg () + return have_blkpg = kver >= KERNEL_VERSION (2,4,0) ? 1 : 0; + } + ++static int ++_chrooted () ++{ ++ static int cached = -1; ++ struct stat root, init_root; ++ ++ if (cached != -1) ++ return cached; ++ ++ if (stat ("/", &root) || stat ("/proc/1/root", &init_root)) ++ /* We can't tell, but are unlikely to be able to tell in the ++ * future either. ++ */ ++ cached = 0; ++ else if (root.st_dev == init_root.st_dev && ++ root.st_ino == init_root.st_ino) ++ /* / has the same dev/ino as /sbin/init's root, so we're not ++ * in a chroot. ++ */ ++ cached = 0; ++ else ++ /* We must be in a chroot. */ ++ cached = 1; ++ ++ return cached; ++} ++ + /* Return nonzero upon success, 0 if something fails. */ + static int + linux_disk_commit (PedDisk* disk) + { ++ int ret = 1; ++ ++ /* Modern versions of udev may notice the write activity on ++ * partition devices caused by _flush_cache, and may decide to ++ * synthesise some change events as a result. These may in turn run ++ * programs that open partition devices, which will race with us ++ * trying to remove those devices. To avoid this, we need to wait ++ * until udevd has finished processing its event queue. ++ * TODO: for upstream submission, this should check whether udevadm ++ * exists on $PATH. ++ */ ++ if (!_chrooted () && system ("udevadm settle") != 0) { ++ /* ignore failures */ ++ } ++ + if (disk->dev->type != PED_DEVICE_FILE) { + + /* We now require BLKPG support. If this assertion fails, +@@ -3263,10 +3306,19 @@ linux_disk_commit (PedDisk* disk) + assert (_have_blkpg ()); + + if (!_disk_sync_part_table (disk)) +- return 0; ++ ret = 0; + } + +- return 1; ++ /* Now we wait for udevd to finish creating device nodes based on ++ * the above activity, so that callers can reliably use them. ++ * TODO: for upstream submission, this should check whether udevadm ++ * exists on $PATH. ++ */ ++ if (!_chrooted () && system ("udevadm settle") != 0) { ++ /* ignore failures */ ++ } ++ ++ return ret; + } + + #if USE_BLKID diff --git a/debian/patches/zfs.patch b/debian/patches/zfs.patch new file mode 100644 index 0000000..8d0e927 --- /dev/null +++ b/debian/patches/zfs.patch @@ -0,0 +1,145 @@ +From a652c80f142411473d14c038e91c24ba81537f5b Mon Sep 17 00:00:00 2001 +From: Colin Watson <cjwatson@ubuntu.com> +Date: Fri, 28 Mar 2014 17:09:48 +0000 +Subject: Add ZFS support + +Last-Update: 2019-10-11 + +Patch-Name: zfs.patch +--- + libparted/fs/Makefile.am | 3 +- + libparted/fs/zfs/zfs.c | 77 ++++++++++++++++++++++++++++++++++++++++ + libparted/libparted.c | 4 +++ + 3 files changed, 83 insertions(+), 1 deletion(-) + create mode 100644 libparted/fs/zfs/zfs.c + +diff --git a/libparted/fs/Makefile.am b/libparted/fs/Makefile.am +index 41a60d98..1636d49f 100644 +--- a/libparted/fs/Makefile.am ++++ b/libparted/fs/Makefile.am +@@ -52,7 +52,8 @@ libfs_la_SOURCES = \ + xfs/platform_defs.h \ + xfs/xfs.c \ + xfs/xfs_sb.h \ +- xfs/xfs_types.h ++ xfs/xfs_types.h \ ++ zfs/zfs.c + + lib_LTLIBRARIES = libparted-fs-resize.la + +diff --git a/libparted/fs/zfs/zfs.c b/libparted/fs/zfs/zfs.c +new file mode 100644 +index 00000000..47cd6773 +--- /dev/null ++++ b/libparted/fs/zfs/zfs.c +@@ -0,0 +1,77 @@ ++/* ++ libparted - a library for manipulating disk partitions ++ Copyright (C) 2000, 2007, 2009-2010 Free Software Foundation, Inc. ++ ++ This program is free software; you can redistribute it and/or modify ++ it under the terms of the GNU General Public License as published by ++ the Free Software Foundation; either version 3 of the License, or ++ (at your option) any later version. ++ ++ This program is distributed in the hope that it will be useful, ++ but WITHOUT ANY WARRANTY; without even the implied warranty of ++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ GNU General Public License for more details. ++ ++ You should have received a copy of the GNU General Public License ++ along with this program. If not, see <http://www.gnu.org/licenses/>. ++*/ ++ ++#include <config.h> ++ ++#include <parted/parted.h> ++#include <parted/endian.h> ++ ++#if ENABLE_NLS ++# include <libintl.h> ++# define _(String) dgettext (PACKAGE, String) ++#else ++# define _(String) (String) ++#endif /* ENABLE_NLS */ ++ ++#include <unistd.h> ++ ++#define ZFS_SIGNATURE 0x00bab10c ++ ++struct zfs_uberblock ++{ ++ uint64_t signature; ++ uint64_t version; ++}; ++ ++static PedGeometry* ++zfs_probe (PedGeometry* geom) ++{ ++ struct zfs_uberblock *uber = alloca (geom->dev->sector_size); ++ ++ if (!ped_geometry_read (geom, uber, 256, 1)) ++ return 0; ++ ++ if ((le64toh (uber->signature) == ZFS_SIGNATURE ++ || be64toh (uber->signature) == ZFS_SIGNATURE) ++ && uber->version != 0) ++ return ped_geometry_new (geom->dev, geom->start, geom->length); ++ else ++ return NULL; ++} ++ ++static PedFileSystemOps zfs_ops = { ++ probe: zfs_probe, ++}; ++ ++static PedFileSystemType zfs_type = { ++ next: NULL, ++ ops: &zfs_ops, ++ name: "zfs", ++}; ++ ++void ++ped_file_system_zfs_init () ++{ ++ ped_file_system_type_register (&zfs_type); ++} ++ ++void ++ped_file_system_zfs_done () ++{ ++ ped_file_system_type_unregister (&zfs_type); ++} +diff --git a/libparted/libparted.c b/libparted/libparted.c +index 204ce007..88e7eea2 100644 +--- a/libparted/libparted.c ++++ b/libparted/libparted.c +@@ -115,6 +115,7 @@ extern void ped_file_system_ext2_init (void); + extern void ped_file_system_nilfs2_init (void); + extern void ped_file_system_btrfs_init (void); + extern void ped_file_system_udf_init (void); ++extern void ped_file_system_zfs_init (void); + + static void + init_file_system_types () +@@ -133,6 +134,7 @@ init_file_system_types () + ped_file_system_nilfs2_init (); + ped_file_system_btrfs_init (); + ped_file_system_udf_init (); ++ ped_file_system_zfs_init (); + } + + extern void ped_disk_aix_done (); +@@ -200,10 +202,12 @@ extern void ped_file_system_xfs_done (void); + extern void ped_file_system_amiga_done (void); + extern void ped_file_system_btrfs_done (void); + extern void ped_file_system_udf_done (void); ++extern void ped_file_system_zfs_done (void); + + static void + done_file_system_types () + { ++ ped_file_system_zfs_done (); + ped_file_system_nilfs2_done (); + ped_file_system_ext2_done (); + ped_file_system_f2fs_done (); |