Logo Search packages:      
Sourcecode: parted version File versions

disk_loop.c

/*
    libparted - a library for manipulating disk partitions
    Copyright (C) 1999, 2000 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
*/

#include "config.h"

#include <parted/parted.h>
#include <parted/debug.h>
#include <parted/endian.h>
#include <string.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 (PedDevice* dev);
static void loop_free (PedDisk* disk);

static int
loop_probe (PedDevice* dev)
{
      PedDisk*    disk;
      char        buf [512];
      int         result;

      disk = loop_alloc (dev);
      if (!disk)
            goto error;

      if (!ped_device_read (dev, buf, 0, 1))
            goto error_destroy_disk;
      if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) == 0) {
            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;
}

#ifndef DISCOVER_ONLY
static int
loop_clobber (PedDevice* dev)
{
      char        buf [512];
      PedSector   i = 0;

      PED_ASSERT (dev != NULL, return 0);

      memset (buf, 0, 512);

      while (loop_probe (dev)) {
            if (!ped_device_write (dev, buf, i++, 1))
                  return 0;
      }
      return 1;
}
#endif /* !DISCOVER_ONLY */

static PedDisk*
loop_alloc (PedDevice* dev)
{
      PedDisk*          disk;

      PED_ASSERT (dev != NULL, return 0);

      if (dev->length < 256)
            return NULL;
      return _ped_disk_alloc (dev, &loop_disk_type);
}

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, return);

      _ped_disk_free (disk);
}

static int
loop_read (PedDisk* disk)
{
      PedDevice*        dev = NULL;
      char              buf [512];
      PedGeometry*            geom;
      PedFileSystemType*      fs_type;
      PedPartition*           part;
      PedConstraint*          constraint_any;

      PED_ASSERT (disk != NULL, return 0);
      dev = disk->dev;
      constraint_any = ped_constraint_any (dev);

      ped_disk_delete_all (disk);

      if (!ped_device_read (dev, buf, 0, 1))
            goto error;
      if (!strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)))
            return 1;

      geom = ped_geometry_new (dev, 0, dev->length);
      if (!geom)
            goto error;

      fs_type = ped_file_system_probe (geom);
      if (!fs_type)
            goto error_free_geom;

      part = ped_partition_new (disk, 0, fs_type, geom->start, geom->end);
      ped_geometry_destroy (geom);
      if (!part)
            goto error;
      part->fs_type = fs_type;

      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 (PedDisk* disk)
{
      char        buf [512];

      if (ped_disk_get_partition (disk, 1)) {
            if (!ped_device_read (disk->dev, buf, 0, 1))
                  return 0;
            if (strncmp (buf, LOOP_SIGNATURE, strlen (LOOP_SIGNATURE)) != 0)
                        return 1;
            memset (buf, 0, strlen (LOOP_SIGNATURE));
            return ped_device_write (disk->dev, buf, 0, 1);
      }

      memset (buf, 0, 512);
      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);
      result->num = part->num;
      return result;
}

static void
loop_partition_destroy (PedPartition* part)
{
      ped_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 PedDiskOps loop_disk_ops = {
      probe:                  loop_probe,
#ifndef DISCOVER_ONLY
      clobber:          loop_clobber,
#else
      clobber:          NULL,
#endif
      alloc:                  loop_alloc,
      duplicate:        loop_duplicate,
      free:             loop_free,
      read:             loop_read,
#ifndef DISCOVER_ONLY
      write:                  loop_write,
#else
      write:                  NULL,
#endif

      partition_new:          loop_partition_new,
      partition_duplicate:    loop_partition_duplicate,
      partition_destroy:      loop_partition_destroy,
      partition_set_system:   loop_partition_set_system,
      partition_set_flag:     loop_partition_set_flag,
      partition_get_flag:     loop_partition_get_flag,
      partition_is_flag_available:  loop_partition_is_flag_available,
      partition_set_name:     NULL,
      partition_get_name:     NULL,
      partition_align:  loop_partition_align,
      partition_enumerate:    loop_partition_enumerate,

      alloc_metadata:         loop_alloc_metadata,
      get_max_primary_partition_count:
                        loop_get_max_primary_partition_count
};

static PedDiskType loop_disk_type = {
      next:       NULL,
      name:       "loop",
      ops:        &loop_disk_ops,
      features:   0
};

void
ped_disk_loop_init ()
{
      ped_register_disk_type (&loop_disk_type);
}

void
ped_disk_loop_done ()
{
      ped_unregister_disk_type (&loop_disk_type);
}


Generated by  Doxygen 1.6.0   Back to index