summaryrefslogtreecommitdiffstats
path: root/libparted/labels/loop.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--libparted/labels/loop.c316
1 files changed, 316 insertions, 0 deletions
diff --git a/libparted/labels/loop.c b/libparted/labels/loop.c
new file mode 100644
index 0000000..45d169d
--- /dev/null
+++ b/libparted/labels/loop.c
@@ -0,0 +1,316 @@
+/*
+ libparted - a library for manipulating disk partitions
+ Copyright (C) 1999-2000, 2007-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 <parted/parted.h>
+#include <parted/debug.h>
+#include <parted/endian.h>
+#include <stdbool.h>
+
+#include "pt-tools.h"
+
+#if ENABLE_NLS
+# include <libintl.h>
+# define _(String) dgettext (PACKAGE, String)
+#else
+# define _(String) (String)
+#endif /* ENABLE_NLS */
+
+#define LOOP_SIGNATURE "GNU Parted Loopback 0"
+
+static PedDiskType loop_disk_type;
+
+static PedDisk* loop_alloc (const PedDevice* dev);
+static void loop_free (PedDisk* disk);
+
+static int
+loop_probe (const PedDevice* dev)
+{
+ PedDisk *disk = loop_alloc (dev);
+ if (!disk)
+ goto error;
+
+ void *buf;
+ if (!ptt_read_sector (dev, 0, &buf))
+ goto error_destroy_disk;
+ int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
+ free (buf);
+
+ int result;
+ if (found_sig) {
+ result = 1;
+ } else {
+ PedGeometry* geom;
+
+ geom = ped_geometry_new (dev, 0, disk->dev->length);
+ if (!geom)
+ goto error_destroy_disk;
+ result = ped_file_system_probe (geom) != NULL;
+ ped_geometry_destroy (geom);
+ }
+ loop_free (disk);
+ return result;
+
+error_destroy_disk:
+ loop_free (disk);
+error:
+ return 0;
+}
+
+static PedDisk*
+loop_alloc (const PedDevice* dev)
+{
+ PED_ASSERT (dev != NULL);
+
+ if (dev->length < 256)
+ return NULL;
+ PedDisk *disk = _ped_disk_alloc ((PedDevice*)dev, &loop_disk_type);
+ PED_ASSERT (disk != NULL);
+ PedGeometry *geom = ped_geometry_new (dev, 0, dev->length);
+ PED_ASSERT (geom != NULL);
+ PedPartition *part = ped_partition_new (disk, PED_PARTITION_NORMAL,
+ NULL, geom->start, geom->end);
+ PED_ASSERT (part != NULL);
+ ped_geometry_destroy (geom);
+ PedConstraint *constraint_any = ped_constraint_any (dev);
+ if (!ped_disk_add_partition (disk, part, constraint_any))
+ goto error;
+ ped_constraint_destroy (constraint_any);
+ return disk;
+ error:
+ ped_constraint_destroy (constraint_any);
+ ped_disk_destroy (disk);
+ return NULL;
+}
+
+static PedDisk*
+loop_duplicate (const PedDisk* disk)
+{
+ return ped_disk_new_fresh (disk->dev, &loop_disk_type);
+}
+
+static void
+loop_free (PedDisk* disk)
+{
+ PED_ASSERT (disk != NULL);
+
+ _ped_disk_free (disk);
+}
+
+static int
+loop_read (PedDisk* disk)
+{
+ PedDevice* dev = NULL;
+ PedGeometry* geom;
+ PedFileSystemType* fs_type;
+ PedPartition* part;
+ PedConstraint* constraint_any;
+
+ PED_ASSERT (disk != NULL);
+ dev = disk->dev;
+ constraint_any = ped_constraint_any (dev);
+
+ ped_disk_delete_all (disk);
+
+ void *buf;
+ if (!ptt_read_sector (dev, 0, &buf))
+ goto error;
+
+ int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
+ free (buf);
+ geom = ped_geometry_new (dev, 0, dev->length);
+ if (!geom)
+ goto error;
+
+ fs_type = ped_file_system_probe (geom);
+ if (!fs_type && !found_sig)
+ goto error_free_geom;
+
+ part = ped_partition_new (disk, PED_PARTITION_NORMAL,
+ fs_type, geom->start, geom->end);
+ ped_geometry_destroy (geom);
+ if (!part)
+ goto error;
+
+ if (!ped_disk_add_partition (disk, part, constraint_any))
+ goto error;
+ ped_constraint_destroy (constraint_any);
+ return 1;
+
+error_free_geom:
+ ped_geometry_destroy (geom);
+error:
+ ped_constraint_destroy (constraint_any);
+ return 0;
+}
+
+#ifndef DISCOVER_ONLY
+static int
+loop_write (const PedDisk* disk)
+{
+ size_t buflen = disk->dev->sector_size;
+ char *buf = alloca (buflen);
+ PedPartition *part = ped_disk_get_partition (disk, 1);
+ /* if there is already a filesystem on the disk, we don't need to write the signature */
+ if (part && part->fs_type)
+ return 1;
+ if (!ped_device_read (disk->dev, buf, 0, 1))
+ return 0;
+ strcpy (buf, LOOP_SIGNATURE);
+
+ return ped_device_write (disk->dev, buf, 0, 1);
+}
+#endif /* !DISCOVER_ONLY */
+
+static PedPartition*
+loop_partition_new (const PedDisk* disk, PedPartitionType part_type,
+ const PedFileSystemType* fs_type,
+ PedSector start, PedSector end)
+{
+ PedPartition* part;
+
+ part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
+ if (!part)
+ return NULL;
+ part->disk_specific = NULL;
+ return part;
+}
+
+static PedPartition*
+loop_partition_duplicate (const PedPartition* part)
+{
+ PedPartition* result;
+
+ result = ped_partition_new (part->disk, part->type, part->fs_type,
+ part->geom.start, part->geom.end);
+ if (result == NULL)
+ return NULL;
+ result->num = part->num;
+ return result;
+}
+
+static void
+loop_partition_destroy (PedPartition* part)
+{
+ free (part);
+}
+
+static int
+loop_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
+{
+ part->fs_type = fs_type;
+ return 1;
+}
+
+static int
+loop_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
+{
+ return 0;
+}
+
+static int
+loop_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
+{
+ return 0;
+}
+
+static int
+loop_partition_align (PedPartition* part, const PedConstraint* constraint)
+{
+ PedGeometry* new_geom;
+
+ new_geom = ped_constraint_solve_nearest (constraint, &part->geom);
+ if (!new_geom) {
+ ped_exception_throw (
+ PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("Unable to satisfy all constraints on the "
+ "partition."));
+ return 0;
+ }
+ ped_geometry_set (&part->geom, new_geom->start, new_geom->length);
+ ped_geometry_destroy (new_geom);
+ return 1;
+}
+
+static int
+loop_partition_is_flag_available (const PedPartition* part,
+ PedPartitionFlag flag)
+{
+ return 0;
+}
+
+static int
+loop_partition_enumerate (PedPartition* part)
+{
+ part->num = 1;
+ return 1;
+}
+
+static int
+loop_alloc_metadata (PedDisk* disk)
+{
+ return 1;
+}
+
+static int
+loop_get_max_primary_partition_count (const PedDisk* disk)
+{
+ return 1;
+}
+
+static bool
+loop_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
+{
+ *max_n = 1;
+ return true;
+}
+
+#include "pt-common.h"
+PT_define_limit_functions (loop)
+
+static PedDiskOps loop_disk_ops = {
+ clobber: NULL,
+ write: NULL_IF_DISCOVER_ONLY (loop_write),
+
+ partition_set_name: NULL,
+ partition_get_name: NULL,
+
+ PT_op_function_initializers (loop)
+};
+
+static PedDiskType loop_disk_type = {
+ next: NULL,
+ name: "loop",
+ ops: &loop_disk_ops,
+ features: 0
+};
+
+void
+ped_disk_loop_init ()
+{
+ ped_disk_type_register (&loop_disk_type);
+}
+
+void
+ped_disk_loop_done ()
+{
+ ped_disk_type_unregister (&loop_disk_type);
+}