2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999-2003, 2005, 2007-2012 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
24 * \brief Disk label access.
26 * Most programs will need to use ped_disk_new() or ped_disk_new_fresh() to get
27 * anything done. A PedDisk is always associated with a device and has a
28 * partition table. There are different types of partition tables (or disk
29 * labels). These are represented by the PedDiskType enumeration.
36 #include <parted/parted.h>
37 #include <parted/debug.h>
40 #include "architecture.h"
41 #include "labels/pt-tools.h"
45 # define _(String) dgettext (PACKAGE, String)
46 # define N_(String) (String)
48 # define _(String) (String)
49 # define N_(String) (String)
50 #endif /* ENABLE_NLS */
52 /* UPDATE MODE functions */
54 static int _disk_check_sanity (PedDisk* disk);
56 static int _disk_push_update_mode (PedDisk* disk);
57 static int _disk_pop_update_mode (PedDisk* disk);
58 static int _disk_raw_insert_before (PedDisk* disk, PedPartition* loc,
60 static int _disk_raw_insert_after (PedDisk* disk, PedPartition* loc,
62 static int _disk_raw_remove (PedDisk* disk, PedPartition* part);
63 static int _disk_raw_add (PedDisk* disk, PedPartition* part);
65 static PedDiskType* disk_types = NULL;
68 ped_disk_type_register (PedDiskType* disk_type)
70 PED_ASSERT (disk_type != NULL);
71 PED_ASSERT (disk_type->ops != NULL);
72 PED_ASSERT (disk_type->name != NULL);
74 disk_type->next = disk_types;
75 disk_types = disk_type;
79 ped_disk_type_unregister (PedDiskType* disk_type)
82 PedDiskType* last = NULL;
84 PED_ASSERT (disk_types != NULL);
85 PED_ASSERT (disk_type != NULL);
87 for (walk = disk_types; walk && walk != disk_type;
88 last = walk, walk = walk->next);
90 PED_ASSERT (walk != NULL);
92 ((struct _PedDiskType*) last)->next = disk_type->next;
94 disk_types = disk_type->next;
98 * Return the next disk type registers, after "type". If "type" is
99 * NULL, returns the first disk type.
101 * \return Next disk; NULL if "type" is the last registered disk type.
104 ped_disk_type_get_next (PedDiskType const *type)
113 * Return the disk type with a name of "name".
115 * \return Disk type; NULL if no match.
118 ped_disk_type_get (const char* name)
120 PedDiskType* walk = NULL;
122 PED_ASSERT (name != NULL);
124 for (walk = ped_disk_type_get_next (NULL); walk;
125 walk = ped_disk_type_get_next (walk))
126 if (strcasecmp (walk->name, name) == 0)
133 * Return the type of partition table detected on "dev".
135 * \return Type; NULL if none was detected.
138 ped_disk_probe (PedDevice* dev)
140 PedDiskType* walk = NULL;
142 PED_ASSERT (dev != NULL);
144 if (!ped_device_open (dev))
147 ped_exception_fetch_all ();
148 for (walk = ped_disk_type_get_next (NULL); walk;
149 walk = ped_disk_type_get_next (walk))
151 if (getenv ("PARTED_DEBUG")) {
152 fprintf (stderr, "probe label: %s\n",
156 if (walk->ops->probe (dev))
161 ped_exception_catch ();
162 ped_exception_leave_all ();
164 ped_device_close (dev);
169 * Read the partition table off a device (if one is found).
171 * \warning May modify \p dev->cylinders, \p dev->heads and \p dev->sectors
172 * if the partition table indicates that the existing values
175 * \return A new \link _PedDisk PedDisk \endlink object;
176 * NULL on failure (e.g. partition table not detected).
179 ped_disk_new (PedDevice* dev)
184 PED_ASSERT (dev != NULL);
186 if (!ped_device_open (dev))
189 type = ped_disk_probe (dev);
191 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
192 _("%s: unrecognised disk label"),
194 goto error_close_dev;
196 disk = ped_disk_new_fresh (dev, type);
198 goto error_close_dev;
199 if (!type->ops->read (disk))
200 goto error_destroy_disk;
201 disk->needs_clobber = 0;
202 ped_device_close (dev);
206 ped_disk_destroy (disk);
208 ped_device_close (dev);
214 _add_duplicate_part (PedDisk* disk, PedPartition* old_part)
216 PedPartition* new_part;
219 new_part = disk->type->ops->partition_duplicate (old_part);
222 new_part->disk = disk;
224 if (!_disk_push_update_mode (disk))
225 goto error_destroy_new_part;
226 ret = _disk_raw_add (disk, new_part);
227 if (!_disk_pop_update_mode (disk))
228 goto error_destroy_new_part;
230 goto error_destroy_new_part;
232 if (!_disk_check_sanity (disk))
233 goto error_destroy_new_part;
237 error_destroy_new_part:
238 ped_partition_destroy (new_part);
244 * Clone a \link _PedDisk PedDisk \endlink object.
246 * \return Deep copy of \p old_disk, NULL on failure.
249 ped_disk_duplicate (const PedDisk* old_disk)
252 PedPartition* old_part;
254 PED_ASSERT (old_disk != NULL);
255 PED_ASSERT (!old_disk->update_mode);
256 PED_ASSERT (old_disk->type->ops->duplicate != NULL);
257 PED_ASSERT (old_disk->type->ops->partition_duplicate != NULL);
259 new_disk = old_disk->type->ops->duplicate (old_disk);
263 if (!_disk_push_update_mode (new_disk))
264 goto error_destroy_new_disk;
265 for (old_part = ped_disk_next_partition (old_disk, NULL); old_part;
266 old_part = ped_disk_next_partition (old_disk, old_part)) {
267 if (ped_partition_is_active (old_part)) {
268 if (!_add_duplicate_part (new_disk, old_part)){
269 _disk_pop_update_mode (new_disk);
270 goto error_destroy_new_disk;
274 if (!_disk_pop_update_mode (new_disk))
275 goto error_destroy_new_disk;
277 new_disk->needs_clobber = old_disk->needs_clobber;
281 error_destroy_new_disk:
282 ped_disk_destroy (new_disk);
287 /* Given a partition table type NAME, e.g., "gpt", return its PedDiskType
288 handle. If no known type has a name matching NAME, return NULL. */
289 static PedDiskType const * _GL_ATTRIBUTE_PURE
290 find_disk_type (char const *name)
292 PedDiskType const *t;
293 for (t = ped_disk_type_get_next (NULL); t; t = ped_disk_type_get_next (t))
295 if (strcmp (t->name, name) == 0)
302 * Remove all identifying signatures of a partition table,
304 * \return 0 on error, 1 otherwise.
306 * \sa ped_disk_clobber()
309 ped_disk_clobber (PedDevice* dev)
311 PED_ASSERT (dev != NULL);
313 if (!ped_device_open (dev))
316 PedDiskType const *gpt = find_disk_type ("gpt");
317 PED_ASSERT (gpt != NULL);
319 /* If there is a GPT table, don't clobber the protective MBR. */
320 bool is_gpt = gpt->ops->probe (dev);
321 PedSector first_sector = (is_gpt ? 1 : 0);
323 /* How many sectors to zero out at each end.
324 This must be large enough to zero out the magic bytes
325 starting at offset 8KiB on a DASD partition table.
326 Doing the same from the end of the disk is probably
327 overkill, but at least on GPT, we do need to zero out
329 const PedSector n_sectors = 9 * 1024 / dev->sector_size + 1;
331 /* Clear the first few. */
332 PedSector n = n_sectors;
333 if (dev->length < first_sector + n_sectors)
334 n = dev->length - first_sector;
335 if (!ptt_clear_sectors (dev, first_sector, n))
336 goto error_close_dev;
338 /* Clear the last few. */
339 PedSector t = (dev->length -
340 (n_sectors < dev->length ? n_sectors : 1));
342 /* Don't clobber the pMBR if we have a pathologically small disk. */
343 if (t < first_sector)
345 if (!ptt_clear_sectors (dev, t, dev->length - t))
346 goto error_close_dev;
348 ped_device_close (dev);
352 ped_device_close (dev);
358 * Create a new partition table on \p dev.
360 * This new partition table is only created in-memory, and nothing is written
361 * to disk until ped_disk_commit_to_dev() is called.
363 * \return The newly constructed \link _PedDisk PedDisk \endlink,
367 ped_disk_new_fresh (PedDevice* dev, const PedDiskType* type)
371 PED_ASSERT (dev != NULL);
372 PED_ASSERT (type != NULL);
373 PED_ASSERT (type->ops->alloc != NULL);
374 PedCHSGeometry* bios_geom = &dev->bios_geom;
375 PED_ASSERT (bios_geom->sectors != 0);
376 PED_ASSERT (bios_geom->heads != 0);
378 disk = type->ops->alloc (dev);
381 if (!_disk_pop_update_mode (disk))
382 goto error_destroy_disk;
383 PED_ASSERT (disk->update_mode == 0);
385 disk->needs_clobber = 1;
389 ped_disk_destroy (disk);
395 _ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type)
399 disk = (PedDisk*) ped_malloc (sizeof (PedDisk));
403 disk->dev = (PedDevice*)dev;
404 disk->type = disk_type;
405 disk->update_mode = 1;
406 disk->part_list = NULL;
414 _ped_disk_free (PedDisk* disk)
416 _disk_push_update_mode (disk);
417 ped_disk_delete_all (disk);
424 * What this function does depends on the PedDiskType of \p disk,
425 * but you can generally assume that outstanding writes are flushed
426 * (this mainly means that _ped_disk_free is called).
429 ped_disk_destroy (PedDisk* disk)
431 PED_ASSERT (disk != NULL);
432 PED_ASSERT (!disk->update_mode);
434 disk->type->ops->free (disk);
438 * Tell the operating system kernel about the partition table layout
441 * This is rather loosely defined: for example, on old versions of Linux,
442 * it simply calls the BLKRRPART ioctl, which tells the kernel to
443 * reread the partition table. On newer versions (2.4.x), it will
444 * use the new blkpg interface to tell Linux where each partition
445 * starts/ends, etc. In this case, Linux does not need to have support for
446 * a specific type of partition table.
448 * \return 0 on failure, 1 otherwise.
451 ped_disk_commit_to_os (PedDisk* disk)
453 PED_ASSERT (disk != NULL);
455 if (!ped_device_open (disk->dev))
457 if (!ped_architecture->disk_ops->disk_commit (disk))
458 goto error_close_dev;
459 ped_device_close (disk->dev);
463 ped_device_close (disk->dev);
469 * Write the changes made to the in-memory description
470 * of a partition table to the device.
472 * \return 0 on failure, 1 otherwise.
475 ped_disk_commit_to_dev (PedDisk* disk)
477 PED_ASSERT (disk != NULL);
478 PED_ASSERT (!disk->update_mode);
480 if (!disk->type->ops->write) {
481 ped_exception_throw (
483 PED_EXCEPTION_CANCEL,
484 _("This libparted doesn't have write support for "
485 "%s. Perhaps it was compiled read-only."),
490 if (!ped_device_open (disk->dev))
493 if (disk->needs_clobber) {
494 if (!ped_disk_clobber (disk->dev))
495 goto error_close_dev;
496 disk->needs_clobber = 0;
498 if (!disk->type->ops->write (disk))
499 goto error_close_dev;
500 ped_device_close (disk->dev);
504 ped_device_close (disk->dev);
510 * This function writes the in-memory changes to a partition table to
511 * disk and informs the operating system of the changes.
513 * \note Equivalent to calling first ped_disk_commit_to_dev(), then
514 * ped_disk_commit_to_os().
516 * \return 0 on failure, 1 otherwise.
519 ped_disk_commit (PedDisk* disk)
521 /* Open the device here, so that the underlying fd is not closed
522 between commit_to_dev and commit_to_os (closing causes unwanted
523 udev events to be sent under Linux). */
524 if (!ped_device_open (disk->dev))
527 if (!ped_disk_commit_to_dev (disk))
528 goto error_close_dev;
530 if (!ped_disk_commit_to_os (disk))
531 goto error_close_dev;
533 ped_device_close (disk->dev);
537 ped_device_close (disk->dev);
543 * \addtogroup PedPartition
549 * Check whether a partition is mounted or busy in some
552 * \note An extended partition is busy if any logical partitions are mounted.
554 * \return \c 1 if busy.
557 ped_partition_is_busy (const PedPartition* part)
559 PED_ASSERT (part != NULL);
561 return ped_architecture->disk_ops->partition_is_busy (part);
565 * Return a path that can be used to address the partition in the
569 ped_partition_get_path (const PedPartition* part)
571 PED_ASSERT (part != NULL);
573 return ped_architecture->disk_ops->partition_get_path (part);
579 * \addtogroup PedDisk
585 * Perform a sanity check on a partition table.
587 * \note The check performed is generic (i.e. it does not depends on the label
590 * \throws PED_EXCEPTION_WARNING if a partition type ID does not match the file
593 * \return 0 if the check fails, 1 otherwise.
596 ped_disk_check (const PedDisk* disk)
600 PED_ASSERT (disk != NULL);
602 for (walk = disk->part_list; walk;
603 walk = ped_disk_next_partition (disk, walk)) {
604 const PedFileSystemType* fs_type = walk->fs_type;
606 PedSector length_error;
607 PedSector max_length_error;
609 if (!ped_partition_is_active (walk) || !fs_type)
612 geom = ped_file_system_probe_specific (fs_type, &walk->geom);
616 length_error = abs (walk->geom.length - geom->length);
617 max_length_error = PED_MAX (4096, walk->geom.length / 100);
618 bool ok = (ped_geometry_test_inside (&walk->geom, geom)
619 && length_error <= max_length_error);
620 char *fs_size = ped_unit_format (disk->dev, geom->length);
621 ped_geometry_destroy (geom);
623 char* part_size = ped_unit_format (disk->dev,
625 PedExceptionOption choice;
626 choice = ped_exception_throw (
627 PED_EXCEPTION_WARNING,
628 PED_EXCEPTION_IGNORE_CANCEL,
629 _("Partition %d is %s, but the file system is "
631 walk->num, part_size, fs_size);
638 if (choice != PED_EXCEPTION_IGNORE)
648 * This function checks if a particular type of partition table supports
651 * \return 1 if \p disk_type supports \p feature, 0 otherwise.
654 ped_disk_type_check_feature (const PedDiskType* disk_type,
655 PedDiskTypeFeature feature)
657 return (disk_type->features & feature) != 0;
661 * Get the number of primary partitions.
664 ped_disk_get_primary_partition_count (const PedDisk* disk)
669 PED_ASSERT (disk != NULL);
671 for (walk = disk->part_list; walk;
672 walk = ped_disk_next_partition (disk, walk)) {
673 if (ped_partition_is_active (walk)
674 && ! (walk->type & PED_PARTITION_LOGICAL))
682 * Get the highest available partition number on \p disk.
685 ped_disk_get_last_partition_num (const PedDisk* disk)
690 PED_ASSERT (disk != NULL);
692 for (walk = disk->part_list; walk;
693 walk = ped_disk_next_partition (disk, walk)) {
694 if (walk->num > highest)
702 * Get the highest supported partition number on \p disk.
704 * \return 0 if call fails. 1 otherwise.
707 ped_disk_get_max_supported_partition_count(const PedDisk* disk, int* supported)
709 PED_ASSERT(disk != NULL);
710 PED_ASSERT(disk->type->ops->get_max_supported_partition_count != NULL);
712 return disk->type->ops->get_max_supported_partition_count(disk, supported);
716 * Get the alignment needed for partition boundaries on this disk.
717 * The returned alignment describes the alignment for the start sector of the
718 * partition, for all disklabel types which require alignment, except Sun
719 * disklabels, the end sector must be aligned too. To get the end sector
720 * alignment decrease the PedAlignment offset by 1.
722 * \return NULL on error, otherwise a pointer to a dynamically allocated
726 ped_disk_get_partition_alignment(const PedDisk *disk)
728 /* disklabel handlers which don't need alignment don't define this */
729 if (!disk->type->ops->get_partition_alignment)
730 return ped_alignment_duplicate(ped_alignment_any);
732 return disk->type->ops->get_partition_alignment(disk);
736 * Get the maximum number of (primary) partitions the disk label supports.
738 * For example, MacIntosh partition maps can have different sizes,
739 * and accordingly support a different number of partitions.
742 ped_disk_get_max_primary_partition_count (const PedDisk* disk)
744 PED_ASSERT (disk->type != NULL);
745 PED_ASSERT (disk->type->ops->get_max_primary_partition_count != NULL);
747 return disk->type->ops->get_max_primary_partition_count (disk);
751 * Set the state (\c 1 or \c 0) of a flag on a disk.
753 * \note It is an error to call this on an unavailable flag -- use
754 * ped_disk_is_flag_available() to determine which flags are available
755 * for a given disk label.
757 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
761 ped_disk_set_flag(PedDisk *disk, PedDiskFlag flag, int state)
765 PED_ASSERT (disk != NULL);
767 PedDiskOps *ops = disk->type->ops;
769 if (!_disk_push_update_mode(disk))
772 if (!ped_disk_is_flag_available(disk, flag)) {
773 ped_exception_throw (
775 PED_EXCEPTION_CANCEL,
776 "The flag '%s' is not available for %s disk labels.",
777 ped_disk_flag_get_name(flag),
779 _disk_pop_update_mode(disk);
783 ret = ops->disk_set_flag(disk, flag, state);
785 if (!_disk_pop_update_mode (disk))
792 * Get the state (\c 1 or \c 0) of a flag on a disk.
795 ped_disk_get_flag(const PedDisk *disk, PedDiskFlag flag)
797 PED_ASSERT (disk != NULL);
799 PedDiskOps *ops = disk->type->ops;
801 if (!ped_disk_is_flag_available(disk, flag))
804 return ops->disk_get_flag(disk, flag);
808 * Check whether a given flag is available on a disk.
810 * \return \c 1 if the flag is available.
813 ped_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag)
815 PED_ASSERT (disk != NULL);
817 PedDiskOps *ops = disk->type->ops;
819 if (!ops->disk_is_flag_available)
822 return ops->disk_is_flag_available(disk, flag);
826 * Returns a name for a \p flag, e.g. PED_DISK_CYLINDER_ALIGNMENT will return
827 * "cylinder_alignment".
829 * \note The returned string will be in English. However,
830 * translations are provided, so the caller can call
831 * dgettext("parted", RESULT) on the result.
834 ped_disk_flag_get_name(PedDiskFlag flag)
837 case PED_DISK_CYLINDER_ALIGNMENT:
838 return N_("cylinder_alignment");
841 ped_exception_throw (
843 PED_EXCEPTION_CANCEL,
844 _("Unknown disk flag, %d."),
851 * Returns the flag associated with \p name.
853 * \p name can be the English
854 * string, or the translation for the native language.
857 ped_disk_flag_get_by_name(const char *name)
861 for (flag = ped_disk_flag_next(0); flag;
862 flag = ped_disk_flag_next(flag)) {
863 const char *flag_name = ped_disk_flag_get_name(flag);
864 if (strcasecmp(name, flag_name) == 0
865 || strcasecmp(name, _(flag_name)) == 0)
873 * Iterates through all disk flags.
875 * ped_disk_flag_next(0) returns the first flag
877 * \return the next flag, or 0 if there are no more flags
880 ped_disk_flag_next(PedDiskFlag flag)
882 return (flag + 1) % (PED_DISK_LAST_FLAG + 1);
886 * \internal We turned a really nasty bureaucracy problem into an elegant maths
887 * problem :-) Basically, there are some constraints to a partition's
890 * (1) it must start and end on a "disk" block, determined by the disk label
891 * (not the hardware). (constraint represented by a PedAlignment)
893 * (2) if we're resizing a partition, we MIGHT need to keep each block aligned.
894 * Eg: if an ext2 file system has 4k blocks, then we can only move the start
895 * by a multiple of 4k. (constraint represented by a PedAlignment)
897 * (3) we need to keep the start and end within the device's physical
898 * boundaries. (constraint represented by a PedGeometry)
900 * Satisfying (1) and (2) simultaneously required a bit of fancy maths ;-) See
901 * ped_alignment_intersect()
903 * The application of these constraints is in disk_*.c's *_partition_align()
907 _partition_align (PedPartition* part, const PedConstraint* constraint)
909 const PedDiskType* disk_type;
911 PED_ASSERT (part != NULL);
912 PED_ASSERT (part->num != -1);
913 PED_ASSERT (part->disk != NULL);
914 disk_type = part->disk->type;
915 PED_ASSERT (disk_type != NULL);
916 PED_ASSERT (disk_type->ops->partition_align != NULL);
917 PED_ASSERT (part->disk->update_mode);
919 return disk_type->ops->partition_align (part, constraint);
923 _partition_enumerate (PedPartition* part)
925 const PedDiskType* disk_type;
927 PED_ASSERT (part != NULL);
928 PED_ASSERT (part->disk != NULL);
929 disk_type = part->disk->type;
930 PED_ASSERT (disk_type != NULL);
931 PED_ASSERT (disk_type->ops->partition_enumerate != NULL);
933 return disk_type->ops->partition_enumerate (part);
937 * Gives all the (active) partitions a number. It should preserve the numbers
938 * and orders as much as possible.
941 ped_disk_enumerate_partitions (PedDisk* disk)
947 PED_ASSERT (disk != NULL);
949 /* first "sort" already-numbered partitions. (e.g. if a logical partition
950 * is removed, then all logical partitions that were number higher MUST be
953 end = ped_disk_get_last_partition_num (disk);
954 for (i=1; i<=end; i++) {
955 walk = ped_disk_get_partition (disk, i);
957 if (!_partition_enumerate (walk))
962 /* now, number un-numbered partitions */
963 for (walk = disk->part_list; walk;
964 walk = ped_disk_next_partition (disk, walk)) {
965 if (ped_partition_is_active (walk) && walk->num == -1) {
966 if (!_partition_enumerate (walk))
975 _disk_remove_metadata (PedDisk* disk)
977 PedPartition* walk = NULL;
980 PED_ASSERT (disk != NULL);
982 next = ped_disk_next_partition (disk, walk);
987 next = ped_disk_next_partition (disk, next);
988 if (!next || next->type & PED_PARTITION_METADATA)
991 if (walk->type & PED_PARTITION_METADATA)
992 ped_disk_delete_partition (disk, walk);
998 _disk_alloc_metadata (PedDisk* disk)
1000 PED_ASSERT (disk != NULL);
1002 if (!disk->update_mode)
1003 _disk_remove_metadata (disk);
1005 return disk->type->ops->alloc_metadata (disk);
1009 _disk_remove_freespace (PedDisk* disk)
1014 walk = ped_disk_next_partition (disk, NULL);
1015 for (; walk; walk = next) {
1016 next = ped_disk_next_partition (disk, walk);
1018 if (walk->type & PED_PARTITION_FREESPACE) {
1019 _disk_raw_remove (disk, walk);
1020 ped_partition_destroy (walk);
1028 _alloc_extended_freespace (PedDisk* disk)
1033 PedPartition* free_space;
1034 PedPartition* extended_part;
1036 extended_part = ped_disk_extended_partition (disk);
1040 last_end = extended_part->geom.start;
1043 for (walk = extended_part->part_list; walk; walk = walk->next) {
1044 if (walk->geom.start > last_end + 1) {
1045 free_space = ped_partition_new (
1047 PED_PARTITION_FREESPACE
1048 | PED_PARTITION_LOGICAL,
1050 last_end + 1, walk->geom.start - 1);
1051 _disk_raw_insert_before (disk, walk, free_space);
1055 last_end = last->geom.end;
1058 if (last_end < extended_part->geom.end) {
1059 free_space = ped_partition_new (
1061 PED_PARTITION_FREESPACE | PED_PARTITION_LOGICAL,
1063 last_end + 1, extended_part->geom.end);
1066 return _disk_raw_insert_after (disk, last, free_space);
1068 extended_part->part_list = free_space;
1075 _disk_alloc_freespace (PedDisk* disk)
1080 PedPartition* free_space;
1082 if (!_disk_remove_freespace (disk))
1084 if (!_alloc_extended_freespace (disk))
1090 for (walk = disk->part_list; walk; walk = walk->next) {
1091 if (walk->geom.start > last_end + 1) {
1092 free_space = ped_partition_new (disk,
1093 PED_PARTITION_FREESPACE, NULL,
1094 last_end + 1, walk->geom.start - 1);
1095 _disk_raw_insert_before (disk, walk, free_space);
1099 last_end = last->geom.end;
1102 if (last_end < disk->dev->length - 1) {
1103 free_space = ped_partition_new (disk,
1104 PED_PARTITION_FREESPACE, NULL,
1105 last_end + 1, disk->dev->length - 1);
1107 return _disk_raw_insert_after (disk, last, free_space);
1109 disk->part_list = free_space;
1116 * Update mode: used when updating the internal representation of the partition
1117 * table. In update mode, the metadata and freespace placeholder/virtual
1118 * partitions are removed, making it much easier for various manipulation
1122 _disk_push_update_mode (PedDisk* disk)
1124 if (!disk->update_mode) {
1126 if (!_disk_check_sanity (disk))
1130 _disk_remove_freespace (disk);
1131 disk->update_mode++;
1132 _disk_remove_metadata (disk);
1135 if (!_disk_check_sanity (disk))
1139 disk->update_mode++;
1145 _disk_pop_update_mode (PedDisk* disk)
1147 PED_ASSERT (disk->update_mode);
1149 if (disk->update_mode == 1) {
1150 /* re-allocate metadata BEFORE leaving update mode, to prevent infinite
1151 * recursion (metadata allocation requires update mode)
1154 if (!_disk_check_sanity (disk))
1158 _disk_alloc_metadata (disk);
1159 disk->update_mode--;
1160 _disk_alloc_freespace (disk);
1163 if (!_disk_check_sanity (disk))
1167 disk->update_mode--;
1175 * \addtogroup PedPartition
1177 * \brief Partition access.
1183 _ped_partition_alloc (const PedDisk* disk, PedPartitionType type,
1184 const PedFileSystemType* fs_type,
1185 PedSector start, PedSector end)
1189 PED_ASSERT (disk != NULL);
1191 part = (PedPartition*) ped_malloc (sizeof (PedPartition));
1198 part->disk = (PedDisk*) disk;
1199 if (!ped_geometry_init (&part->geom, disk->dev, start, end - start + 1))
1200 goto error_free_part;
1204 part->part_list = NULL;
1205 part->fs_type = fs_type;
1216 _ped_partition_free (PedPartition* part)
1222 _ped_partition_attempt_align (PedPartition* part,
1223 const PedConstraint* external,
1224 PedConstraint* internal)
1226 PedConstraint* intersection;
1227 PedGeometry* solution;
1229 intersection = ped_constraint_intersect (external, internal);
1230 ped_constraint_destroy (internal);
1234 solution = ped_constraint_solve_nearest (intersection, &part->geom);
1236 goto fail_free_intersection;
1237 ped_geometry_set (&part->geom, solution->start, solution->length);
1238 ped_geometry_destroy (solution);
1239 ped_constraint_destroy (intersection);
1242 fail_free_intersection:
1243 ped_constraint_destroy (intersection);
1249 * Create a new \link _PedPartition PedPartition \endlink on \p disk.
1251 * \param type One of \p PED_PARTITION_NORMAL, \p PED_PARTITION_EXTENDED,
1252 * \p PED_PARTITION_LOGICAL.
1254 * \note The constructed partition is not added to <tt>disk</tt>'s
1255 * partition table. Use ped_disk_add_partition() to do this.
1257 * \return A new \link _PedPartition PedPartition \endlink object,
1260 * \throws PED_EXCEPTION_ERROR if \p type is \p EXTENDED or \p LOGICAL but the
1261 * label does not support this concept.
1264 ped_partition_new (const PedDisk* disk, PedPartitionType type,
1265 const PedFileSystemType* fs_type, PedSector start,
1268 int supports_extended;
1271 PED_ASSERT (disk != NULL);
1272 PED_ASSERT (disk->type->ops->partition_new != NULL);
1274 supports_extended = ped_disk_type_check_feature (disk->type,
1275 PED_DISK_TYPE_EXTENDED);
1277 if (!supports_extended
1278 && (type == PED_PARTITION_EXTENDED
1279 || type == PED_PARTITION_LOGICAL)) {
1280 ped_exception_throw (
1281 PED_EXCEPTION_ERROR,
1282 PED_EXCEPTION_CANCEL,
1283 _("%s disk labels do not support extended "
1289 part = disk->type->ops->partition_new (disk, type, fs_type, start, end);
1293 if (fs_type || part->type == PED_PARTITION_EXTENDED) {
1294 if (!ped_partition_set_system (part, fs_type))
1295 goto error_destroy_part;
1300 ped_partition_destroy (part);
1306 * Destroy a \link _PedPartition PedPartition \endlink object.
1308 * \note Should not be called on a partition that is in a partition table.
1309 * Use ped_disk_delete_partition() instead.
1312 ped_partition_destroy (PedPartition* part)
1314 PED_ASSERT (part != NULL);
1315 PED_ASSERT (part->disk != NULL);
1316 PED_ASSERT (part->disk->type->ops->partition_new != NULL);
1318 part->disk->type->ops->partition_destroy (part);
1323 * Return whether or not the partition is "active".
1325 * A partition is active if \p part->type is neither \p PED_PARTITION_METADATA
1326 * nor \p PED_PARTITION_FREE.
1329 ped_partition_is_active (const PedPartition* part)
1331 PED_ASSERT (part != NULL);
1333 return !(part->type & PED_PARTITION_FREESPACE
1334 || part->type & PED_PARTITION_METADATA);
1338 * Set the state (\c 1 or \c 0) of a flag on a partition.
1340 * Flags are disk label specific, although they have a global
1341 * "namespace": the flag PED_PARTITION_BOOT, for example, roughly means
1342 * "this" partition is bootable". But this means different things on different
1343 * disk labels (and may not be defined on some disk labels). For example,
1344 * on MS-DOS disk labels, there can only be one boot partition, and this
1345 * refers to the partition that will be booted from on startup. On PC98
1346 * disk labels, the user can choose from any bootable partition on startup.
1348 * \note It is an error to call this on an unavailable flag -- use
1349 * ped_partition_is_flag_available() to determine which flags are available
1350 * for a given disk label.
1352 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
1356 ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1360 PED_ASSERT (part != NULL);
1361 PED_ASSERT (part->disk != NULL);
1362 PED_ASSERT (ped_partition_is_active (part));
1364 ops = part->disk->type->ops;
1365 PED_ASSERT (ops->partition_set_flag != NULL);
1366 PED_ASSERT (ops->partition_is_flag_available != NULL);
1368 if (!ops->partition_is_flag_available (part, flag)) {
1369 ped_exception_throw (
1370 PED_EXCEPTION_ERROR,
1371 PED_EXCEPTION_CANCEL,
1372 "The flag '%s' is not available for %s disk labels.",
1373 ped_partition_flag_get_name (flag),
1374 part->disk->type->name);
1378 return ops->partition_set_flag (part, flag, state);
1382 * Get the state (\c 1 or \c 0) of a flag on a partition.
1384 * See ped_partition_set_flag() for conditions that must hold.
1386 * \todo Where's the check for flag availability?
1389 ped_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1391 PED_ASSERT (part != NULL);
1392 PED_ASSERT (part->disk != NULL);
1393 PED_ASSERT (part->disk->type->ops->partition_get_flag != NULL);
1394 PED_ASSERT (ped_partition_is_active (part));
1396 return part->disk->type->ops->partition_get_flag (part, flag);
1400 * Check whether a given flag is available on a partition.
1402 * \return \c 1 if the flag is available.
1405 ped_partition_is_flag_available (const PedPartition* part,
1406 PedPartitionFlag flag)
1408 PED_ASSERT (part != NULL);
1409 PED_ASSERT (part->disk != NULL);
1410 PED_ASSERT (part->disk->type->ops->partition_is_flag_available != NULL);
1411 PED_ASSERT (ped_partition_is_active (part));
1413 return part->disk->type->ops->partition_is_flag_available (part, flag);
1417 * Sets the system type on the partition to \p fs_type.
1419 * \note The file system may be opened, to get more information about the
1420 * file system, e.g. to determine if it's FAT16 or FAT32.
1422 * \return \c 0 on failure.
1425 ped_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1427 const PedDiskType* disk_type;
1429 PED_ASSERT (part != NULL);
1430 PED_ASSERT (ped_partition_is_active (part));
1431 PED_ASSERT (part->disk != NULL);
1432 disk_type = part->disk->type;
1433 PED_ASSERT (disk_type != NULL);
1434 PED_ASSERT (disk_type->ops != NULL);
1435 PED_ASSERT (disk_type->ops->partition_set_system != NULL);
1437 return disk_type->ops->partition_set_system (part, fs_type);
1441 _assert_partition_name_feature (const PedDiskType* disk_type)
1443 if (!ped_disk_type_check_feature (
1444 disk_type, PED_DISK_TYPE_PARTITION_NAME)) {
1445 ped_exception_throw (
1446 PED_EXCEPTION_ERROR,
1447 PED_EXCEPTION_CANCEL,
1448 "%s disk labels do not support partition names.",
1456 * Sets the name of a partition.
1458 * \note This will only work if the disk label supports it.
1461 * ped_disk_type_check_feature (part->disk->type, PED_DISK_TYPE_PARTITION_NAME);
1463 * to check whether this feature is enabled for a label.
1465 * \note \p name will not be modified by libparted. It can be freed
1466 * by the caller immediately after ped_partition_set_name() is called.
1468 * \return \c 1 on success, \c 0 otherwise.
1471 ped_partition_set_name (PedPartition* part, const char* name)
1473 PED_ASSERT (part != NULL);
1474 PED_ASSERT (part->disk != NULL);
1475 PED_ASSERT (ped_partition_is_active (part));
1476 PED_ASSERT (name != NULL);
1478 if (!_assert_partition_name_feature (part->disk->type))
1481 PED_ASSERT (part->disk->type->ops->partition_set_name != NULL);
1482 part->disk->type->ops->partition_set_name (part, name);
1487 * Returns the name of a partition \p part. This will only work if the disk
1488 * label supports it.
1490 * \note The returned string should not be modified. It should
1491 * not be referenced after the partition is destroyed.
1494 ped_partition_get_name (const PedPartition* part)
1496 PED_ASSERT (part != NULL);
1497 PED_ASSERT (part->disk != NULL);
1498 PED_ASSERT (ped_partition_is_active (part));
1500 if (!_assert_partition_name_feature (part->disk->type))
1503 PED_ASSERT (part->disk->type->ops->partition_get_name != NULL);
1504 return part->disk->type->ops->partition_get_name (part);
1510 * \addtogroup PedDisk
1516 ped_disk_extended_partition (const PedDisk* disk)
1520 PED_ASSERT (disk != NULL);
1522 for (walk = disk->part_list; walk; walk = walk->next) {
1523 if (walk->type == PED_PARTITION_EXTENDED)
1530 * Return the next partition after \p part on \p disk. If \p part is \c NULL,
1531 * return the first partition. If \p part is the last partition, returns
1532 * \c NULL. If \p part is an extended partition, returns the first logical
1533 * partition. If this is called repeatedly passing the return value as \p part,
1534 * a depth-first traversal is executed.
1536 * \return The next partition, \c NULL if no more partitions left.
1539 ped_disk_next_partition (const PedDisk* disk, const PedPartition* part)
1541 PED_ASSERT (disk != NULL);
1544 return disk->part_list;
1545 if (part->type == PED_PARTITION_EXTENDED)
1546 return part->part_list ? part->part_list : part->next;
1549 if (part->type & PED_PARTITION_LOGICAL)
1550 return ped_disk_extended_partition (disk)->next;
1557 static int _GL_ATTRIBUTE_PURE
1558 _disk_check_sanity (PedDisk* disk)
1562 PED_ASSERT (disk != NULL);
1564 for (walk = disk->part_list; walk; walk = walk->next) {
1565 PED_ASSERT (!(walk->type & PED_PARTITION_LOGICAL));
1566 PED_ASSERT (!walk->prev || walk->prev->next == walk);
1569 if (!ped_disk_extended_partition (disk))
1572 for (walk = ped_disk_extended_partition (disk)->part_list; walk;
1573 walk = walk->next) {
1574 PED_ASSERT (walk->type & PED_PARTITION_LOGICAL);
1576 PED_ASSERT (walk->prev->next == walk);
1583 * Returns the partition numbered \p num.
1585 * \return \c NULL if the specified partition does not exist.
1588 ped_disk_get_partition (const PedDisk* disk, int num)
1592 PED_ASSERT (disk != NULL);
1594 for (walk = disk->part_list; walk;
1595 walk = ped_disk_next_partition (disk, walk)) {
1596 if (walk->num == num && !(walk->type & PED_PARTITION_FREESPACE))
1604 * Returns the partition that contains sect. If sect lies within a logical
1605 * partition, then the logical partition is returned (not the extended
1609 ped_disk_get_partition_by_sector (const PedDisk* disk, PedSector sect)
1613 PED_ASSERT (disk != NULL);
1615 for (walk = disk->part_list; walk;
1616 walk = ped_disk_next_partition (disk, walk)) {
1617 if (ped_geometry_test_sector_inside (&walk->geom, sect)
1618 && walk->type != PED_PARTITION_EXTENDED)
1622 /* should never get here, unless sect is outside of disk's useable
1623 * part, or we're in "update mode", and the free space place-holders
1624 * have been removed with _disk_remove_freespace()
1630 * Return the maximum representable length (in sectors) of a
1631 * partition on disk \disk.
1634 ped_disk_max_partition_length (const PedDisk* disk)
1636 return disk->type->ops->max_length ();
1640 * Return the maximum representable start sector of a
1641 * partition on disk \disk.
1644 ped_disk_max_partition_start_sector (const PedDisk* disk)
1646 return disk->type->ops->max_start_sector ();
1649 /* I'm beginning to agree with Sedgewick :-/ */
1651 _disk_raw_insert_before (PedDisk* disk, PedPartition* loc, PedPartition* part)
1653 PED_ASSERT (disk != NULL);
1654 PED_ASSERT (loc != NULL);
1655 PED_ASSERT (part != NULL);
1657 part->prev = loc->prev;
1660 part->prev->next = part;
1662 if (loc->type & PED_PARTITION_LOGICAL)
1663 ped_disk_extended_partition (disk)->part_list = part;
1665 disk->part_list = part;
1673 _disk_raw_insert_after (PedDisk* disk, PedPartition* loc, PedPartition* part)
1675 PED_ASSERT (disk != NULL);
1676 PED_ASSERT (loc != NULL);
1677 PED_ASSERT (part != NULL);
1680 part->next = loc->next;
1682 loc->next->prev = part;
1689 _disk_raw_remove (PedDisk* disk, PedPartition* part)
1691 PED_ASSERT (disk != NULL);
1692 PED_ASSERT (part != NULL);
1695 part->prev->next = part->next;
1697 part->next->prev = part->prev;
1699 if (part->type & PED_PARTITION_LOGICAL) {
1700 ped_disk_extended_partition (disk)->part_list
1703 disk->part_list = part->next;
1706 part->next->prev = NULL;
1716 _disk_raw_add (PedDisk* disk, PedPartition* part)
1720 PedPartition* ext_part;
1722 PED_ASSERT (disk->update_mode);
1724 ext_part = ped_disk_extended_partition (disk);
1727 walk = (part->type & PED_PARTITION_LOGICAL) ?
1728 ext_part->part_list : disk->part_list;
1730 for (; walk; last = walk, walk = walk->next) {
1731 if (walk->geom.start > part->geom.end)
1736 return _disk_raw_insert_before (disk, walk, part);
1739 return _disk_raw_insert_after (disk, last, part);
1741 if (part->type & PED_PARTITION_LOGICAL)
1742 ext_part->part_list = part;
1744 disk->part_list = part;
1751 static PedConstraint*
1752 _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
1754 PedSector min_start;
1757 PedGeometry free_space;
1759 PED_ASSERT (part->disk->update_mode);
1760 PED_ASSERT (part->geom.dev == geom->dev);
1762 if (part->type & PED_PARTITION_LOGICAL) {
1763 PedPartition* ext_part;
1765 ext_part = ped_disk_extended_partition (part->disk);
1766 PED_ASSERT (ext_part != NULL);
1768 min_start = ext_part->geom.start;
1769 max_end = ext_part->geom.end;
1770 walk = ext_part->part_list;
1773 max_end = part->disk->dev->length - 1;
1774 walk = part->disk->part_list;
1778 && (walk->geom.start < geom->start
1779 || min_start >= walk->geom.start)) {
1781 min_start = walk->geom.end + 1;
1789 max_end = walk->geom.start - 1;
1791 if (min_start >= max_end)
1794 ped_geometry_init (&free_space, part->disk->dev,
1795 min_start, max_end - min_start + 1);
1796 return ped_constraint_new_from_max (&free_space);
1800 * Returns \c 0 if the partition, \p part overlaps with any partitions on the
1801 * \p disk. The geometry of \p part is taken to be \p geom, NOT \p part->geom
1802 * (the idea here is to check if \p geom is valid, before changing \p part).
1804 * This is useful for seeing if a resized partitions new geometry is going to
1805 * fit, without the existing geomtry getting in the way.
1807 * Note: overlap with an extended partition is also allowed, provided that
1808 * \p geom lies completely inside the extended partition.
1810 static int _GL_ATTRIBUTE_PURE
1811 _disk_check_part_overlaps (PedDisk* disk, PedPartition* part)
1815 PED_ASSERT (disk != NULL);
1816 PED_ASSERT (part != NULL);
1818 for (walk = ped_disk_next_partition (disk, NULL); walk;
1819 walk = ped_disk_next_partition (disk, walk)) {
1820 if (walk->type & PED_PARTITION_FREESPACE)
1824 if (part->type & PED_PARTITION_EXTENDED
1825 && walk->type & PED_PARTITION_LOGICAL)
1828 if (ped_geometry_test_overlap (&walk->geom, &part->geom)) {
1829 if (walk->type & PED_PARTITION_EXTENDED
1830 && part->type & PED_PARTITION_LOGICAL
1831 && ped_geometry_test_inside (&walk->geom,
1842 _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
1844 PedPartition* ext_part = ped_disk_extended_partition (disk);
1846 PED_ASSERT (part->disk == disk);
1848 PED_ASSERT (part->geom.start >= 0);
1849 PED_ASSERT (part->geom.end < disk->dev->length);
1850 PED_ASSERT (part->geom.start <= part->geom.end);
1852 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
1853 && (part->type == PED_PARTITION_EXTENDED
1854 || part->type == PED_PARTITION_LOGICAL)) {
1855 ped_exception_throw (
1856 PED_EXCEPTION_ERROR,
1857 PED_EXCEPTION_CANCEL,
1858 _("%s disk labels don't support logical or extended "
1864 if (ped_partition_is_active (part)
1865 && ! (part->type & PED_PARTITION_LOGICAL)) {
1866 if (ped_disk_get_primary_partition_count (disk) + 1
1867 > ped_disk_get_max_primary_partition_count (disk)) {
1868 ped_exception_throw (
1869 PED_EXCEPTION_ERROR,
1870 PED_EXCEPTION_CANCEL,
1871 _("Too many primary partitions."));
1876 if ((part->type & PED_PARTITION_LOGICAL) && !ext_part) {
1877 ped_exception_throw (
1878 PED_EXCEPTION_ERROR,
1879 PED_EXCEPTION_CANCEL,
1880 _("Can't add a logical partition to %s, because "
1881 "there is no extended partition."),
1890 _check_extended_partition (PedDisk* disk, PedPartition* part)
1893 PedPartition* ext_part;
1895 PED_ASSERT (disk != NULL);
1896 ext_part = ped_disk_extended_partition (disk);
1897 if (!ext_part) ext_part = part;
1898 PED_ASSERT (ext_part != NULL);
1900 if (part != ext_part) {
1901 ped_exception_throw (
1902 PED_EXCEPTION_ERROR,
1903 PED_EXCEPTION_CANCEL,
1904 _("Can't have more than one extended partition on %s."),
1909 for (walk = ext_part->part_list; walk; walk = walk->next) {
1910 if (!ped_geometry_test_inside (&ext_part->geom, &walk->geom)) {
1911 ped_exception_throw (
1912 PED_EXCEPTION_ERROR,
1913 PED_EXCEPTION_CANCEL,
1914 _("Can't have logical partitions outside of "
1915 "the extended partition."));
1923 _check_partition (PedDisk* disk, PedPartition* part)
1925 PedPartition* ext_part = ped_disk_extended_partition (disk);
1927 PED_ASSERT (part->geom.start <= part->geom.end);
1929 if (part->type == PED_PARTITION_EXTENDED) {
1930 if (!_check_extended_partition (disk, part))
1934 if (part->type & PED_PARTITION_LOGICAL
1935 && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1936 ped_exception_throw (
1937 PED_EXCEPTION_ERROR,
1938 PED_EXCEPTION_CANCEL,
1939 _("Can't have a logical partition outside of the "
1940 "extended partition on %s."),
1945 if (!_disk_check_part_overlaps (disk, part)) {
1946 ped_exception_throw (
1947 PED_EXCEPTION_ERROR,
1948 PED_EXCEPTION_CANCEL,
1949 _("Can't have overlapping partitions."));
1953 if (! (part->type & PED_PARTITION_LOGICAL)
1954 && ext_part && ext_part != part
1955 && ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1956 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1957 _("Can't have a primary partition inside an extended "
1962 if (!(part->type & PED_PARTITION_METADATA))
1963 if (!disk->type->ops->partition_check(part))
1970 * Adds PedPartition \p part to PedPartition \p disk.
1972 * \warning The partition's geometry may be changed, subject to \p constraint.
1973 * You could set \p constraint to <tt>ped_constraint_exact(&part->geom)</tt>,
1974 * but many partition table schemes have special requirements on the start
1975 * and end of partitions. Therefore, having an overly strict constraint
1976 * will probably mean that this function will fail (in which
1977 * case \p part will be left unmodified)
1978 * \p part is assigned a number (\p part->num) in this process.
1980 * \return \c 0 on failure.
1983 ped_disk_add_partition (PedDisk* disk, PedPartition* part,
1984 const PedConstraint* constraint)
1986 PedConstraint* overlap_constraint = NULL;
1987 PedConstraint* constraints = NULL;
1989 PED_ASSERT (disk != NULL);
1990 PED_ASSERT (part != NULL);
1992 if (!_partition_check_basic_sanity (disk, part))
1995 if (!_disk_push_update_mode (disk))
1998 if (ped_partition_is_active (part)) {
2000 = _partition_get_overlap_constraint (part, &part->geom);
2001 constraints = ped_constraint_intersect (overlap_constraint,
2004 if (!constraints && constraint) {
2005 ped_exception_throw (
2006 PED_EXCEPTION_ERROR,
2007 PED_EXCEPTION_CANCEL,
2008 _("Can't have overlapping partitions."));
2012 if (!_partition_enumerate (part))
2014 if (!_partition_align (part, constraints))
2017 /* FIXME: when _check_partition fails, we end up leaking PART
2018 at least for DVH partition tables. Simply calling
2019 ped_partition_destroy(part) here fixes it for DVH, but
2020 causes trouble for other partition types. Similarly,
2021 reordering these two checks, putting _check_partition after
2022 _disk_raw_add induces an infinite loop. */
2023 if (!_check_partition (disk, part))
2025 if (!_disk_raw_add (disk, part))
2028 ped_constraint_destroy (overlap_constraint);
2029 ped_constraint_destroy (constraints);
2030 if (!_disk_pop_update_mode (disk))
2033 if (!_disk_check_sanity (disk))
2039 ped_constraint_destroy (overlap_constraint);
2040 ped_constraint_destroy (constraints);
2041 _disk_pop_update_mode (disk);
2046 * Removes PedPartition \p part from PedDisk \p disk.
2048 * If \p part is an extended partition, it must not contain any logical
2049 * partitions. \p part is *NOT* destroyed. The caller must call
2050 * ped_partition_destroy(), or use ped_disk_delete_partition() instead.
2052 * \return \c 0 on error.
2055 ped_disk_remove_partition (PedDisk* disk, PedPartition* part)
2057 PED_ASSERT (disk != NULL);
2058 PED_ASSERT (part != NULL);
2060 if (!_disk_push_update_mode (disk))
2062 PED_ASSERT (part->part_list == NULL);
2063 _disk_raw_remove (disk, part);
2064 if (!_disk_pop_update_mode (disk))
2066 ped_disk_enumerate_partitions (disk);
2071 ped_disk_delete_all_logical (PedDisk* disk);
2074 * Removes \p part from \p disk, and destroys \p part.
2076 * \return \c 0 on failure.
2079 ped_disk_delete_partition (PedDisk* disk, PedPartition* part)
2081 PED_ASSERT (disk != NULL);
2082 PED_ASSERT (part != NULL);
2084 if (!_disk_push_update_mode (disk))
2086 if (part->type == PED_PARTITION_EXTENDED)
2087 ped_disk_delete_all_logical (disk);
2088 ped_disk_remove_partition (disk, part);
2089 ped_partition_destroy (part);
2090 if (!_disk_pop_update_mode (disk))
2097 ped_disk_delete_all_logical (PedDisk* disk)
2101 PedPartition* ext_part;
2103 PED_ASSERT (disk != NULL);
2104 ext_part = ped_disk_extended_partition (disk);
2105 PED_ASSERT (ext_part != NULL);
2107 for (walk = ext_part->part_list; walk; walk = next) {
2110 if (!ped_disk_delete_partition (disk, walk))
2117 * Removes and destroys all partitions on \p disk.
2119 * \return \c 0 on failure.
2122 ped_disk_delete_all (PedDisk* disk)
2127 PED_ASSERT (disk != NULL);
2129 if (!_disk_push_update_mode (disk))
2132 for (walk = disk->part_list; walk; walk = next) {
2135 if (!ped_disk_delete_partition (disk, walk)) {
2136 _disk_pop_update_mode(disk);
2141 if (!_disk_pop_update_mode (disk))
2148 * Sets the geometry of \p part (i.e. change a partitions location). This can
2149 * fail for many reasons, e.g. can't overlap with other partitions. If it
2150 * does fail, \p part will remain unchanged. Returns \c 0 on failure. \p part's
2151 * geometry may be set to something different from \p start and \p end subject
2154 * \warning The constraint warning from ped_disk_add_partition() applies.
2156 * \note this function does not modify the contents of the partition. You need
2157 * to call ped_file_system_resize() separately.
2160 ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part,
2161 const PedConstraint* constraint,
2162 PedSector start, PedSector end)
2164 PedConstraint* overlap_constraint = NULL;
2165 PedConstraint* constraints = NULL;
2166 PedGeometry old_geom;
2167 PedGeometry new_geom;
2169 PED_ASSERT (disk != NULL);
2170 PED_ASSERT (part != NULL);
2171 PED_ASSERT (part->disk == disk);
2173 old_geom = part->geom;
2174 if (!ped_geometry_init (&new_geom, part->geom.dev, start, end - start + 1))
2177 if (!_disk_push_update_mode (disk))
2181 = _partition_get_overlap_constraint (part, &new_geom);
2182 constraints = ped_constraint_intersect (overlap_constraint, constraint);
2183 if (!constraints && constraint) {
2184 ped_exception_throw (
2185 PED_EXCEPTION_ERROR,
2186 PED_EXCEPTION_CANCEL,
2187 _("Can't have overlapping partitions."));
2188 goto error_pop_update_mode;
2191 part->geom = new_geom;
2192 if (!_partition_align (part, constraints))
2193 goto error_pop_update_mode;
2194 if (!_check_partition (disk, part))
2195 goto error_pop_update_mode;
2197 /* remove and add, to ensure the ordering gets updated if necessary */
2198 _disk_raw_remove (disk, part);
2199 _disk_raw_add (disk, part);
2201 if (!_disk_pop_update_mode (disk))
2204 ped_constraint_destroy (overlap_constraint);
2205 ped_constraint_destroy (constraints);
2208 error_pop_update_mode:
2209 _disk_pop_update_mode (disk);
2211 ped_constraint_destroy (overlap_constraint);
2212 ped_constraint_destroy (constraints);
2213 part->geom = old_geom;
2218 * Grow PedPartition \p part geometry to the maximum possible subject to
2219 * \p constraint. The new geometry will be a superset of the old geometry.
2221 * \return 0 on failure
2224 ped_disk_maximize_partition (PedDisk* disk, PedPartition* part,
2225 const PedConstraint* constraint)
2227 PedGeometry old_geom;
2228 PedSector global_min_start;
2229 PedSector global_max_end;
2230 PedSector new_start;
2232 PedPartition* ext_part = ped_disk_extended_partition (disk);
2233 PedConstraint* constraint_any;
2235 PED_ASSERT (disk != NULL);
2236 PED_ASSERT (part != NULL);
2238 if (part->type & PED_PARTITION_LOGICAL) {
2239 PED_ASSERT (ext_part != NULL);
2240 global_min_start = ext_part->geom.start;
2241 global_max_end = ext_part->geom.end;
2243 global_min_start = 0;
2244 global_max_end = disk->dev->length - 1;
2247 old_geom = part->geom;
2249 if (!_disk_push_update_mode (disk))
2253 new_start = part->prev->geom.end + 1;
2255 new_start = global_min_start;
2258 new_end = part->next->geom.start - 1;
2260 new_end = global_max_end;
2262 if (!ped_disk_set_partition_geom (disk, part, constraint, new_start,
2266 if (!_disk_pop_update_mode (disk))
2271 constraint_any = ped_constraint_any (disk->dev);
2272 ped_disk_set_partition_geom (disk, part, constraint_any,
2273 old_geom.start, old_geom.end);
2274 ped_constraint_destroy (constraint_any);
2275 _disk_pop_update_mode (disk);
2280 * Get the maximum geometry \p part can be grown to, subject to
2283 * \return \c NULL on failure.
2286 ped_disk_get_max_partition_geometry (PedDisk* disk, PedPartition* part,
2287 const PedConstraint* constraint)
2289 PedGeometry old_geom;
2290 PedGeometry* max_geom;
2291 PedConstraint* constraint_exact;
2293 PED_ASSERT(disk != NULL);
2294 PED_ASSERT(part != NULL);
2295 PED_ASSERT(ped_partition_is_active (part));
2297 old_geom = part->geom;
2298 if (!ped_disk_maximize_partition (disk, part, constraint))
2300 max_geom = ped_geometry_duplicate (&part->geom);
2302 constraint_exact = ped_constraint_exact (&old_geom);
2303 ped_disk_set_partition_geom (disk, part, constraint_exact,
2304 old_geom.start, old_geom.end);
2305 ped_constraint_destroy (constraint_exact);
2307 /* this assertion should never fail, because the old
2308 * geometry was valid
2310 PED_ASSERT (ped_geometry_test_equal (&part->geom, &old_geom));
2316 * Reduce the size of the extended partition to a minimum while still wrapping
2317 * its logical partitions. If there are no logical partitions, remove the
2318 * extended partition.
2320 * \return 0 on failure.
2323 ped_disk_minimize_extended_partition (PedDisk* disk)
2325 PedPartition* first_logical;
2326 PedPartition* last_logical;
2328 PedPartition* ext_part;
2329 PedConstraint* constraint;
2332 PED_ASSERT (disk != NULL);
2334 ext_part = ped_disk_extended_partition (disk);
2338 if (!_disk_push_update_mode (disk))
2341 first_logical = ext_part->part_list;
2342 if (!first_logical) {
2343 if (!_disk_pop_update_mode (disk))
2345 return ped_disk_delete_partition (disk, ext_part);
2348 for (walk = first_logical; walk->next; walk = walk->next);
2349 last_logical = walk;
2351 constraint = ped_constraint_any (disk->dev);
2352 status = ped_disk_set_partition_geom (disk, ext_part, constraint,
2353 first_logical->geom.start,
2354 last_logical->geom.end);
2355 ped_constraint_destroy (constraint);
2357 if (!_disk_pop_update_mode (disk))
2367 * \addtogroup PedPartition
2373 * Returns a name that seems mildly appropriate for a partition type \p type.
2375 * Eg, if you pass (PED_PARTITION_LOGICAL & PED_PARTITION_FREESPACE), it
2376 * will return "free". This isn't to be taken too seriously - it's just
2377 * useful for user interfaces, so you can show the user something ;-)
2379 * \note The returned string will be in English. However,
2380 * translations are provided, so the caller can call
2381 * dgettext("parted", RESULT) on the result.
2385 ped_partition_type_get_name (PedPartitionType type)
2387 if (type & PED_PARTITION_METADATA)
2388 return N_("metadata");
2389 else if (type & PED_PARTITION_FREESPACE)
2391 else if (type & PED_PARTITION_EXTENDED)
2392 return N_("extended");
2393 else if (type & PED_PARTITION_LOGICAL)
2394 return N_("logical");
2396 return N_("primary");
2401 * Returns a name for a \p flag, e.g. PED_PARTITION_BOOT will return "boot".
2403 * \note The returned string will be in English. However,
2404 * translations are provided, so the caller can call
2405 * dgettext("parted", RESULT) on the result.
2408 ped_partition_flag_get_name (PedPartitionFlag flag)
2411 case PED_PARTITION_BOOT:
2413 case PED_PARTITION_BIOS_GRUB:
2414 return N_("bios_grub");
2415 case PED_PARTITION_ROOT:
2417 case PED_PARTITION_SWAP:
2419 case PED_PARTITION_HIDDEN:
2420 return N_("hidden");
2421 case PED_PARTITION_RAID:
2423 case PED_PARTITION_LVM:
2425 case PED_PARTITION_LBA:
2427 case PED_PARTITION_HPSERVICE:
2428 return N_("hp-service");
2429 case PED_PARTITION_PALO:
2431 case PED_PARTITION_PREP:
2433 case PED_PARTITION_MSFT_RESERVED:
2434 return N_("msftres");
2435 case PED_PARTITION_APPLE_TV_RECOVERY:
2436 return N_("atvrecv");
2437 case PED_PARTITION_DIAG:
2439 case PED_PARTITION_LEGACY_BOOT:
2440 return N_("legacy_boot");
2443 ped_exception_throw (
2445 PED_EXCEPTION_CANCEL,
2446 _("Unknown partition flag, %d."),
2453 * Iterates through all flags.
2455 * ped_partition_flag_next(0) returns the first flag
2457 * \return the next flag, or 0 if there are no more flags
2460 ped_partition_flag_next (PedPartitionFlag flag)
2462 return (flag + 1) % (PED_PARTITION_LAST_FLAG + 1);
2466 * Returns the flag associated with \p name.
2468 * \p name can be the English
2469 * string, or the translation for the native language.
2472 ped_partition_flag_get_by_name (const char* name)
2474 PedPartitionFlag flag;
2475 const char* flag_name;
2477 for (flag = ped_partition_flag_next (0); flag;
2478 flag = ped_partition_flag_next (flag)) {
2479 flag_name = ped_partition_flag_get_name (flag);
2480 if (strcasecmp (name, flag_name) == 0
2481 || strcasecmp (name, _(flag_name)) == 0)
2489 ped_partition_print (const PedPartition* part)
2491 PED_ASSERT (part != NULL);
2493 printf (" %-10s %02d (%d->%d)\n",
2494 ped_partition_type_get_name (part->type),
2496 (int) part->geom.start, (int) part->geom.end);
2502 * \addtogroup PedDisk
2508 * Prints a summary of disk's partitions. Useful for debugging.
2511 ped_disk_print (const PedDisk* disk)
2515 PED_ASSERT (disk != NULL);
2517 for (part = disk->part_list; part;
2518 part = ped_disk_next_partition (disk, part))
2519 ped_partition_print (part);