diff options
author | Roland McGrath <roland@gnu.org> | 2001-08-26 00:09:34 +0000 |
---|---|---|
committer | Roland McGrath <roland@gnu.org> | 2001-08-26 00:09:34 +0000 |
commit | b381b500bc5984c67fb213c5a7417ebfc0c6f2a1 (patch) | |
tree | a615a550225b5a52397b1d7551cb36ee5f41763f /libstore | |
parent | 255e762f0a16716e1822ce6f2eccf0fadc676dd9 (diff) |
2001-08-25 Roland McGrath <roland@frob.com>
* part.c (store_part_create): Do a run-time check on ped_get_version.
2001-08-25 Neal H Walfield <neal@cs.uml.edu>
* part.c: New file.
* std.c (store_std_classes): Add store_part_class.
* store.h (store_part_create): New prototype.
(store_part_open): Likewise.
Diffstat (limited to 'libstore')
-rw-r--r-- | libstore/part.c | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/libstore/part.c b/libstore/part.c new file mode 100644 index 00000000..227a5c84 --- /dev/null +++ b/libstore/part.c @@ -0,0 +1,194 @@ +/* Partition store backend + Copyright (C) 2001 Free Software Foundation, Inc. + + Written by Neal H Walfield <neal@cs.uml.edu> + + This task is part of the GNU Hurd. + + The GNU Hurd 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, or (at + your option) any later version. + + The GNU Hurd 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, USA. */ + +#include <stdlib.h> +#include <errno.h> +#include <assert.h> +#include <cthreads.h> +#include <hurd/store.h> + +#include <parted/parted.h> +#include <parted/device_gnu.h> +#include <string.h> +#include <error.h> + +#define NEED_PARTED_VERSION "1.5.4" + +/* Return a new store in STORE which contains a remap store of partition + PART from the contents of SOURCE; SOURCE is consumed. */ +error_t +store_part_create (struct store *source, int index, int flags, + struct store **store) +{ + static struct mutex parted_lock = MUTEX_INITIALIZER; + static int version_check; + error_t err = 0; + PedDevice *dev; + PedDisk *disk; + PedPartition *part; + struct store_run run; + + if ((source->block_size < PED_SECTOR_SIZE + && PED_SECTOR_SIZE % source->block_size != 0) + || (source->block_size > PED_SECTOR_SIZE + && source->block_size % PED_SECTOR_SIZE != 0)) + return EINVAL; + + mutex_lock (&parted_lock); + + /* Since Parted provides no source-level information about + version compatibility, we have to check at run time. */ + if (version_check == 0) + { + const char *version = ped_get_version (); + version_check = -1; + if (version == 0) + error (0, 0, "cannot get version of Parted library!"); + else if (strverscmp (version, NEED_PARTED_VERSION) < 0) + error (0, 0, "Parted library version %s older than needed %s", + version, NEED_PARTED_VERSION); + else + version_check = 1; + } + if (version_check <= 0) + { + error (0, 0, "the `part' store type is not available"); + mutex_unlock (&parted_lock); + return ENOTSUP; + } + + ped_exception_fetch_all (); + + dev = ped_device_new_from_store (source); + if (! dev) + { + ped_exception_catch (); + err = EIO; + goto out; + } + + assert (ped_device_open (dev) != 0); + + disk = ped_disk_new (dev); + if (! disk) + { + ped_exception_catch (); + err = EIO; + goto out_with_dev; + } + + for (part = ped_disk_next_partition (disk, NULL); part; + part = ped_disk_next_partition (disk, part)) + { + if (part->type != PED_PARTITION_LOGICAL + && part->type != 0 /* PED_PARTITION_PRIMARY */) + continue; + + assert (part->num); + if (part->num == index) + break; + } + + if (! part) + { + err = EIO; + goto out_with_disk; + } + + if (source->block_size == PED_SECTOR_SIZE) + { + run.start = part->geom.start; + run.length = part->geom.length; + } + else if (source->block_size < PED_SECTOR_SIZE) + { + run.start = part->geom.start * (PED_SECTOR_SIZE / source->block_size); + run.length = part->geom.length * (PED_SECTOR_SIZE / source->block_size); + } + else + /* source->block_size > PED_SECTOR_SIZE */ + { + run.start = part->geom.start * PED_SECTOR_SIZE; + if (run.start % source->block_size != 0) + err = EIO; + else + { + run.start /= source->block_size; + run.length = part->geom.length * PED_SECTOR_SIZE; + if (run.length % source->block_size != 0) + err = EIO; + else + run.length /= source->block_size; + } + } + +out_with_disk: + assert (ped_device_close (dev) != 0); + assert (ped_disk_destroy (disk)); +out_with_dev: + ped_device_destroy (dev); +out: + ped_exception_leave_all (); + mutex_unlock (&parted_lock); + + if (! err) + err = store_remap (source, &run, 1, store); + + return err; +} + +/* Open the part NAME. NAME consists of a partition number, a ':', a another + store class name, a ':' and a name for to by passed to the store class. + E.g. "2:device:hd0" would open the second partition on a DEVICE store + named "hd0". FLAGS indicate how to open the store. CLASSES is used to + select classes specified by the type NAME; if it is 0, STORE_STD_CLASSES + is used. The new store is returned in *STORE. */ +error_t +store_part_open (const char *name, int flags, + const struct store_class *const *classes, + struct store **store) +{ + int part; + char *endp; + struct store *source; + error_t err; + + part = strtol (name, &endp, 0); + if (endp == name || *endp != ':') + return EINVAL; + + name = endp + 1; + if (*name == '\0') + return EINVAL; + + err = store_typed_open (name, flags, classes, &source); + if (! err) + { + err = store_part_create (source, part, flags, store); + if (err) + store_free (source); + } + + return err; +} + +struct store_class +store_part_class = { -1, "part", open: store_part_open }; |