diff options
Diffstat (limited to 'debian/patches/kfreebsd-gnu.patch')
-rw-r--r-- | debian/patches/kfreebsd-gnu.patch | 1434 |
1 files changed, 1434 insertions, 0 deletions
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> |