2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999-2003, 2005, 2007-2010 Free Software Foundation,
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 3 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
25 * \brief Disk label access.
27 * Most programs will need to use ped_disk_new() or ped_disk_new_fresh() to get
28 * anything done. A PedDisk is always associated with a device and has a
29 * partition table. There are different types of partition tables (or disk
30 * labels). These are represented by the PedDiskType enumeration.
37 #include <parted/parted.h>
38 #include <parted/debug.h>
41 #include "architecture.h"
42 #include "labels/pt-tools.h"
46 # define _(String) dgettext (PACKAGE, String)
47 # define N_(String) (String)
49 # define _(String) (String)
50 # define N_(String) (String)
51 #endif /* ENABLE_NLS */
53 /* UPDATE MODE functions */
55 static int _disk_check_sanity (PedDisk* disk);
57 static int _disk_push_update_mode (PedDisk* disk);
58 static int _disk_pop_update_mode (PedDisk* disk);
59 static int _disk_raw_insert_before (PedDisk* disk, PedPartition* loc,
61 static int _disk_raw_insert_after (PedDisk* disk, PedPartition* loc,
63 static int _disk_raw_remove (PedDisk* disk, PedPartition* part);
64 static int _disk_raw_add (PedDisk* disk, PedPartition* part);
66 static PedDiskType* disk_types = NULL;
69 ped_disk_type_register (PedDiskType* disk_type)
71 PED_ASSERT (disk_type != NULL, return);
72 PED_ASSERT (disk_type->ops != NULL, return);
73 PED_ASSERT (disk_type->name != NULL, return);
75 disk_type->next = disk_types;
76 disk_types = disk_type;
80 ped_disk_type_unregister (PedDiskType* disk_type)
83 PedDiskType* last = NULL;
85 PED_ASSERT (disk_types != NULL, return);
86 PED_ASSERT (disk_type != NULL, return);
88 for (walk = disk_types; walk && walk != disk_type;
89 last = walk, walk = walk->next);
91 PED_ASSERT (walk != NULL, return);
93 ((struct _PedDiskType*) last)->next = disk_type->next;
95 disk_types = disk_type->next;
99 * Return the next disk type registers, after "type". If "type" is
100 * NULL, returns the first disk type.
102 * \return Next disk; NULL if "type" is the last registered disk type.
105 ped_disk_type_get_next (PedDiskType const *type)
114 * Return the disk type with a name of "name".
116 * \return Disk type; NULL if no match.
119 ped_disk_type_get (const char* name)
121 PedDiskType* walk = NULL;
123 PED_ASSERT (name != NULL, return NULL);
125 for (walk = ped_disk_type_get_next (NULL); walk;
126 walk = ped_disk_type_get_next (walk))
127 if (strcasecmp (walk->name, name) == 0)
134 * Return the type of partition table detected on "dev".
136 * \return Type; NULL if none was detected.
139 ped_disk_probe (PedDevice* dev)
141 PedDiskType* walk = NULL;
143 PED_ASSERT (dev != NULL, return NULL);
145 if (!ped_device_open (dev))
148 ped_exception_fetch_all ();
149 for (walk = ped_disk_type_get_next (NULL); walk;
150 walk = ped_disk_type_get_next (walk))
152 if (getenv ("PARTED_DEBUG")) {
153 fprintf (stderr, "probe label: %s\n",
157 if (walk->ops->probe (dev))
162 ped_exception_catch ();
163 ped_exception_leave_all ();
165 ped_device_close (dev);
170 * Read the partition table off a device (if one is found).
172 * \warning May modify \p dev->cylinders, \p dev->heads and \p dev->sectors
173 * if the partition table indicates that the existing values
176 * \return A new \link _PedDisk PedDisk \endlink object;
177 * NULL on failure (e.g. partition table not detected).
180 ped_disk_new (PedDevice* dev)
185 PED_ASSERT (dev != NULL, return NULL);
187 if (!ped_device_open (dev))
190 type = ped_disk_probe (dev);
192 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
193 _("%s: unrecognised disk label"),
195 goto error_close_dev;
197 disk = ped_disk_new_fresh (dev, type);
199 goto error_close_dev;
200 if (!type->ops->read (disk))
201 goto error_destroy_disk;
202 disk->needs_clobber = 0;
203 ped_device_close (dev);
207 ped_disk_destroy (disk);
209 ped_device_close (dev);
215 _add_duplicate_part (PedDisk* disk, PedPartition* old_part)
217 PedPartition* new_part;
220 new_part = disk->type->ops->partition_duplicate (old_part);
223 new_part->disk = disk;
225 if (!_disk_push_update_mode (disk))
226 goto error_destroy_new_part;
227 ret = _disk_raw_add (disk, new_part);
228 if (!_disk_pop_update_mode (disk))
229 goto error_destroy_new_part;
231 goto error_destroy_new_part;
233 if (!_disk_check_sanity (disk))
234 goto error_destroy_new_part;
238 error_destroy_new_part:
239 ped_partition_destroy (new_part);
245 * Clone a \link _PedDisk PedDisk \endlink object.
247 * \return Deep copy of \p old_disk, NULL on failure.
250 ped_disk_duplicate (const PedDisk* old_disk)
253 PedPartition* old_part;
255 PED_ASSERT (old_disk != NULL, return NULL);
256 PED_ASSERT (!old_disk->update_mode, return NULL);
257 PED_ASSERT (old_disk->type->ops->duplicate != NULL, return NULL);
258 PED_ASSERT (old_disk->type->ops->partition_duplicate != NULL,
261 new_disk = old_disk->type->ops->duplicate (old_disk);
265 if (!_disk_push_update_mode (new_disk))
266 goto error_destroy_new_disk;
267 for (old_part = ped_disk_next_partition (old_disk, NULL); old_part;
268 old_part = ped_disk_next_partition (old_disk, old_part)) {
269 if (ped_partition_is_active (old_part)) {
270 if (!_add_duplicate_part (new_disk, old_part)){
271 _disk_pop_update_mode (new_disk);
272 goto error_destroy_new_disk;
276 if (!_disk_pop_update_mode (new_disk))
277 goto error_destroy_new_disk;
279 new_disk->needs_clobber = old_disk->needs_clobber;
283 error_destroy_new_disk:
284 ped_disk_destroy (new_disk);
289 /* Given a partition table type NAME, e.g., "gpt", return its PedDiskType
290 handle. If no known type has a name matching NAME, return NULL. */
291 static PedDiskType const *
292 find_disk_type (char const *name)
294 PedDiskType const *t;
295 for (t = ped_disk_type_get_next (NULL); t; t = ped_disk_type_get_next (t))
297 if (strcmp (t->name, name) == 0)
304 * Remove all identifying signatures of a partition table,
306 * \return 0 on error, 1 otherwise.
308 * \sa ped_disk_clobber()
311 ped_disk_clobber (PedDevice* dev)
313 PED_ASSERT (dev != NULL, goto error);
315 if (!ped_device_open (dev))
318 PedDiskType const *gpt = find_disk_type ("gpt");
319 PED_ASSERT (gpt != NULL, goto error);
321 /* If there is a GPT table, don't clobber the protective MBR. */
322 bool is_gpt = gpt->ops->probe (dev);
323 PedSector first_sector = (is_gpt ? 1 : 0);
325 /* How many sectors to zero out at each end.
326 This must be large enough to zero out the magic bytes
327 starting at offset 8KiB on a DASD partition table.
328 Doing the same from the end of the disk is probably
329 overkill, but at least on GPT, we do need to zero out
331 const PedSector n_sectors = 9 * 1024 / dev->sector_size + 1;
333 /* Clear the first few. */
334 PedSector n = n_sectors;
335 if (dev->length < first_sector + n_sectors)
336 n = dev->length - first_sector;
337 if (!ptt_clear_sectors (dev, first_sector, n))
338 goto error_close_dev;
340 /* Clear the last few. */
341 PedSector t = (dev->length -
342 (n_sectors < dev->length ? n_sectors : 1));
344 /* Don't clobber the pMBR if we have a pathologically small disk. */
345 if (t < first_sector)
347 if (!ptt_clear_sectors (dev, t, dev->length - t))
348 goto error_close_dev;
350 ped_device_close (dev);
354 ped_device_close (dev);
360 * Create a new partition table on \p dev.
362 * This new partition table is only created in-memory, and nothing is written
363 * to disk until ped_disk_commit_to_dev() is called.
365 * \return The newly constructed \link _PedDisk PedDisk \endlink,
369 ped_disk_new_fresh (PedDevice* dev, const PedDiskType* type)
373 PED_ASSERT (dev != NULL, return NULL);
374 PED_ASSERT (type != NULL, return NULL);
375 PED_ASSERT (type->ops->alloc != NULL, return NULL);
376 PedCHSGeometry* bios_geom = &dev->bios_geom;
377 PED_ASSERT (bios_geom->sectors != 0, return NULL);
378 PED_ASSERT (bios_geom->heads != 0, return NULL);
380 disk = type->ops->alloc (dev);
383 if (!_disk_pop_update_mode (disk))
384 goto error_destroy_disk;
385 PED_ASSERT (disk->update_mode == 0, ignored);
387 disk->needs_clobber = 1;
391 ped_disk_destroy (disk);
397 _ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type)
401 disk = (PedDisk*) ped_malloc (sizeof (PedDisk));
405 disk->dev = (PedDevice*)dev;
406 disk->type = disk_type;
407 disk->update_mode = 1;
408 disk->part_list = NULL;
416 _ped_disk_free (PedDisk* disk)
418 _disk_push_update_mode (disk);
419 ped_disk_delete_all (disk);
426 * What this function does depends on the PedDiskType of \p disk,
427 * but you can generally assume that outstanding writes are flushed
428 * (this mainly means that _ped_disk_free is called).
431 ped_disk_destroy (PedDisk* disk)
433 PED_ASSERT (disk != NULL, return);
434 PED_ASSERT (!disk->update_mode, return);
436 disk->type->ops->free (disk);
440 * Tell the operating system kernel about the partition table layout
443 * This is rather loosely defined: for example, on old versions of Linux,
444 * it simply calls the BLKRRPART ioctl, which tells the kernel to
445 * reread the partition table. On newer versions (2.4.x), it will
446 * use the new blkpg interface to tell Linux where each partition
447 * starts/ends, etc. In this case, Linux does not need to have support for
448 * a specific type of partition table.
450 * \return 0 on failure, 1 otherwise.
453 ped_disk_commit_to_os (PedDisk* disk)
455 PED_ASSERT (disk != NULL, return 0);
457 if (!ped_device_open (disk->dev))
459 if (!ped_architecture->disk_ops->disk_commit (disk))
460 goto error_close_dev;
461 ped_device_close (disk->dev);
465 ped_device_close (disk->dev);
471 * Write the changes made to the in-memory description
472 * of a partition table to the device.
474 * \return 0 on failure, 1 otherwise.
477 ped_disk_commit_to_dev (PedDisk* disk)
479 PED_ASSERT (disk != NULL, goto error);
480 PED_ASSERT (!disk->update_mode, goto error);
482 if (!disk->type->ops->write) {
483 ped_exception_throw (
485 PED_EXCEPTION_CANCEL,
486 _("This libparted doesn't have write support for "
487 "%s. Perhaps it was compiled read-only."),
492 if (!ped_device_open (disk->dev))
495 if (disk->needs_clobber) {
496 if (!ped_disk_clobber (disk->dev))
497 goto error_close_dev;
498 disk->needs_clobber = 0;
500 if (!disk->type->ops->write (disk))
501 goto error_close_dev;
502 ped_device_close (disk->dev);
506 ped_device_close (disk->dev);
512 * This function writes the in-memory changes to a partition table to
513 * disk and informs the operating system of the changes.
515 * \note Equivalent to calling first ped_disk_commit_to_dev(), then
516 * ped_disk_commit_to_os().
518 * \return 0 on failure, 1 otherwise.
521 ped_disk_commit (PedDisk* disk)
523 /* Open the device here, so that the underlying fd is not closed
524 between commit_to_dev and commit_to_os (closing causes unwanted
525 udev events to be sent under Linux). */
526 if (!ped_device_open (disk->dev))
529 if (!ped_disk_commit_to_dev (disk))
530 goto error_close_dev;
532 if (!ped_disk_commit_to_os (disk))
533 goto error_close_dev;
535 ped_device_close (disk->dev);
539 ped_device_close (disk->dev);
545 * \addtogroup PedPartition
551 * Check whether a partition is mounted or busy in some
554 * \note An extended partition is busy if any logical partitions are mounted.
556 * \return \c 1 if busy.
559 ped_partition_is_busy (const PedPartition* part)
561 PED_ASSERT (part != NULL, return 1);
563 return ped_architecture->disk_ops->partition_is_busy (part);
567 * Return a path that can be used to address the partition in the
571 ped_partition_get_path (const PedPartition* part)
573 PED_ASSERT (part != NULL, return NULL);
575 return ped_architecture->disk_ops->partition_get_path (part);
581 * \addtogroup PedDisk
587 * Perform a sanity check on a partition table.
589 * \note The check performed is generic (i.e. it does not depends on the label
592 * \throws PED_EXCEPTION_WARNING if a partition type ID does not match the file
595 * \return 0 if the check fails, 1 otherwise.
598 ped_disk_check (const PedDisk* disk)
602 PED_ASSERT (disk != NULL, return 0);
604 for (walk = disk->part_list; walk;
605 walk = ped_disk_next_partition (disk, walk)) {
606 const PedFileSystemType* fs_type = walk->fs_type;
608 PedSector length_error;
609 PedSector max_length_error;
611 if (!ped_partition_is_active (walk) || !fs_type)
614 geom = ped_file_system_probe_specific (fs_type, &walk->geom);
618 length_error = abs (walk->geom.length - geom->length);
619 max_length_error = PED_MAX (4096, walk->geom.length / 100);
620 bool ok = (ped_geometry_test_inside (&walk->geom, geom)
621 && length_error <= max_length_error);
622 char *fs_size = ped_unit_format (disk->dev, geom->length);
623 ped_geometry_destroy (geom);
625 char* part_size = ped_unit_format (disk->dev,
627 PedExceptionOption choice;
628 choice = ped_exception_throw (
629 PED_EXCEPTION_WARNING,
630 PED_EXCEPTION_IGNORE_CANCEL,
631 _("Partition %d is %s, but the file system is "
633 walk->num, part_size, fs_size);
640 if (choice != PED_EXCEPTION_IGNORE)
650 * This function checks if a particular type of partition table supports
653 * \return 1 if \p disk_type supports \p feature, 0 otherwise.
656 ped_disk_type_check_feature (const PedDiskType* disk_type,
657 PedDiskTypeFeature feature)
659 return (disk_type->features & feature) != 0;
663 * Get the number of primary partitions.
666 ped_disk_get_primary_partition_count (const PedDisk* disk)
671 PED_ASSERT (disk != NULL, return 0);
673 for (walk = disk->part_list; walk;
674 walk = ped_disk_next_partition (disk, walk)) {
675 if (ped_partition_is_active (walk)
676 && ! (walk->type & PED_PARTITION_LOGICAL))
684 * Get the highest available partition number on \p disk.
687 ped_disk_get_last_partition_num (const PedDisk* disk)
692 PED_ASSERT (disk != NULL, return 0);
694 for (walk = disk->part_list; walk;
695 walk = ped_disk_next_partition (disk, walk)) {
696 if (walk->num > highest)
704 * Get the highest supported partition number on \p disk.
706 * \return 0 if call fails. 1 otherwise.
709 ped_disk_get_max_supported_partition_count(const PedDisk* disk, int* supported)
711 PED_ASSERT(disk != NULL, return -1);
712 PED_ASSERT(disk->type->ops->get_max_supported_partition_count != NULL, return -1);
714 return disk->type->ops->get_max_supported_partition_count(disk, supported);
718 * Get the alignment needed for partition boundaries on this disk.
719 * The returned alignment describes the alignment for the start sector of the
720 * partition, for all disklabel types which require alignment, except Sun
721 * disklabels, the end sector must be aligned too. To get the end sector
722 * alignment decrease the PedAlignment offset by 1.
724 * \return NULL on error, otherwise a pointer to a dynamically allocated
728 ped_disk_get_partition_alignment(const PedDisk *disk)
730 /* disklabel handlers which don't need alignment don't define this */
731 if (!disk->type->ops->get_partition_alignment)
732 return ped_alignment_duplicate(ped_alignment_any);
734 return disk->type->ops->get_partition_alignment(disk);
738 * Get the maximum number of (primary) partitions the disk label supports.
740 * For example, MacIntosh partition maps can have different sizes,
741 * and accordingly support a different number of partitions.
744 ped_disk_get_max_primary_partition_count (const PedDisk* disk)
746 PED_ASSERT (disk->type != NULL, return 0);
747 PED_ASSERT (disk->type->ops->get_max_primary_partition_count != NULL,
750 return disk->type->ops->get_max_primary_partition_count (disk);
754 * Set the state (\c 1 or \c 0) of a flag on a disk.
756 * \note It is an error to call this on an unavailable flag -- use
757 * ped_disk_is_flag_available() to determine which flags are available
758 * for a given disk label.
760 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
764 ped_disk_set_flag(PedDisk *disk, PedDiskFlag flag, int state)
768 PED_ASSERT (disk != NULL, return 0);
770 PedDiskOps *ops = disk->type->ops;
772 if (!_disk_push_update_mode(disk))
775 if (!ped_disk_is_flag_available(disk, flag)) {
776 ped_exception_throw (
778 PED_EXCEPTION_CANCEL,
779 "The flag '%s' is not available for %s disk labels.",
780 ped_disk_flag_get_name(flag),
782 _disk_pop_update_mode(disk);
786 ret = ops->disk_set_flag(disk, flag, state);
788 if (!_disk_pop_update_mode (disk))
795 * Get the state (\c 1 or \c 0) of a flag on a disk.
798 ped_disk_get_flag(const PedDisk *disk, PedDiskFlag flag)
800 PED_ASSERT (disk != NULL, return 0);
802 PedDiskOps *ops = disk->type->ops;
804 if (!ped_disk_is_flag_available(disk, flag))
807 return ops->disk_get_flag(disk, flag);
811 * Check whether a given flag is available on a disk.
813 * \return \c 1 if the flag is available.
816 ped_disk_is_flag_available(const PedDisk *disk, PedDiskFlag flag)
818 PED_ASSERT (disk != NULL, return 0);
820 PedDiskOps *ops = disk->type->ops;
822 if (!ops->disk_is_flag_available)
825 return ops->disk_is_flag_available(disk, flag);
829 * Returns a name for a \p flag, e.g. PED_DISK_CYLINDER_ALIGNMENT will return
830 * "cylinder_alignment".
832 * \note The returned string will be in English. However,
833 * translations are provided, so the caller can call
834 * dgettext("parted", RESULT) on the result.
837 ped_disk_flag_get_name(PedDiskFlag flag)
840 case PED_DISK_CYLINDER_ALIGNMENT:
841 return N_("cylinder_alignment");
844 ped_exception_throw (
846 PED_EXCEPTION_CANCEL,
847 _("Unknown disk flag, %d."),
854 * Returns the flag associated with \p name.
856 * \p name can be the English
857 * string, or the translation for the native language.
860 ped_disk_flag_get_by_name(const char *name)
864 for (flag = ped_disk_flag_next(0); flag;
865 flag = ped_disk_flag_next(flag)) {
866 const char *flag_name = ped_disk_flag_get_name(flag);
867 if (strcasecmp(name, flag_name) == 0
868 || strcasecmp(name, _(flag_name)) == 0)
876 * Iterates through all disk flags.
878 * ped_disk_flag_next(0) returns the first flag
880 * \return the next flag, or 0 if there are no more flags
883 ped_disk_flag_next(PedDiskFlag flag)
885 return (flag + 1) % (PED_DISK_LAST_FLAG + 1);
889 * \internal We turned a really nasty bureaucracy problem into an elegant maths
890 * problem :-) Basically, there are some constraints to a partition's
893 * (1) it must start and end on a "disk" block, determined by the disk label
894 * (not the hardware). (constraint represented by a PedAlignment)
896 * (2) if we're resizing a partition, we MIGHT need to keep each block aligned.
897 * Eg: if an ext2 file system has 4k blocks, then we can only move the start
898 * by a multiple of 4k. (constraint represented by a PedAlignment)
900 * (3) we need to keep the start and end within the device's physical
901 * boundaries. (constraint represented by a PedGeometry)
903 * Satisfying (1) and (2) simultaneously required a bit of fancy maths ;-) See
904 * ped_alignment_intersect()
906 * The application of these constraints is in disk_*.c's *_partition_align()
910 _partition_align (PedPartition* part, const PedConstraint* constraint)
912 const PedDiskType* disk_type;
914 PED_ASSERT (part != NULL, return 0);
915 PED_ASSERT (part->num != -1, return 0);
916 PED_ASSERT (part->disk != NULL, return 0);
917 disk_type = part->disk->type;
918 PED_ASSERT (disk_type != NULL, return 0);
919 PED_ASSERT (disk_type->ops->partition_align != NULL, return 0);
920 PED_ASSERT (part->disk->update_mode, return 0);
922 return disk_type->ops->partition_align (part, constraint);
926 _partition_enumerate (PedPartition* part)
928 const PedDiskType* disk_type;
930 PED_ASSERT (part != NULL, return 0);
931 PED_ASSERT (part->disk != NULL, return 0);
932 disk_type = part->disk->type;
933 PED_ASSERT (disk_type != NULL, return 0);
934 PED_ASSERT (disk_type->ops->partition_enumerate != NULL, return 0);
936 return disk_type->ops->partition_enumerate (part);
940 * Gives all the (active) partitions a number. It should preserve the numbers
941 * and orders as much as possible.
944 ped_disk_enumerate_partitions (PedDisk* disk)
950 PED_ASSERT (disk != NULL, return 0);
952 /* first "sort" already-numbered partitions. (e.g. if a logical partition
953 * is removed, then all logical partitions that were number higher MUST be
956 end = ped_disk_get_last_partition_num (disk);
957 for (i=1; i<=end; i++) {
958 walk = ped_disk_get_partition (disk, i);
960 if (!_partition_enumerate (walk))
965 /* now, number un-numbered partitions */
966 for (walk = disk->part_list; walk;
967 walk = ped_disk_next_partition (disk, walk)) {
968 if (ped_partition_is_active (walk) && walk->num == -1) {
969 if (!_partition_enumerate (walk))
978 _disk_remove_metadata (PedDisk* disk)
980 PedPartition* walk = NULL;
983 PED_ASSERT (disk != NULL, return 0);
985 next = ped_disk_next_partition (disk, walk);
990 next = ped_disk_next_partition (disk, next);
991 if (!next || next->type & PED_PARTITION_METADATA)
994 if (walk->type & PED_PARTITION_METADATA)
995 ped_disk_delete_partition (disk, walk);
1001 _disk_alloc_metadata (PedDisk* disk)
1003 PED_ASSERT (disk != NULL, return 0);
1005 if (!disk->update_mode)
1006 _disk_remove_metadata (disk);
1008 return disk->type->ops->alloc_metadata (disk);
1012 _disk_remove_freespace (PedDisk* disk)
1017 walk = ped_disk_next_partition (disk, NULL);
1018 for (; walk; walk = next) {
1019 next = ped_disk_next_partition (disk, walk);
1021 if (walk->type & PED_PARTITION_FREESPACE) {
1022 _disk_raw_remove (disk, walk);
1023 ped_partition_destroy (walk);
1031 _alloc_extended_freespace (PedDisk* disk)
1036 PedPartition* free_space;
1037 PedPartition* extended_part;
1039 extended_part = ped_disk_extended_partition (disk);
1043 last_end = extended_part->geom.start;
1046 for (walk = extended_part->part_list; walk; walk = walk->next) {
1047 if (walk->geom.start > last_end + 1) {
1048 free_space = ped_partition_new (
1050 PED_PARTITION_FREESPACE
1051 | PED_PARTITION_LOGICAL,
1053 last_end + 1, walk->geom.start - 1);
1054 _disk_raw_insert_before (disk, walk, free_space);
1058 last_end = last->geom.end;
1061 if (last_end < extended_part->geom.end) {
1062 free_space = ped_partition_new (
1064 PED_PARTITION_FREESPACE | PED_PARTITION_LOGICAL,
1066 last_end + 1, extended_part->geom.end);
1069 return _disk_raw_insert_after (disk, last, free_space);
1071 extended_part->part_list = free_space;
1078 _disk_alloc_freespace (PedDisk* disk)
1083 PedPartition* free_space;
1085 if (!_disk_remove_freespace (disk))
1087 if (!_alloc_extended_freespace (disk))
1093 for (walk = disk->part_list; walk; walk = walk->next) {
1094 if (walk->geom.start > last_end + 1) {
1095 free_space = ped_partition_new (disk,
1096 PED_PARTITION_FREESPACE, NULL,
1097 last_end + 1, walk->geom.start - 1);
1098 _disk_raw_insert_before (disk, walk, free_space);
1102 last_end = last->geom.end;
1105 if (last_end < disk->dev->length - 1) {
1106 free_space = ped_partition_new (disk,
1107 PED_PARTITION_FREESPACE, NULL,
1108 last_end + 1, disk->dev->length - 1);
1110 return _disk_raw_insert_after (disk, last, free_space);
1112 disk->part_list = free_space;
1119 * Update mode: used when updating the internal representation of the partition
1120 * table. In update mode, the metadata and freespace placeholder/virtual
1121 * partitions are removed, making it much easier for various manipulation
1125 _disk_push_update_mode (PedDisk* disk)
1127 if (!disk->update_mode) {
1129 if (!_disk_check_sanity (disk))
1133 _disk_remove_freespace (disk);
1134 disk->update_mode++;
1135 _disk_remove_metadata (disk);
1138 if (!_disk_check_sanity (disk))
1142 disk->update_mode++;
1148 _disk_pop_update_mode (PedDisk* disk)
1150 PED_ASSERT (disk->update_mode, return 0);
1152 if (disk->update_mode == 1) {
1153 /* re-allocate metadata BEFORE leaving update mode, to prevent infinite
1154 * recursion (metadata allocation requires update mode)
1157 if (!_disk_check_sanity (disk))
1161 _disk_alloc_metadata (disk);
1162 disk->update_mode--;
1163 _disk_alloc_freespace (disk);
1166 if (!_disk_check_sanity (disk))
1170 disk->update_mode--;
1178 * \addtogroup PedPartition
1180 * \brief Partition access.
1186 _ped_partition_alloc (const PedDisk* disk, PedPartitionType type,
1187 const PedFileSystemType* fs_type,
1188 PedSector start, PedSector end)
1192 PED_ASSERT (disk != NULL, return 0);
1194 part = (PedPartition*) ped_malloc (sizeof (PedPartition));
1201 part->disk = (PedDisk*) disk;
1202 if (!ped_geometry_init (&part->geom, disk->dev, start, end - start + 1))
1203 goto error_free_part;
1207 part->part_list = NULL;
1208 part->fs_type = fs_type;
1219 _ped_partition_free (PedPartition* part)
1225 _ped_partition_attempt_align (PedPartition* part,
1226 const PedConstraint* external,
1227 PedConstraint* internal)
1229 PedConstraint* intersection;
1230 PedGeometry* solution;
1232 intersection = ped_constraint_intersect (external, internal);
1233 ped_constraint_destroy (internal);
1237 solution = ped_constraint_solve_nearest (intersection, &part->geom);
1239 goto fail_free_intersection;
1240 ped_geometry_set (&part->geom, solution->start, solution->length);
1241 ped_geometry_destroy (solution);
1242 ped_constraint_destroy (intersection);
1245 fail_free_intersection:
1246 ped_constraint_destroy (intersection);
1252 * Create a new \link _PedPartition PedPartition \endlink on \p disk.
1254 * \param type One of \p PED_PARTITION_NORMAL, \p PED_PARTITION_EXTENDED,
1255 * \p PED_PARTITION_LOGICAL.
1257 * \note The constructed partition is not added to <tt>disk</tt>'s
1258 * partition table. Use ped_disk_add_partition() to do this.
1260 * \return A new \link _PedPartition PedPartition \endlink object,
1263 * \throws PED_EXCEPTION_ERROR if \p type is \p EXTENDED or \p LOGICAL but the
1264 * label does not support this concept.
1267 ped_partition_new (const PedDisk* disk, PedPartitionType type,
1268 const PedFileSystemType* fs_type, PedSector start,
1271 int supports_extended;
1274 PED_ASSERT (disk != NULL, return NULL);
1275 PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL);
1277 supports_extended = ped_disk_type_check_feature (disk->type,
1278 PED_DISK_TYPE_EXTENDED);
1280 if (!supports_extended
1281 && (type == PED_PARTITION_EXTENDED
1282 || type == PED_PARTITION_LOGICAL)) {
1283 ped_exception_throw (
1284 PED_EXCEPTION_ERROR,
1285 PED_EXCEPTION_CANCEL,
1286 _("%s disk labels do not support extended "
1292 part = disk->type->ops->partition_new (disk, type, fs_type, start, end);
1296 if (fs_type || part->type == PED_PARTITION_EXTENDED) {
1297 if (!ped_partition_set_system (part, fs_type))
1298 goto error_destroy_part;
1303 ped_partition_destroy (part);
1309 * Destroy a \link _PedPartition PedPartition \endlink object.
1311 * \note Should not be called on a partition that is in a partition table.
1312 * Use ped_disk_delete_partition() instead.
1315 ped_partition_destroy (PedPartition* part)
1317 PED_ASSERT (part != NULL, return);
1318 PED_ASSERT (part->disk != NULL, return);
1319 PED_ASSERT (part->disk->type->ops->partition_new != NULL, return);
1321 part->disk->type->ops->partition_destroy (part);
1326 * Return whether or not the partition is "active".
1328 * A partition is active if \p part->type is neither \p PED_PARTITION_METADATA
1329 * nor \p PED_PARTITION_FREE.
1332 ped_partition_is_active (const PedPartition* part)
1334 PED_ASSERT (part != NULL, return 0);
1336 return !(part->type & PED_PARTITION_FREESPACE
1337 || part->type & PED_PARTITION_METADATA);
1341 * Set the state (\c 1 or \c 0) of a flag on a partition.
1343 * Flags are disk label specific, although they have a global
1344 * "namespace": the flag PED_PARTITION_BOOT, for example, roughly means
1345 * "this" partition is bootable". But this means different things on different
1346 * disk labels (and may not be defined on some disk labels). For example,
1347 * on MS-DOS disk labels, there can only be one boot partition, and this
1348 * refers to the partition that will be booted from on startup. On PC98
1349 * disk labels, the user can choose from any bootable partition on startup.
1351 * \note It is an error to call this on an unavailable flag -- use
1352 * ped_partition_is_flag_available() to determine which flags are available
1353 * for a given disk label.
1355 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
1359 ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1363 PED_ASSERT (part != NULL, return 0);
1364 PED_ASSERT (part->disk != NULL, return 0);
1365 PED_ASSERT (ped_partition_is_active (part), return 0);
1367 ops = part->disk->type->ops;
1368 PED_ASSERT (ops->partition_set_flag != NULL, return 0);
1369 PED_ASSERT (ops->partition_is_flag_available != NULL, return 0);
1371 if (!ops->partition_is_flag_available (part, flag)) {
1372 ped_exception_throw (
1373 PED_EXCEPTION_ERROR,
1374 PED_EXCEPTION_CANCEL,
1375 "The flag '%s' is not available for %s disk labels.",
1376 ped_partition_flag_get_name (flag),
1377 part->disk->type->name);
1381 return ops->partition_set_flag (part, flag, state);
1385 * Get the state (\c 1 or \c 0) of a flag on a partition.
1387 * See ped_partition_set_flag() for conditions that must hold.
1389 * \todo Where's the check for flag availability?
1392 ped_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1394 PED_ASSERT (part != NULL, return 0);
1395 PED_ASSERT (part->disk != NULL, return 0);
1396 PED_ASSERT (part->disk->type->ops->partition_get_flag != NULL,
1398 PED_ASSERT (ped_partition_is_active (part), return 0);
1400 return part->disk->type->ops->partition_get_flag (part, flag);
1404 * Check whether a given flag is available on a partition.
1406 * \return \c 1 if the flag is available.
1409 ped_partition_is_flag_available (const PedPartition* part,
1410 PedPartitionFlag flag)
1412 PED_ASSERT (part != NULL, return 0);
1413 PED_ASSERT (part->disk != NULL, return 0);
1414 PED_ASSERT (part->disk->type->ops->partition_is_flag_available != NULL,
1416 PED_ASSERT (ped_partition_is_active (part), return 0);
1418 return part->disk->type->ops->partition_is_flag_available (part, flag);
1422 * Sets the system type on the partition to \p fs_type.
1424 * \note The file system may be opened, to get more information about the
1425 * file system, e.g. to determine if it's FAT16 or FAT32.
1427 * \return \c 0 on failure.
1430 ped_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1432 const PedDiskType* disk_type;
1434 PED_ASSERT (part != NULL, return 0);
1435 PED_ASSERT (ped_partition_is_active (part), return 0);
1436 PED_ASSERT (part->disk != NULL, return 0);
1437 disk_type = part->disk->type;
1438 PED_ASSERT (disk_type != NULL, return 0);
1439 PED_ASSERT (disk_type->ops != NULL, return 0);
1440 PED_ASSERT (disk_type->ops->partition_set_system != NULL, return 0);
1442 return disk_type->ops->partition_set_system (part, fs_type);
1446 _assert_partition_name_feature (const PedDiskType* disk_type)
1448 if (!ped_disk_type_check_feature (
1449 disk_type, PED_DISK_TYPE_PARTITION_NAME)) {
1450 ped_exception_throw (
1451 PED_EXCEPTION_ERROR,
1452 PED_EXCEPTION_CANCEL,
1453 "%s disk labels do not support partition names.",
1461 * Sets the name of a partition.
1463 * \note This will only work if the disk label supports it.
1466 * ped_disk_type_check_feature (part->disk->type, PED_DISK_TYPE_PARTITION_NAME);
1468 * to check whether this feature is enabled for a label.
1470 * \note \p name will not be modified by libparted. It can be freed
1471 * by the caller immediately after ped_partition_set_name() is called.
1473 * \return \c 1 on success, \c 0 otherwise.
1476 ped_partition_set_name (PedPartition* part, const char* name)
1478 PED_ASSERT (part != NULL, return 0);
1479 PED_ASSERT (part->disk != NULL, return 0);
1480 PED_ASSERT (ped_partition_is_active (part), return 0);
1481 PED_ASSERT (name != NULL, return 0);
1483 if (!_assert_partition_name_feature (part->disk->type))
1486 PED_ASSERT (part->disk->type->ops->partition_set_name != NULL,
1488 part->disk->type->ops->partition_set_name (part, name);
1493 * Returns the name of a partition \p part. This will only work if the disk
1494 * label supports it.
1496 * \note The returned string should not be modified. It should
1497 * not be referenced after the partition is destroyed.
1500 ped_partition_get_name (const PedPartition* part)
1502 PED_ASSERT (part != NULL, return NULL);
1503 PED_ASSERT (part->disk != NULL, return 0);
1504 PED_ASSERT (ped_partition_is_active (part), return 0);
1506 if (!_assert_partition_name_feature (part->disk->type))
1509 PED_ASSERT (part->disk->type->ops->partition_get_name != NULL,
1511 return part->disk->type->ops->partition_get_name (part);
1517 * \addtogroup PedDisk
1523 ped_disk_extended_partition (const PedDisk* disk)
1527 PED_ASSERT (disk != NULL, return 0);
1529 for (walk = disk->part_list; walk; walk = walk->next) {
1530 if (walk->type == PED_PARTITION_EXTENDED)
1537 * Return the next partition after \p part on \p disk. If \p part is \c NULL,
1538 * return the first partition. If \p part is the last partition, returns
1539 * \c NULL. If \p part is an extended partition, returns the first logical
1540 * partition. If this is called repeatedly passing the return value as \p part,
1541 * a depth-first traversal is executed.
1543 * \return The next partition, \c NULL if no more partitions left.
1546 ped_disk_next_partition (const PedDisk* disk, const PedPartition* part)
1548 PED_ASSERT (disk != NULL, return 0);
1551 return disk->part_list;
1552 if (part->type == PED_PARTITION_EXTENDED)
1553 return part->part_list ? part->part_list : part->next;
1556 if (part->type & PED_PARTITION_LOGICAL)
1557 return ped_disk_extended_partition (disk)->next;
1565 _disk_check_sanity (PedDisk* disk)
1569 PED_ASSERT (disk != NULL, return 0);
1571 for (walk = disk->part_list; walk; walk = walk->next) {
1572 PED_ASSERT (!(walk->type & PED_PARTITION_LOGICAL), return 0);
1573 PED_ASSERT (!walk->prev || walk->prev->next == walk, return 0);
1576 if (!ped_disk_extended_partition (disk))
1579 for (walk = ped_disk_extended_partition (disk)->part_list; walk;
1580 walk = walk->next) {
1581 PED_ASSERT (walk->type & PED_PARTITION_LOGICAL, return 0);
1583 PED_ASSERT (walk->prev->next == walk, return 0);
1590 * Returns the partition numbered \p num.
1592 * \return \c NULL if the specified partition does not exist.
1595 ped_disk_get_partition (const PedDisk* disk, int num)
1599 PED_ASSERT (disk != NULL, return 0);
1601 for (walk = disk->part_list; walk;
1602 walk = ped_disk_next_partition (disk, walk)) {
1603 if (walk->num == num && !(walk->type & PED_PARTITION_FREESPACE))
1611 * Returns the partition that contains sect. If sect lies within a logical
1612 * partition, then the logical partition is returned (not the extended
1616 ped_disk_get_partition_by_sector (const PedDisk* disk, PedSector sect)
1620 PED_ASSERT (disk != NULL, return 0);
1622 for (walk = disk->part_list; walk;
1623 walk = ped_disk_next_partition (disk, walk)) {
1624 if (ped_geometry_test_sector_inside (&walk->geom, sect)
1625 && walk->type != PED_PARTITION_EXTENDED)
1629 /* should never get here, unless sect is outside of disk's useable
1630 * part, or we're in "update mode", and the free space place-holders
1631 * have been removed with _disk_remove_freespace()
1637 * Return the maximum representable length (in sectors) of a
1638 * partition on disk \disk.
1641 ped_disk_max_partition_length (const PedDisk* disk)
1643 return disk->type->ops->max_length ();
1647 * Return the maximum representable start sector of a
1648 * partition on disk \disk.
1651 ped_disk_max_partition_start_sector (const PedDisk* disk)
1653 return disk->type->ops->max_start_sector ();
1656 /* I'm beginning to agree with Sedgewick :-/ */
1658 _disk_raw_insert_before (PedDisk* disk, PedPartition* loc, PedPartition* part)
1660 PED_ASSERT (disk != NULL, return 0);
1661 PED_ASSERT (loc != NULL, return 0);
1662 PED_ASSERT (part != NULL, return 0);
1664 part->prev = loc->prev;
1667 part->prev->next = part;
1669 if (loc->type & PED_PARTITION_LOGICAL)
1670 ped_disk_extended_partition (disk)->part_list = part;
1672 disk->part_list = part;
1680 _disk_raw_insert_after (PedDisk* disk, PedPartition* loc, PedPartition* part)
1682 PED_ASSERT (disk != NULL, return 0);
1683 PED_ASSERT (loc != NULL, return 0);
1684 PED_ASSERT (part != NULL, return 0);
1687 part->next = loc->next;
1689 loc->next->prev = part;
1696 _disk_raw_remove (PedDisk* disk, PedPartition* part)
1698 PED_ASSERT (disk != NULL, return 0);
1699 PED_ASSERT (part != NULL, return 0);
1702 part->prev->next = part->next;
1704 part->next->prev = part->prev;
1706 if (part->type & PED_PARTITION_LOGICAL) {
1707 ped_disk_extended_partition (disk)->part_list
1710 disk->part_list = part->next;
1713 part->next->prev = NULL;
1723 _disk_raw_add (PedDisk* disk, PedPartition* part)
1727 PedPartition* ext_part;
1729 PED_ASSERT (disk->update_mode, return 0);
1731 ext_part = ped_disk_extended_partition (disk);
1734 walk = (part->type & PED_PARTITION_LOGICAL) ?
1735 ext_part->part_list : disk->part_list;
1737 for (; walk; last = walk, walk = walk->next) {
1738 if (walk->geom.start > part->geom.end)
1743 return _disk_raw_insert_before (disk, walk, part);
1746 return _disk_raw_insert_after (disk, last, part);
1748 if (part->type & PED_PARTITION_LOGICAL)
1749 ext_part->part_list = part;
1751 disk->part_list = part;
1758 static PedConstraint*
1759 _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
1761 PedSector min_start;
1764 PedGeometry free_space;
1766 PED_ASSERT (part->disk->update_mode, return NULL);
1767 PED_ASSERT (part->geom.dev == geom->dev, return NULL);
1769 if (part->type & PED_PARTITION_LOGICAL) {
1770 PedPartition* ext_part;
1772 ext_part = ped_disk_extended_partition (part->disk);
1773 PED_ASSERT (ext_part != NULL, return NULL);
1775 min_start = ext_part->geom.start;
1776 max_end = ext_part->geom.end;
1777 walk = ext_part->part_list;
1780 max_end = part->disk->dev->length - 1;
1781 walk = part->disk->part_list;
1785 && (walk->geom.start < geom->start
1786 || min_start >= walk->geom.start)) {
1788 min_start = walk->geom.end + 1;
1796 max_end = walk->geom.start - 1;
1798 if (min_start >= max_end)
1801 ped_geometry_init (&free_space, part->disk->dev,
1802 min_start, max_end - min_start + 1);
1803 return ped_constraint_new_from_max (&free_space);
1807 * Returns \c 0 if the partition, \p part overlaps with any partitions on the
1808 * \p disk. The geometry of \p part is taken to be \p geom, NOT \p part->geom
1809 * (the idea here is to check if \p geom is valid, before changing \p part).
1811 * This is useful for seeing if a resized partitions new geometry is going to
1812 * fit, without the existing geomtry getting in the way.
1814 * Note: overlap with an extended partition is also allowed, provided that
1815 * \p geom lies completely inside the extended partition.
1818 _disk_check_part_overlaps (PedDisk* disk, PedPartition* part)
1822 PED_ASSERT (disk != NULL, return 0);
1823 PED_ASSERT (part != NULL, return 0);
1825 for (walk = ped_disk_next_partition (disk, NULL); walk;
1826 walk = ped_disk_next_partition (disk, walk)) {
1827 if (walk->type & PED_PARTITION_FREESPACE)
1831 if (part->type & PED_PARTITION_EXTENDED
1832 && walk->type & PED_PARTITION_LOGICAL)
1835 if (ped_geometry_test_overlap (&walk->geom, &part->geom)) {
1836 if (walk->type & PED_PARTITION_EXTENDED
1837 && part->type & PED_PARTITION_LOGICAL
1838 && ped_geometry_test_inside (&walk->geom,
1849 _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
1851 PedPartition* ext_part = ped_disk_extended_partition (disk);
1853 PED_ASSERT (part->disk == disk, return 0);
1855 PED_ASSERT (part->geom.start >= 0, return 0);
1856 PED_ASSERT (part->geom.end < disk->dev->length, return 0);
1857 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1859 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
1860 && (part->type == PED_PARTITION_EXTENDED
1861 || part->type == PED_PARTITION_LOGICAL)) {
1862 ped_exception_throw (
1863 PED_EXCEPTION_ERROR,
1864 PED_EXCEPTION_CANCEL,
1865 _("%s disk labels don't support logical or extended "
1871 if (ped_partition_is_active (part)
1872 && ! (part->type & PED_PARTITION_LOGICAL)) {
1873 if (ped_disk_get_primary_partition_count (disk) + 1
1874 > ped_disk_get_max_primary_partition_count (disk)) {
1875 ped_exception_throw (
1876 PED_EXCEPTION_ERROR,
1877 PED_EXCEPTION_CANCEL,
1878 _("Too many primary partitions."));
1883 if ((part->type & PED_PARTITION_LOGICAL) && !ext_part) {
1884 ped_exception_throw (
1885 PED_EXCEPTION_ERROR,
1886 PED_EXCEPTION_CANCEL,
1887 _("Can't add a logical partition to %s, because "
1888 "there is no extended partition."),
1897 _check_extended_partition (PedDisk* disk, PedPartition* part)
1900 PedPartition* ext_part;
1902 PED_ASSERT (disk != NULL, return 0);
1903 ext_part = ped_disk_extended_partition (disk);
1904 if (!ext_part) ext_part = part;
1905 PED_ASSERT (ext_part != NULL, return 0);
1907 if (part != ext_part) {
1908 ped_exception_throw (
1909 PED_EXCEPTION_ERROR,
1910 PED_EXCEPTION_CANCEL,
1911 _("Can't have more than one extended partition on %s."),
1916 for (walk = ext_part->part_list; walk; walk = walk->next) {
1917 if (!ped_geometry_test_inside (&ext_part->geom, &walk->geom)) {
1918 ped_exception_throw (
1919 PED_EXCEPTION_ERROR,
1920 PED_EXCEPTION_CANCEL,
1921 _("Can't have logical partitions outside of "
1922 "the extended partition."));
1930 _check_partition (PedDisk* disk, PedPartition* part)
1932 PedPartition* ext_part = ped_disk_extended_partition (disk);
1934 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1936 if (part->type == PED_PARTITION_EXTENDED) {
1937 if (!_check_extended_partition (disk, part))
1941 if (part->type & PED_PARTITION_LOGICAL
1942 && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1943 ped_exception_throw (
1944 PED_EXCEPTION_ERROR,
1945 PED_EXCEPTION_CANCEL,
1946 _("Can't have a logical partition outside of the "
1947 "extended partition on %s."),
1952 if (!_disk_check_part_overlaps (disk, part)) {
1953 ped_exception_throw (
1954 PED_EXCEPTION_ERROR,
1955 PED_EXCEPTION_CANCEL,
1956 _("Can't have overlapping partitions."));
1960 if (! (part->type & PED_PARTITION_LOGICAL)
1961 && ext_part && ext_part != part
1962 && ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1963 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1964 _("Can't have a primary partition inside an extended "
1969 if (!(part->type & PED_PARTITION_METADATA))
1970 if (!disk->type->ops->partition_check(part))
1977 * Adds PedPartition \p part to PedPartition \p disk.
1979 * \warning The partition's geometry may be changed, subject to \p constraint.
1980 * You could set \p constraint to <tt>ped_constraint_exact(&part->geom)</tt>,
1981 * but many partition table schemes have special requirements on the start
1982 * and end of partitions. Therefore, having an overly strict constraint
1983 * will probably mean that this function will fail (in which
1984 * case \p part will be left unmodified)
1985 * \p part is assigned a number (\p part->num) in this process.
1987 * \return \c 0 on failure.
1990 ped_disk_add_partition (PedDisk* disk, PedPartition* part,
1991 const PedConstraint* constraint)
1993 PedConstraint* overlap_constraint = NULL;
1994 PedConstraint* constraints = NULL;
1996 PED_ASSERT (disk != NULL, return 0);
1997 PED_ASSERT (part != NULL, return 0);
1999 if (!_partition_check_basic_sanity (disk, part))
2002 if (!_disk_push_update_mode (disk))
2005 if (ped_partition_is_active (part)) {
2007 = _partition_get_overlap_constraint (part, &part->geom);
2008 constraints = ped_constraint_intersect (overlap_constraint,
2011 if (!constraints && constraint) {
2012 ped_exception_throw (
2013 PED_EXCEPTION_ERROR,
2014 PED_EXCEPTION_CANCEL,
2015 _("Can't have overlapping partitions."));
2019 if (!_partition_enumerate (part))
2021 if (!_partition_align (part, constraints))
2024 /* FIXME: when _check_partition fails, we end up leaking PART
2025 at least for DVH partition tables. Simply calling
2026 ped_partition_destroy(part) here fixes it for DVH, but
2027 causes trouble for other partition types. Similarly,
2028 reordering these two checks, putting _check_partition after
2029 _disk_raw_add induces an infinite loop. */
2030 if (!_check_partition (disk, part))
2032 if (!_disk_raw_add (disk, part))
2035 ped_constraint_destroy (overlap_constraint);
2036 ped_constraint_destroy (constraints);
2037 if (!_disk_pop_update_mode (disk))
2040 if (!_disk_check_sanity (disk))
2046 ped_constraint_destroy (overlap_constraint);
2047 ped_constraint_destroy (constraints);
2048 _disk_pop_update_mode (disk);
2053 * Removes PedPartition \p part from PedDisk \p disk.
2055 * If \p part is an extended partition, it must not contain any logical
2056 * partitions. \p part is *NOT* destroyed. The caller must call
2057 * ped_partition_destroy(), or use ped_disk_delete_partition() instead.
2059 * \return \c 0 on error.
2062 ped_disk_remove_partition (PedDisk* disk, PedPartition* part)
2064 PED_ASSERT (disk != NULL, return 0);
2065 PED_ASSERT (part != NULL, return 0);
2067 if (!_disk_push_update_mode (disk))
2069 PED_ASSERT (part->part_list == NULL, ignored);
2070 _disk_raw_remove (disk, part);
2071 if (!_disk_pop_update_mode (disk))
2073 ped_disk_enumerate_partitions (disk);
2078 ped_disk_delete_all_logical (PedDisk* disk);
2081 * Removes \p part from \p disk, and destroys \p part.
2083 * \return \c 0 on failure.
2086 ped_disk_delete_partition (PedDisk* disk, PedPartition* part)
2088 PED_ASSERT (disk != NULL, return 0);
2089 PED_ASSERT (part != NULL, return 0);
2091 if (!_disk_push_update_mode (disk))
2093 if (part->type == PED_PARTITION_EXTENDED)
2094 ped_disk_delete_all_logical (disk);
2095 ped_disk_remove_partition (disk, part);
2096 ped_partition_destroy (part);
2097 if (!_disk_pop_update_mode (disk))
2104 ped_disk_delete_all_logical (PedDisk* disk)
2108 PedPartition* ext_part;
2110 PED_ASSERT (disk != NULL, return 0);
2111 ext_part = ped_disk_extended_partition (disk);
2112 PED_ASSERT (ext_part != NULL, return 0);
2114 for (walk = ext_part->part_list; walk; walk = next) {
2117 if (!ped_disk_delete_partition (disk, walk))
2124 * Removes and destroys all partitions on \p disk.
2126 * \return \c 0 on failure.
2129 ped_disk_delete_all (PedDisk* disk)
2134 PED_ASSERT (disk != NULL, return 0);
2136 if (!_disk_push_update_mode (disk))
2139 for (walk = disk->part_list; walk; walk = next) {
2142 if (!ped_disk_delete_partition (disk, walk)) {
2143 _disk_pop_update_mode(disk);
2148 if (!_disk_pop_update_mode (disk))
2155 * Sets the geometry of \p part (i.e. change a partitions location). This can
2156 * fail for many reasons, e.g. can't overlap with other partitions. If it
2157 * does fail, \p part will remain unchanged. Returns \c 0 on failure. \p part's
2158 * geometry may be set to something different from \p start and \p end subject
2161 * \warning The constraint warning from ped_disk_add_partition() applies.
2163 * \note this function does not modify the contents of the partition. You need
2164 * to call ped_file_system_resize() separately.
2167 ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part,
2168 const PedConstraint* constraint,
2169 PedSector start, PedSector end)
2171 PedConstraint* overlap_constraint = NULL;
2172 PedConstraint* constraints = NULL;
2173 PedGeometry old_geom;
2174 PedGeometry new_geom;
2176 PED_ASSERT (disk != NULL, return 0);
2177 PED_ASSERT (part != NULL, return 0);
2178 PED_ASSERT (part->disk == disk, return 0);
2180 old_geom = part->geom;
2181 ped_geometry_init (&new_geom, part->geom.dev, start, end - start + 1);
2183 if (!_disk_push_update_mode (disk))
2187 = _partition_get_overlap_constraint (part, &new_geom);
2188 constraints = ped_constraint_intersect (overlap_constraint, constraint);
2189 if (!constraints && constraint) {
2190 ped_exception_throw (
2191 PED_EXCEPTION_ERROR,
2192 PED_EXCEPTION_CANCEL,
2193 _("Can't have overlapping partitions."));
2194 goto error_pop_update_mode;
2197 part->geom = new_geom;
2198 if (!_partition_align (part, constraints))
2199 goto error_pop_update_mode;
2200 if (!_check_partition (disk, part))
2201 goto error_pop_update_mode;
2203 /* remove and add, to ensure the ordering gets updated if necessary */
2204 _disk_raw_remove (disk, part);
2205 _disk_raw_add (disk, part);
2207 if (!_disk_pop_update_mode (disk))
2210 ped_constraint_destroy (overlap_constraint);
2211 ped_constraint_destroy (constraints);
2214 error_pop_update_mode:
2215 _disk_pop_update_mode (disk);
2217 ped_constraint_destroy (overlap_constraint);
2218 ped_constraint_destroy (constraints);
2219 part->geom = old_geom;
2224 * Grow PedPartition \p part geometry to the maximum possible subject to
2225 * \p constraint. The new geometry will be a superset of the old geometry.
2227 * \return 0 on failure
2230 ped_disk_maximize_partition (PedDisk* disk, PedPartition* part,
2231 const PedConstraint* constraint)
2233 PedGeometry old_geom;
2234 PedSector global_min_start;
2235 PedSector global_max_end;
2236 PedSector new_start;
2238 PedPartition* ext_part = ped_disk_extended_partition (disk);
2239 PedConstraint* constraint_any;
2241 PED_ASSERT (disk != NULL, return 0);
2242 PED_ASSERT (part != NULL, return 0);
2244 if (part->type & PED_PARTITION_LOGICAL) {
2245 PED_ASSERT (ext_part != NULL, return 0);
2246 global_min_start = ext_part->geom.start;
2247 global_max_end = ext_part->geom.end;
2249 global_min_start = 0;
2250 global_max_end = disk->dev->length - 1;
2253 old_geom = part->geom;
2255 if (!_disk_push_update_mode (disk))
2259 new_start = part->prev->geom.end + 1;
2261 new_start = global_min_start;
2264 new_end = part->next->geom.start - 1;
2266 new_end = global_max_end;
2268 if (!ped_disk_set_partition_geom (disk, part, constraint, new_start,
2272 if (!_disk_pop_update_mode (disk))
2277 constraint_any = ped_constraint_any (disk->dev);
2278 ped_disk_set_partition_geom (disk, part, constraint_any,
2279 old_geom.start, old_geom.end);
2280 ped_constraint_destroy (constraint_any);
2281 _disk_pop_update_mode (disk);
2286 * Get the maximum geometry \p part can be grown to, subject to
2289 * \return \c NULL on failure.
2292 ped_disk_get_max_partition_geometry (PedDisk* disk, PedPartition* part,
2293 const PedConstraint* constraint)
2295 PedGeometry old_geom;
2296 PedGeometry* max_geom;
2297 PedConstraint* constraint_exact;
2299 PED_ASSERT(disk != NULL, return NULL);
2300 PED_ASSERT(part != NULL, return NULL);
2301 PED_ASSERT(ped_partition_is_active (part), return NULL);
2303 old_geom = part->geom;
2304 if (!ped_disk_maximize_partition (disk, part, constraint))
2306 max_geom = ped_geometry_duplicate (&part->geom);
2308 constraint_exact = ped_constraint_exact (&old_geom);
2309 ped_disk_set_partition_geom (disk, part, constraint_exact,
2310 old_geom.start, old_geom.end);
2311 ped_constraint_destroy (constraint_exact);
2313 /* this assertion should never fail, because the old
2314 * geometry was valid
2316 PED_ASSERT (ped_geometry_test_equal (&part->geom, &old_geom),
2323 * Reduce the size of the extended partition to a minimum while still wrapping
2324 * its logical partitions. If there are no logical partitions, remove the
2325 * extended partition.
2327 * \return 0 on failure.
2330 ped_disk_minimize_extended_partition (PedDisk* disk)
2332 PedPartition* first_logical;
2333 PedPartition* last_logical;
2335 PedPartition* ext_part;
2336 PedConstraint* constraint;
2339 PED_ASSERT (disk != NULL, return 0);
2341 ext_part = ped_disk_extended_partition (disk);
2345 if (!_disk_push_update_mode (disk))
2348 first_logical = ext_part->part_list;
2349 if (!first_logical) {
2350 if (!_disk_pop_update_mode (disk))
2352 return ped_disk_delete_partition (disk, ext_part);
2355 for (walk = first_logical; walk->next; walk = walk->next);
2356 last_logical = walk;
2358 constraint = ped_constraint_any (disk->dev);
2359 status = ped_disk_set_partition_geom (disk, ext_part, constraint,
2360 first_logical->geom.start,
2361 last_logical->geom.end);
2362 ped_constraint_destroy (constraint);
2364 if (!_disk_pop_update_mode (disk))
2374 * \addtogroup PedPartition
2380 * Returns a name that seems mildly appropriate for a partition type \p type.
2382 * Eg, if you pass (PED_PARTITION_LOGICAL & PED_PARTITION_FREESPACE), it
2383 * will return "free". This isn't to be taken too seriously - it's just
2384 * useful for user interfaces, so you can show the user something ;-)
2386 * \note The returned string will be in English. However,
2387 * translations are provided, so the caller can call
2388 * dgettext("parted", RESULT) on the result.
2392 ped_partition_type_get_name (PedPartitionType type)
2394 if (type & PED_PARTITION_METADATA)
2395 return N_("metadata");
2396 else if (type & PED_PARTITION_FREESPACE)
2398 else if (type & PED_PARTITION_EXTENDED)
2399 return N_("extended");
2400 else if (type & PED_PARTITION_LOGICAL)
2401 return N_("logical");
2403 return N_("primary");
2408 * Returns a name for a \p flag, e.g. PED_PARTITION_BOOT will return "boot".
2410 * \note The returned string will be in English. However,
2411 * translations are provided, so the caller can call
2412 * dgettext("parted", RESULT) on the result.
2415 ped_partition_flag_get_name (PedPartitionFlag flag)
2418 case PED_PARTITION_BOOT:
2420 case PED_PARTITION_BIOS_GRUB:
2421 return N_("bios_grub");
2422 case PED_PARTITION_ROOT:
2424 case PED_PARTITION_SWAP:
2426 case PED_PARTITION_HIDDEN:
2427 return N_("hidden");
2428 case PED_PARTITION_RAID:
2430 case PED_PARTITION_LVM:
2432 case PED_PARTITION_LBA:
2434 case PED_PARTITION_HPSERVICE:
2435 return N_("hp-service");
2436 case PED_PARTITION_PALO:
2438 case PED_PARTITION_PREP:
2440 case PED_PARTITION_MSFT_RESERVED:
2441 return N_("msftres");
2442 case PED_PARTITION_APPLE_TV_RECOVERY:
2443 return N_("atvrecv");
2444 case PED_PARTITION_DIAG:
2448 ped_exception_throw (
2450 PED_EXCEPTION_CANCEL,
2451 _("Unknown partition flag, %d."),
2458 * Iterates through all flags.
2460 * ped_partition_flag_next(0) returns the first flag
2462 * \return the next flag, or 0 if there are no more flags
2465 ped_partition_flag_next (PedPartitionFlag flag)
2467 return (flag + 1) % (PED_PARTITION_LAST_FLAG + 1);
2471 * Returns the flag associated with \p name.
2473 * \p name can be the English
2474 * string, or the translation for the native language.
2477 ped_partition_flag_get_by_name (const char* name)
2479 PedPartitionFlag flag;
2480 const char* flag_name;
2482 for (flag = ped_partition_flag_next (0); flag;
2483 flag = ped_partition_flag_next (flag)) {
2484 flag_name = ped_partition_flag_get_name (flag);
2485 if (strcasecmp (name, flag_name) == 0
2486 || strcasecmp (name, _(flag_name)) == 0)
2494 ped_partition_print (const PedPartition* part)
2496 PED_ASSERT (part != NULL, return);
2498 printf (" %-10s %02d (%d->%d)\n",
2499 ped_partition_type_get_name (part->type),
2501 (int) part->geom.start, (int) part->geom.end);
2507 * \addtogroup PedDisk
2513 * Prints a summary of disk's partitions. Useful for debugging.
2516 ped_disk_print (const PedDisk* disk)
2520 PED_ASSERT (disk != NULL, return);
2522 for (part = disk->part_list; part;
2523 part = ped_disk_next_partition (disk, part))
2524 ped_partition_print (part);