summaryrefslogtreecommitdiffstats
path: root/libparted/labels/pt-tools.c
diff options
context:
space:
mode:
Diffstat (limited to 'libparted/labels/pt-tools.c')
-rw-r--r--libparted/labels/pt-tools.c186
1 files changed, 186 insertions, 0 deletions
diff --git a/libparted/labels/pt-tools.c b/libparted/labels/pt-tools.c
new file mode 100644
index 0000000..add4c45
--- /dev/null
+++ b/libparted/labels/pt-tools.c
@@ -0,0 +1,186 @@
+/* partition table tools
+ Copyright (C) 2008-2014, 2019-2023 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 <string.h>
+#include <stdlib.h>
+
+#include <parted/parted.h>
+#include <parted/debug.h>
+
+#include "pt-tools.h"
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(String) dgettext (PACKAGE, String)
+#else
+# define _(String) (String)
+#endif /* ENABLE_NLS */
+
+static char zero[16 * 1024];
+
+/* Write a single sector to DISK, filling the first BUFLEN
+ bytes of that sector with data from BUF, and NUL-filling
+ any remaining bytes. Return nonzero to indicate success,
+ zero otherwise. */
+int
+ptt_write_sector (PedDisk const *disk, void const *buf, size_t buflen)
+{
+ PED_ASSERT (buflen <= disk->dev->sector_size);
+ /* Allocate a big enough buffer for ped_device_write. */
+ char *s0 = ped_malloc (disk->dev->sector_size);
+ if (s0 == NULL)
+ return 0;
+ /* Copy boot_code into the first part. */
+ memcpy (s0, buf, buflen);
+ char *p = s0 + buflen;
+ /* Fill the rest with zeros. */
+ memset (p, 0, disk->dev->sector_size - buflen);
+ int write_ok = ped_device_write (disk->dev, s0, 0, 1);
+ free (s0);
+
+ return write_ok;
+}
+
+/* Read N sectors, starting with sector SECTOR_NUM (which has length
+ DEV->sector_size) into malloc'd storage. If the read fails, free
+ the memory and return zero without modifying *BUF. Otherwise, set
+ *BUF to the new buffer and return 1. */
+int
+ptt_read_sectors (PedDevice const *dev, PedSector start_sector,
+ PedSector n_sectors, void **buf)
+{
+ char *b = ped_malloc (n_sectors * dev->sector_size);
+ PED_ASSERT (b != NULL);
+ if (!ped_device_read (dev, b, start_sector, n_sectors)) {
+ free (b);
+ return 0;
+ }
+ *buf = b;
+ return 1;
+}
+
+/* Read sector, SECTOR_NUM (which has length DEV->sector_size) into malloc'd
+ storage. If the read fails, free the memory and return zero without
+ modifying *BUF. Otherwise, set *BUF to the new buffer and return 1. */
+int
+ptt_read_sector (PedDevice const *dev, PedSector sector_num, void **buf)
+{
+ return ptt_read_sectors (dev, sector_num, 1, buf);
+}
+
+/* Zero N sectors of DEV, starting with START.
+ Return nonzero to indicate success, zero otherwise. */
+int
+ptt_clear_sectors (PedDevice *dev, PedSector start, PedSector n)
+{
+ PED_ASSERT (dev->sector_size <= sizeof zero);
+ PedSector n_z_sectors = sizeof zero / dev->sector_size;
+ PedSector n_full = n / n_z_sectors;
+ PedSector i;
+ for (i = 0; i < n_full; i++)
+ {
+ if (!ped_device_write (dev, zero, start + n_z_sectors * i, n_z_sectors))
+ return 0;
+ }
+
+ PedSector rem = n - n_z_sectors * i;
+ return (rem == 0
+ ? 1 : ped_device_write (dev, zero, start + n_z_sectors * i, rem));
+}
+
+/* Zero N sectors of GEOM->dev, starting with GEOM->start + START.
+ Return nonzero to indicate success, zero otherwise. */
+int
+ptt_geom_clear_sectors (PedGeometry *geom, PedSector start, PedSector n)
+{
+ return ptt_clear_sectors (geom->dev, geom->start + start, n);
+}
+
+#define pt_limit_lookup _GL_ATTRIBUTE_PURE __pt_limit_lookup
+#include "pt-limit.c"
+
+/* Throw an exception and return 0 if PART's starting sector number or
+ its length is greater than the maximum allowed value for LABEL_TYPE.
+ Otherwise, return 1. */
+int
+ptt_partition_max_start_len (char const *pt_type, const PedPartition *part)
+{
+ struct partition_limit const *pt_lim
+ = __pt_limit_lookup (pt_type, strlen (pt_type));
+
+ /* If we don't have info on the type, return "true". */
+ if (pt_lim == NULL)
+ return 1;
+
+ /* If the length in sectors exceeds the limit, you lose. */
+ if (part->geom.length > pt_lim->max_length)
+ {
+ ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+ _("partition length of %jd sectors exceeds"
+ " the %s-partition-table-imposed maximum"
+ " of %jd"),
+ part->geom.length,
+ pt_type,
+ pt_lim->max_length);
+ return 0;
+ }
+
+ /* If the starting sector exceeds the limit, you lose. */
+ if (part->geom.start > pt_lim->max_start_sector) {
+ ped_exception_throw (
+ PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+ _("starting sector number, %jd exceeds"
+ " the %s-partition-table-imposed maximum"
+ " of %jd"),
+ part->geom.start,
+ pt_type,
+ pt_lim->max_start_sector);
+ return 0;
+ }
+
+ return 1;
+}
+
+/* Set *MAX to the largest representation-imposed starting sector number
+ of a partition of type PT_TYPE and return 0. If PT_TYPE is not
+ recognized, return -1. */
+int
+ptt_partition_max_start_sector (char const *pt_type, PedSector *max)
+{
+ struct partition_limit const *pt_lim
+ = __pt_limit_lookup (pt_type, strlen (pt_type));
+ if (pt_lim == NULL)
+ return -1;
+
+ *max = pt_lim->max_start_sector;
+ return 0;
+}
+
+/* Set *MAX to the maximum representable length of a partition of type
+ PT_TYPE and return 0. If PT_TYPE is not recognized, return -1. */
+int
+ptt_partition_max_length (char const *pt_type, PedSector *max)
+{
+ struct partition_limit const *pt_lim
+ = __pt_limit_lookup (pt_type, strlen (pt_type));
+ if (pt_lim == NULL)
+ return -1;
+
+ *max = pt_lim->max_length;
+ return 0;
+}