1N/A/*
1N/A libparted - a library for manipulating disk partitions
1N/A Copyright (C) 1999-2000, 2007-2010 Free Software Foundation, Inc.
1N/A
1N/A This program is free software; you can redistribute it and/or modify
1N/A it under the terms of the GNU General Public License as published by
1N/A the Free Software Foundation; either version 3 of the License, or
1N/A (at your option) any later version.
1N/A
1N/A This program is distributed in the hope that it will be useful,
1N/A but WITHOUT ANY WARRANTY; without even the implied warranty of
1N/A MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1N/A GNU General Public License for more details.
1N/A
1N/A You should have received a copy of the GNU General Public License
1N/A along with this program. If not, see <http://www.gnu.org/licenses/>.
1N/A*/
1N/A
1N/A#include <config.h>
1N/A
1N/A#include <parted/parted.h>
1N/A#include <parted/debug.h>
1N/A#include <parted/endian.h>
1N/A#include <stdbool.h>
1N/A
1N/A#include "pt-tools.h"
1N/A
1N/A#if ENABLE_NLS
1N/A# include <libintl.h>
1N/A# define _(String) dgettext (PACKAGE, String)
1N/A#else
1N/A# define _(String) (String)
1N/A#endif /* ENABLE_NLS */
1N/A
1N/A#define LOOP_SIGNATURE "GNU Parted Loopback 0"
1N/A
1N/Astatic PedDiskType loop_disk_type;
1N/A
1N/Astatic PedDisk* loop_alloc (const PedDevice* dev);
1N/Astatic void loop_free (PedDisk* disk);
1N/A
1N/Astatic int
1N/Aloop_probe (const PedDevice* dev)
1N/A{
1N/A PedDisk *disk = loop_alloc (dev);
1N/A if (!disk)
1N/A goto error;
1N/A
1N/A void *buf;
1N/A if (!ptt_read_sector (dev, 0, &buf))
1N/A goto error_destroy_disk;
1N/A int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
1N/A free (buf);
1N/A
1N/A int result;
1N/A if (found_sig) {
1N/A result = 1;
1N/A } else {
1N/A PedGeometry* geom;
1N/A
1N/A geom = ped_geometry_new (dev, 0, disk->dev->length);
1N/A if (!geom)
1N/A goto error_destroy_disk;
1N/A result = ped_file_system_probe (geom) != NULL;
1N/A ped_geometry_destroy (geom);
1N/A }
1N/A loop_free (disk);
1N/A return result;
1N/A
1N/Aerror_destroy_disk:
1N/A loop_free (disk);
1N/Aerror:
1N/A return 0;
1N/A}
1N/A
1N/Astatic PedDisk*
1N/Aloop_alloc (const PedDevice* dev)
1N/A{
1N/A PED_ASSERT (dev != NULL, return 0);
1N/A
1N/A if (dev->length < 256)
1N/A return NULL;
1N/A return _ped_disk_alloc ((PedDevice*)dev, &loop_disk_type);
1N/A}
1N/A
1N/Astatic PedDisk*
1N/Aloop_duplicate (const PedDisk* disk)
1N/A{
1N/A return ped_disk_new_fresh (disk->dev, &loop_disk_type);
1N/A}
1N/A
1N/Astatic void
1N/Aloop_free (PedDisk* disk)
1N/A{
1N/A PED_ASSERT (disk != NULL, return);
1N/A
1N/A _ped_disk_free (disk);
1N/A}
1N/A
1N/Astatic int
1N/Aloop_read (PedDisk* disk)
1N/A{
1N/A PedDevice* dev = NULL;
1N/A PedGeometry* geom;
1N/A PedFileSystemType* fs_type;
1N/A PedPartition* part;
1N/A PedConstraint* constraint_any;
1N/A
1N/A PED_ASSERT (disk != NULL, return 0);
1N/A dev = disk->dev;
1N/A constraint_any = ped_constraint_any (dev);
1N/A
1N/A ped_disk_delete_all (disk);
1N/A
1N/A void *buf;
1N/A if (!ptt_read_sector (dev, 0, &buf))
1N/A goto error;
1N/A
1N/A int found_sig = !strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE));
1N/A free (buf);
1N/A
1N/A if (found_sig) {
1N/A ped_constraint_destroy (constraint_any);
1N/A return 1;
1N/A }
1N/A
1N/A geom = ped_geometry_new (dev, 0, dev->length);
1N/A if (!geom)
1N/A goto error;
1N/A
1N/A fs_type = ped_file_system_probe (geom);
1N/A if (!fs_type)
1N/A goto error_free_geom;
1N/A
1N/A part = ped_partition_new (disk, PED_PARTITION_NORMAL,
1N/A fs_type, geom->start, geom->end);
1N/A ped_geometry_destroy (geom);
1N/A if (!part)
1N/A goto error;
1N/A part->fs_type = fs_type;
1N/A
1N/A if (!ped_disk_add_partition (disk, part, constraint_any))
1N/A goto error;
1N/A ped_constraint_destroy (constraint_any);
1N/A return 1;
1N/A
1N/Aerror_free_geom:
1N/A ped_geometry_destroy (geom);
1N/Aerror:
1N/A ped_constraint_destroy (constraint_any);
1N/A return 0;
1N/A}
1N/A
1N/A#ifndef DISCOVER_ONLY
1N/Astatic int
1N/Aloop_write (const PedDisk* disk)
1N/A{
1N/A size_t buflen = disk->dev->sector_size;
1N/A char *buf = ped_malloc (buflen);
1N/A if (buf == NULL)
1N/A return 0;
1N/A
1N/A if (ped_disk_get_partition (disk, 1)) {
1N/A if (!ped_device_read (disk->dev, buf, 0, 1)) {
1N/A free (buf);
1N/A return 0;
1N/A }
1N/A if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0) {
1N/A free (buf);
1N/A return 1;
1N/A }
1N/A memset (buf, 0, strlen (LOOP_SIGNATURE));
1N/A return ped_device_write (disk->dev, buf, 0, 1);
1N/A }
1N/A
1N/A memset (buf, 0, buflen);
1N/A strcpy (buf, LOOP_SIGNATURE);
1N/A
1N/A int write_ok = ped_device_write (disk->dev, buf, 0, 1);
1N/A free (buf);
1N/A return write_ok;
1N/A}
1N/A#endif /* !DISCOVER_ONLY */
1N/A
1N/Astatic PedPartition*
1N/Aloop_partition_new (const PedDisk* disk, PedPartitionType part_type,
1N/A const PedFileSystemType* fs_type,
1N/A PedSector start, PedSector end)
1N/A{
1N/A PedPartition* part;
1N/A
1N/A part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1N/A if (!part)
1N/A return NULL;
1N/A part->disk_specific = NULL;
1N/A return part;
1N/A}
1N/A
1N/Astatic PedPartition*
1N/Aloop_partition_duplicate (const PedPartition* part)
1N/A{
1N/A PedPartition* result;
1N/A
1N/A result = ped_partition_new (part->disk, part->type, part->fs_type,
1N/A part->geom.start, part->geom.end);
1N/A result->num = part->num;
1N/A return result;
1N/A}
1N/A
1N/Astatic void
1N/Aloop_partition_destroy (PedPartition* part)
1N/A{
1N/A free (part);
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1N/A{
1N/A part->fs_type = fs_type;
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1N/A{
1N/A return 0;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1N/A{
1N/A return 0;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_align (PedPartition* part, const PedConstraint* constraint)
1N/A{
1N/A PedGeometry* new_geom;
1N/A
1N/A new_geom = ped_constraint_solve_nearest (constraint, &part->geom);
1N/A if (!new_geom) {
1N/A ped_exception_throw (
1N/A PED_EXCEPTION_ERROR,
1N/A PED_EXCEPTION_CANCEL,
1N/A _("Unable to satisfy all constraints on the "
1N/A "partition."));
1N/A return 0;
1N/A }
1N/A ped_geometry_set (&part->geom, new_geom->start, new_geom->length);
1N/A ped_geometry_destroy (new_geom);
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_is_flag_available (const PedPartition* part,
1N/A PedPartitionFlag flag)
1N/A{
1N/A return 0;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_partition_enumerate (PedPartition* part)
1N/A{
1N/A part->num = 1;
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_alloc_metadata (PedDisk* disk)
1N/A{
1N/A return 1;
1N/A}
1N/A
1N/Astatic int
1N/Aloop_get_max_primary_partition_count (const PedDisk* disk)
1N/A{
1N/A return 1;
1N/A}
1N/A
1N/Astatic bool
1N/Aloop_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1N/A{
1N/A *max_n = 1;
1N/A return true;
1N/A}
1N/A
1N/A#include "pt-common.h"
1N/APT_define_limit_functions (loop)
1N/A
1N/Astatic PedDiskOps loop_disk_ops = {
1N/A .clobber = NULL,
1N/A .write = NULL_IF_DISCOVER_ONLY (loop_write),
1N/A
1N/A .partition_set_name = NULL,
1N/A .partition_get_name = NULL,
1N/A
1N/A PT_op_function_initializers (loop)
1N/A};
1N/A
1N/Astatic PedDiskType loop_disk_type = {
1N/A .next = NULL,
1N/A .name = "loop",
1N/A .ops = &loop_disk_ops,
1N/A .features = 0
1N/A};
1N/A
1N/Avoid
1N/Aped_disk_loop_init ()
1N/A{
1N/A ped_disk_type_register (&loop_disk_type);
1N/A}
1N/A
1N/Avoid
1N/Aped_disk_loop_done ()
1N/A{
1N/A ped_disk_type_unregister (&loop_disk_type);
1N/A}