2 libparted - a library for manipulating disk partitions
3 Copyright (C) 1999, 2000, 2001, 2002, 2003, 2005
4 Free Software Foundation, Inc.
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 2 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, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
26 * \brief Disk label access.
28 * Most programs will need to use ped_disk_new() or ped_disk_new_fresh() to get
29 * anything done. A PedDisk is always associated with a device and has a
30 * partition table. There are different types of partition tables (or disk
31 * labels). These are represented by the PedDiskType enumeration.
38 #include <parted/parted.h>
39 #include <parted/debug.h>
43 # define _(String) dgettext (PACKAGE, String)
44 # define N_(String) (String)
46 # define _(String) (String)
47 # define N_(String) (String)
48 #endif /* ENABLE_NLS */
50 /* UPDATE MODE functions */
52 static int _disk_check_sanity (PedDisk* disk);
54 static void _disk_push_update_mode (PedDisk* disk);
55 static void _disk_pop_update_mode (PedDisk* disk);
56 static int _disk_raw_insert_before (PedDisk* disk, PedPartition* loc,
58 static int _disk_raw_insert_after (PedDisk* disk, PedPartition* loc,
60 static int _disk_raw_remove (PedDisk* disk, PedPartition* part);
61 static int _disk_raw_add (PedDisk* disk, PedPartition* part);
63 static PedDiskType* disk_types = NULL;
66 ped_disk_type_register (PedDiskType* disk_type)
68 PED_ASSERT (disk_type != NULL, return);
69 PED_ASSERT (disk_type->ops != NULL, return);
70 PED_ASSERT (disk_type->name != NULL, return);
72 /* pretend that "next" isn't part of the struct :-) */
73 ((struct _PedDiskType*) disk_type)->next = disk_types;
74 disk_types = (struct _PedDiskType*) disk_type;
78 ped_disk_type_unregister (PedDiskType* disk_type)
81 PedDiskType* last = NULL;
83 PED_ASSERT (disk_types != NULL, return);
84 PED_ASSERT (disk_type != NULL, return);
86 for (walk = disk_types; walk && walk != disk_type;
87 last = walk, walk = walk->next);
89 PED_ASSERT (walk != NULL, return);
91 ((struct _PedDiskType*) last)->next = disk_type->next;
93 disk_types = disk_type->next;
97 * Deprecated: use ped_disk_type_regiser.
100 ped_register_disk_type (PedDiskType* disk_type)
102 ped_disk_type_register (disk_type);
106 * Deprecated: use ped_disk_type_unregiser.
109 ped_unregister_disk_type (PedDiskType* disk_type)
111 ped_disk_type_unregister (disk_type);
115 * Return the next disk type registers, after "type". If "type" is
116 * NULL, returns the first disk type.
118 * \return Next disk; NULL if "type" is the last registered disk type.
121 ped_disk_type_get_next (PedDiskType* type)
130 * Return the disk type with a name of "name".
132 * \return Disk type; NULL if no match.
135 ped_disk_type_get (const char* name)
137 PedDiskType* walk = NULL;
139 PED_ASSERT (name != NULL, return NULL);
141 for (walk = ped_disk_type_get_next (NULL); walk;
142 walk = ped_disk_type_get_next (walk))
143 if (strcasecmp (walk->name, name) == 0)
150 * Return the type of partition table detected on "dev".
152 * \return Type; NULL if none was detected.
155 ped_disk_probe (PedDevice* dev)
157 PedDiskType* walk = NULL;
159 PED_ASSERT (dev != NULL, return NULL);
161 if (!ped_device_open (dev))
164 ped_exception_fetch_all ();
165 for (walk = ped_disk_type_get_next (NULL); walk;
166 walk = ped_disk_type_get_next (walk))
167 if (walk->ops->probe (dev))
171 ped_exception_catch ();
172 ped_exception_leave_all ();
174 ped_device_close (dev);
179 * Read the partition table off a device (if one is found).
181 * \warning May modify \p dev->cylinders, \p dev->heads and \p dev->sectors
182 * if the partition table indicates that the existing values
185 * \return A new \link _PedDisk PedDisk \endlink object;
186 * NULL on failure (e.g. partition table not detected).
189 ped_disk_new (PedDevice* dev)
194 PED_ASSERT (dev != NULL, return NULL);
196 if (!ped_device_open (dev))
199 type = ped_disk_probe (dev);
201 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
202 _("Unable to open %s - unrecognised disk label."),
204 goto error_close_dev;
206 disk = ped_disk_new_fresh (dev, type);
208 goto error_close_dev;
209 if (!type->ops->read (disk))
210 goto error_destroy_disk;
211 disk->needs_clobber = 0;
212 ped_device_close (dev);
216 ped_disk_destroy (disk);
218 ped_device_close (dev);
224 _add_duplicate_part (PedDisk* disk, PedPartition* old_part)
226 PedPartition* new_part;
227 PedConstraint* constraint_exact;
229 new_part = disk->type->ops->partition_duplicate (old_part);
232 new_part->disk = disk;
234 constraint_exact = ped_constraint_exact (&new_part->geom);
235 if (!constraint_exact)
236 goto error_destroy_new_part;
237 if (!ped_disk_add_partition (disk, new_part, constraint_exact))
238 goto error_destroy_constraint_exact;
239 ped_constraint_destroy (constraint_exact);
242 error_destroy_constraint_exact:
243 ped_constraint_destroy (constraint_exact);
244 error_destroy_new_part:
245 ped_partition_destroy (new_part);
251 * Clone a \link _PedDisk PedDisk \endlink object.
253 * \return Deep copy of \p old_disk, NULL on failure.
256 ped_disk_duplicate (const PedDisk* old_disk)
259 PedPartition* old_part;
261 PED_ASSERT (old_disk != NULL, return NULL);
262 PED_ASSERT (!old_disk->update_mode, return NULL);
263 PED_ASSERT (old_disk->type->ops->duplicate != NULL, return NULL);
264 PED_ASSERT (old_disk->type->ops->partition_duplicate != NULL,
267 new_disk = old_disk->type->ops->duplicate (old_disk);
271 _disk_push_update_mode (new_disk);
272 for (old_part = ped_disk_next_partition (old_disk, NULL); old_part;
273 old_part = ped_disk_next_partition (old_disk, old_part)) {
274 if (ped_partition_is_active (old_part)) {
275 if (!_add_duplicate_part (new_disk, old_part))
276 goto error_destroy_new_disk;
279 _disk_pop_update_mode (new_disk);
282 error_destroy_new_disk:
283 ped_disk_destroy (new_disk);
289 * Remove all identifying signatures of a partition table,
290 * except for partition tables of a given type.
292 * \return 0 on error, 1 otherwise.
294 * \sa ped_disk_clobber()
297 ped_disk_clobber_exclude (PedDevice* dev, const PedDiskType* exclude)
301 PED_ASSERT (dev != NULL, goto error);
303 if (!ped_device_open (dev))
306 for (walk = ped_disk_type_get_next (NULL); walk;
307 walk = ped_disk_type_get_next (walk)) {
313 ped_exception_fetch_all ();
314 probed = walk->ops->probe (dev);
316 ped_exception_catch ();
317 ped_exception_leave_all ();
319 if (probed && walk->ops->clobber) {
320 if (!walk->ops->clobber (dev))
321 goto error_close_dev;
324 ped_device_close (dev);
328 ped_device_close (dev);
334 * Remove all identifying signatures of a partition table,
336 * \return 0 on error, 1 otherwise.
338 * \sa ped_disk_clobber_exclude()
341 ped_disk_clobber (PedDevice* dev)
343 return ped_disk_clobber_exclude (dev, NULL);
347 * Create a new partition table on \p dev.
349 * This new partition table is only created in-memory, and nothing is written
350 * to disk until ped_disk_commit_to_dev() is called.
352 * \return The newly constructed \link _PedDisk PedDisk \endlink,
356 ped_disk_new_fresh (PedDevice* dev, const PedDiskType* type)
360 PED_ASSERT (dev != NULL, return NULL);
361 PED_ASSERT (type != NULL, return NULL);
362 PED_ASSERT (type->ops->alloc != NULL, return NULL);
364 disk = type->ops->alloc (dev);
367 _disk_pop_update_mode (disk);
368 PED_ASSERT (disk->update_mode == 0, goto error_destroy_disk);
370 disk->needs_clobber = 1;
374 ped_disk_destroy (disk);
380 _ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type)
384 disk = (PedDisk*) ped_malloc (sizeof (PedDisk));
388 disk->dev = (PedDevice*)dev;
389 disk->type = disk_type;
390 disk->update_mode = 1;
391 disk->part_list = NULL;
401 _ped_disk_free (PedDisk* disk)
403 _disk_push_update_mode (disk);
404 ped_disk_delete_all (disk);
411 * What this function does depends on the PedDiskType of \p disk,
412 * but you can generally assume that outstanding writes are flushed
413 * (this mainly means that _ped_disk_free is called).
416 ped_disk_destroy (PedDisk* disk)
418 PED_ASSERT (disk != NULL, return);
419 PED_ASSERT (!disk->update_mode, return);
421 disk->type->ops->free (disk);
425 * Tell the operating system kernel about the partition table layout
428 * This is rather loosely defined: for example, on old versions of Linux,
429 * it simply calls the BLKRRPART ioctl, which tells the kernel to
430 * reread the partition table. On newer versions (2.4.x), it will
431 * use the new blkpg interface to tell Linux where each partition
432 * starts/ends, etc. In this case, Linux does not need to have support for
433 * a specific type of partition table.
435 * \return 0 on failure, 1 otherwise.
438 ped_disk_commit_to_os (PedDisk* disk)
440 PED_ASSERT (disk != NULL, return 0);
442 if (!ped_device_open (disk->dev))
444 if (!ped_architecture->disk_ops->disk_commit (disk))
445 goto error_close_dev;
446 ped_device_close (disk->dev);
450 ped_device_close (disk->dev);
456 * Write the changes made to the in-memory description
457 * of a partition table to the device.
459 * \return 0 on failure, 1 otherwise.
462 ped_disk_commit_to_dev (PedDisk* disk)
464 PED_ASSERT (disk != NULL, goto error);
465 PED_ASSERT (!disk->update_mode, goto error);
467 if (!disk->type->ops->write) {
468 ped_exception_throw (
470 PED_EXCEPTION_CANCEL,
471 _("This libparted doesn't have write support for "
472 "%s. Perhaps it was compiled read-only."),
477 if (!ped_device_open (disk->dev))
480 if (disk->needs_clobber) {
481 if (!ped_disk_clobber_exclude (disk->dev, disk->type))
482 goto error_close_dev;
483 disk->needs_clobber = 0;
485 if (!disk->type->ops->write (disk))
486 goto error_close_dev;
487 ped_device_close (disk->dev);
491 ped_device_close (disk->dev);
497 * This function writes the in-memory changes to a partition table to
498 * disk and informs the operating system of the changes.
500 * \note Equivalent to calling first ped_disk_commit_to_dev(), then
501 * ped_disk_commit_to_os().
503 * \return 0 on failure, 1 otherwise.
506 ped_disk_commit (PedDisk* disk)
508 if (!ped_disk_commit_to_dev (disk))
510 return ped_disk_commit_to_os (disk);
514 * \addtogroup PedPartition
520 * Check whether a partition is mounted or busy in some
523 * \note An extended partition is busy if any logical partitions are mounted.
525 * \return \c 1 if busy.
528 ped_partition_is_busy (const PedPartition* part)
530 PED_ASSERT (part != NULL, return 1);
532 return ped_architecture->disk_ops->partition_is_busy (part);
536 * Return a path that can be used to address the partition in the
540 ped_partition_get_path (const PedPartition* part)
542 PED_ASSERT (part != NULL, return NULL);
544 return ped_architecture->disk_ops->partition_get_path (part);
550 * \addtogroup PedDisk
556 * Perform a sanity check on a partition table.
558 * \note The check performed is generic (i.e. it does not depends on the label
561 * \throws PED_EXCEPTION_WARNING if a partition type ID does not match the file
564 * \return 0 if the check fails, 1 otherwise.
567 ped_disk_check (PedDisk* disk)
571 PED_ASSERT (disk != NULL, return 0);
573 for (walk = disk->part_list; walk;
574 walk = ped_disk_next_partition (disk, walk)) {
575 const PedFileSystemType* fs_type = walk->fs_type;
577 PedSector length_error;
578 PedSector max_length_error;
580 if (!ped_partition_is_active (walk) || !fs_type)
583 geom = ped_file_system_probe_specific (fs_type, &walk->geom);
587 length_error = abs (walk->geom.length - geom->length);
588 max_length_error = PED_MAX (4096, walk->geom.length / 100);
589 if (!ped_geometry_test_inside (&walk->geom, geom)
590 || length_error > max_length_error) {
591 char* part_size = ped_unit_format (disk->dev, walk->geom.length);
592 char* fs_size = ped_unit_format (disk->dev, geom->length);
593 PedExceptionOption choice;
595 choice = ped_exception_throw (
596 PED_EXCEPTION_WARNING,
597 PED_EXCEPTION_IGNORE_CANCEL,
598 _("Partition %d is %s, but the file system is "
600 walk->num, part_size, fs_size);
602 ped_free (part_size);
605 if (choice != PED_EXCEPTION_IGNORE)
614 * This function checks if a particular type of partition table supports
617 * \return 1 if \p disk_type supports \p feature, 0 otherwise.
620 ped_disk_type_check_feature (const PedDiskType* disk_type,
621 PedDiskTypeFeature feature)
623 return (disk_type->features & feature) != 0;
627 * Get the number of primary partitions.
630 ped_disk_get_primary_partition_count (PedDisk* disk)
635 PED_ASSERT (disk != NULL, return 0);
637 for (walk = disk->part_list; walk;
638 walk = ped_disk_next_partition (disk, walk)) {
639 if (ped_partition_is_active (walk)
640 && ! (walk->type & PED_PARTITION_LOGICAL))
648 * Get the highest partition number on \p disk.
651 ped_disk_get_last_partition_num (PedDisk* disk)
656 PED_ASSERT (disk != NULL, return 0);
658 for (walk = disk->part_list; walk;
659 walk = ped_disk_next_partition (disk, walk)) {
660 if (walk->num > highest)
668 * Get the maximum number of (primary) partitions the disk label supports.
670 * For example, MacIntosh partition maps can have different sizes,
671 * and accordingly support a different number of partitions.
674 ped_disk_get_max_primary_partition_count (const PedDisk* disk)
676 PED_ASSERT (disk->type != NULL, return 0);
677 PED_ASSERT (disk->type->ops->get_max_primary_partition_count != NULL,
680 return disk->type->ops->get_max_primary_partition_count (disk);
684 * \internal We turned a really nasty bureaucracy problem into an elegant maths
685 * problem :-) Basically, there are some constraints to a partition's
688 * (1) it must start and end on a "disk" block, determined by the disk label
689 * (not the hardware). (constraint represented by a PedAlignment)
691 * (2) if we're resizing a partition, we MIGHT need to keep each block aligned.
692 * Eg: if an ext2 file system has 4k blocks, then we can only move the start
693 * by a multiple of 4k. (constraint represented by a PedAlignment)
695 * (3) we need to keep the start and end within the device's physical
696 * boundaries. (constraint represented by a PedGeometry)
698 * Satisfying (1) and (2) simultaneously required a bit of fancy maths ;-) See
699 * ped_alignment_intersect()
701 * The application of these constraints is in disk_*.c's *_partition_align()
705 _partition_align (PedPartition* part, const PedConstraint* constraint)
707 const PedDiskType* disk_type;
709 PED_ASSERT (part != NULL, return 0);
710 PED_ASSERT (part->num != -1, return 0);
711 PED_ASSERT (part->disk != NULL, return 0);
712 disk_type = part->disk->type;
713 PED_ASSERT (disk_type != NULL, return 0);
714 PED_ASSERT (disk_type->ops->partition_align != NULL, return 0);
715 PED_ASSERT (part->disk->update_mode, return 0);
717 return disk_type->ops->partition_align (part, constraint);
721 _partition_enumerate (PedPartition* part)
723 const PedDiskType* disk_type;
725 PED_ASSERT (part != NULL, return 0);
726 PED_ASSERT (part->disk != NULL, return 0);
727 disk_type = part->disk->type;
728 PED_ASSERT (disk_type != NULL, return 0);
729 PED_ASSERT (disk_type->ops->partition_enumerate != NULL, return 0);
731 return disk_type->ops->partition_enumerate (part);
735 * Gives all the (active) partitions a number. It should preserve the numbers
736 * and orders as much as possible.
739 ped_disk_enumerate_partitions (PedDisk* disk)
745 PED_ASSERT (disk != NULL, return 0);
747 /* first "sort" already-numbered partitions. (e.g. if a logical partition
748 * is removed, then all logical partitions that were number higher MUST be
751 end = ped_disk_get_last_partition_num (disk);
752 for (i=1; i<=end; i++) {
753 walk = ped_disk_get_partition (disk, i);
755 if (!_partition_enumerate (walk))
760 /* now, number un-numbered partitions */
761 for (walk = disk->part_list; walk;
762 walk = ped_disk_next_partition (disk, walk)) {
763 if (ped_partition_is_active (walk) && walk->num == -1) {
764 if (!_partition_enumerate (walk))
773 _disk_remove_metadata (PedDisk* disk)
775 PedPartition* walk = NULL;
778 PED_ASSERT (disk != NULL, return 0);
780 next = ped_disk_next_partition (disk, walk);
785 next = ped_disk_next_partition (disk, next);
786 if (!next || next->type & PED_PARTITION_METADATA)
789 if (walk->type & PED_PARTITION_METADATA)
790 ped_disk_delete_partition (disk, walk);
796 _disk_alloc_metadata (PedDisk* disk)
798 PED_ASSERT (disk != NULL, return 0);
800 if (!disk->update_mode)
801 _disk_remove_metadata (disk);
803 return disk->type->ops->alloc_metadata (disk);
807 _disk_remove_freespace (PedDisk* disk)
812 walk = ped_disk_next_partition (disk, NULL);
813 for (; walk; walk = next) {
814 next = ped_disk_next_partition (disk, walk);
816 if (walk->type & PED_PARTITION_FREESPACE) {
817 _disk_raw_remove (disk, walk);
818 ped_partition_destroy (walk);
826 _alloc_extended_freespace (PedDisk* disk)
831 PedPartition* free_space;
832 PedPartition* extended_part;
834 extended_part = ped_disk_extended_partition (disk);
838 last_end = extended_part->geom.start;
841 for (walk = extended_part->part_list; walk; walk = walk->next) {
842 if (walk->geom.start > last_end + 1) {
843 free_space = ped_partition_new (
845 PED_PARTITION_FREESPACE
846 | PED_PARTITION_LOGICAL,
848 last_end + 1, walk->geom.start - 1);
849 _disk_raw_insert_before (disk, walk, free_space);
853 last_end = last->geom.end;
856 if (last_end < extended_part->geom.end) {
857 free_space = ped_partition_new (
859 PED_PARTITION_FREESPACE | PED_PARTITION_LOGICAL,
861 last_end + 1, extended_part->geom.end);
864 return _disk_raw_insert_after (disk, last, free_space);
866 extended_part->part_list = free_space;
873 _disk_alloc_freespace (PedDisk* disk)
878 PedPartition* free_space;
880 if (!_disk_remove_freespace (disk))
882 if (!_alloc_extended_freespace (disk))
888 for (walk = disk->part_list; walk; walk = walk->next) {
889 if (walk->geom.start > last_end + 1) {
890 free_space = ped_partition_new (disk,
891 PED_PARTITION_FREESPACE, NULL,
892 last_end + 1, walk->geom.start - 1);
893 _disk_raw_insert_before (disk, walk, free_space);
897 last_end = last->geom.end;
900 if (last_end < disk->dev->length - 1) {
901 free_space = ped_partition_new (disk,
902 PED_PARTITION_FREESPACE, NULL,
903 last_end + 1, disk->dev->length - 1);
905 return _disk_raw_insert_after (disk, last, free_space);
907 disk->part_list = free_space;
914 * Update mode: used when updating the internal representation of the partition
915 * table. In update mode, the metadata and freespace placeholder/virtual
916 * partitions are removed, making it much easier for various manipulation
920 _disk_push_update_mode (PedDisk* disk)
922 if (!disk->update_mode) {
924 _disk_check_sanity (disk);
927 _disk_remove_freespace (disk);
929 _disk_remove_metadata (disk);
932 _disk_check_sanity (disk);
940 _disk_pop_update_mode (PedDisk* disk)
942 PED_ASSERT (disk->update_mode, return);
944 if (disk->update_mode == 1) {
945 /* re-allocate metadata BEFORE leaving update mode, to prevent infinite
946 * recursion (metadata allocation requires update mode)
949 _disk_check_sanity (disk);
952 _disk_alloc_metadata (disk);
954 _disk_alloc_freespace (disk);
957 _disk_check_sanity (disk);
967 * \addtogroup PedPartition
969 * \brief Partition access.
975 _ped_partition_alloc (const PedDisk* disk, PedPartitionType type,
976 const PedFileSystemType* fs_type,
977 PedSector start, PedSector end)
981 PED_ASSERT (disk != NULL, return 0);
983 part = (PedPartition*) ped_malloc (sizeof (PedPartition));
990 part->disk = (PedDisk*) disk;
991 if (!ped_geometry_init (&part->geom, disk->dev, start, end - start + 1))
992 goto error_free_part;
996 part->part_list = NULL;
997 part->fs_type = fs_type;
1008 _ped_partition_free (PedPartition* part)
1014 _ped_partition_attempt_align (PedPartition* part,
1015 const PedConstraint* external,
1016 PedConstraint* internal)
1018 PedConstraint* intersection;
1019 PedGeometry* solution;
1021 intersection = ped_constraint_intersect (external, internal);
1022 ped_constraint_destroy (internal);
1026 solution = ped_constraint_solve_nearest (intersection, &part->geom);
1028 goto fail_free_intersection;
1029 ped_geometry_set (&part->geom, solution->start, solution->length);
1030 ped_geometry_destroy (solution);
1031 ped_constraint_destroy (intersection);
1034 fail_free_intersection:
1035 ped_constraint_destroy (intersection);
1041 * Create a new \link _PedPartition PedPartition \endlink on \p disk.
1043 * \param type One of \p PED_PARTITION_PRIMARY, \p PED_PARTITION_EXTENDED,
1044 * \p PED_PARTITION_LOGICAL.
1046 * \note The constructed partition is not added to <tt>disk</tt>'s
1047 * partition table. Use ped_disk_add_partition() to do this.
1049 * \return A new \link _PedPartition PedPartition \endlink object,
1052 * \throws PED_EXCEPTION_ERROR if \p type is \p EXTENDED or \p LOGICAL but the
1053 * label does not support this concept.
1056 ped_partition_new (const PedDisk* disk, PedPartitionType type,
1057 const PedFileSystemType* fs_type, PedSector start,
1060 int supports_extended;
1063 PED_ASSERT (disk != NULL, return NULL);
1064 PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL);
1066 supports_extended = ped_disk_type_check_feature (disk->type,
1067 PED_DISK_TYPE_EXTENDED);
1069 if (!supports_extended
1070 && (type == PED_PARTITION_EXTENDED
1071 || type == PED_PARTITION_LOGICAL)) {
1072 ped_exception_throw (
1073 PED_EXCEPTION_ERROR,
1074 PED_EXCEPTION_CANCEL,
1075 _("%s disk labels do not support extended "
1081 part = disk->type->ops->partition_new (disk, type, fs_type, start, end);
1085 if (fs_type || part->type == PED_PARTITION_EXTENDED) {
1086 if (!ped_partition_set_system (part, fs_type))
1087 goto error_destroy_part;
1092 ped_partition_destroy (part);
1098 * Destroy a \link _PedPartition PedPartition \endlink object.
1100 * \note Should not be called on a partition that is in a partition table.
1101 * Use ped_disk_delete_partition() instead.
1104 ped_partition_destroy (PedPartition* part)
1106 PED_ASSERT (part != NULL, return);
1107 PED_ASSERT (part->disk != NULL, return);
1108 PED_ASSERT (part->disk->type->ops->partition_new != NULL, return);
1110 part->disk->type->ops->partition_destroy (part);
1115 * Return whether or not the partition is "active".
1117 * A partition is active if \p part->type is neither \p PED_PARTITION_METADATA
1118 * nor \p PED_PARTITION_FREE.
1121 ped_partition_is_active (const PedPartition* part)
1123 PED_ASSERT (part != NULL, return 0);
1125 return !(part->type & PED_PARTITION_FREESPACE
1126 || part->type & PED_PARTITION_METADATA);
1130 * Set the state (\c 1 or \c 0) of a flag on a partition.
1132 * Flags are disk label specific, although they have a global
1133 * "namespace": the flag PED_PARTITION_BOOT, for example, roughly means
1134 * "this" partition is bootable". But this means different things on different
1135 * disk labels (and may not be defined on some disk labels). For example,
1136 * on MS-DOS disk labels, there can only be one boot partition, and this
1137 * refers to the partition that will be booted from on startup. On PC98
1138 * disk labels, the user can choose from any bootable partition on startup.
1140 * \note It is an error to call this on an unavailable flag -- use
1141 * ped_partition_is_flag_available() to determine which flags are available
1142 * for a given disk label.
1144 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
1148 ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1152 PED_ASSERT (part != NULL, return 0);
1153 PED_ASSERT (part->disk != NULL, return 0);
1154 PED_ASSERT (ped_partition_is_active (part), return 0);
1156 ops = part->disk->type->ops;
1157 PED_ASSERT (ops->partition_set_flag != NULL, return 0);
1158 PED_ASSERT (ops->partition_is_flag_available != NULL, return 0);
1160 if (!ops->partition_is_flag_available (part, flag)) {
1161 ped_exception_throw (
1162 PED_EXCEPTION_ERROR,
1163 PED_EXCEPTION_CANCEL,
1164 "The flag '%s' is not available for %s disk labels.",
1165 ped_partition_flag_get_name (flag),
1166 part->disk->type->name);
1170 return ops->partition_set_flag (part, flag, state);
1174 * Get the state (\c 1 or \c 0) of a flag on a partition.
1176 * See ped_partition_set_flag() for conditions that must hold.
1178 * \todo Where's the check for flag availability?
1181 ped_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1183 PED_ASSERT (part != NULL, return 0);
1184 PED_ASSERT (part->disk != NULL, return 0);
1185 PED_ASSERT (part->disk->type->ops->partition_get_flag != NULL,
1187 PED_ASSERT (ped_partition_is_active (part), return 0);
1189 return part->disk->type->ops->partition_get_flag (part, flag);
1193 * Check whether a given flag is available on a partition.
1195 * \return \c 1 if the flag is available.
1198 ped_partition_is_flag_available (const PedPartition* part,
1199 PedPartitionFlag flag)
1201 PED_ASSERT (part != NULL, return 0);
1202 PED_ASSERT (part->disk != NULL, return 0);
1203 PED_ASSERT (part->disk->type->ops->partition_is_flag_available != NULL,
1205 PED_ASSERT (ped_partition_is_active (part), return 0);
1207 return part->disk->type->ops->partition_is_flag_available (part, flag);
1211 * Sets the system type on the partition to \p fs_type.
1213 * \note The file system may be opened, to get more information about the
1214 * file system, e.g. to determine if it's FAT16 or FAT32.
1216 * \return \c 0 on failure.
1219 ped_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1222 const PedDiskType* disk_type;
1224 PED_ASSERT (part != NULL, return 0);
1225 PED_ASSERT (ped_partition_is_active (part), return 0);
1226 PED_ASSERT (part->disk != NULL, return 0);
1227 disk_type = part->disk->type;
1228 PED_ASSERT (disk_type != NULL, return 0);
1229 PED_ASSERT (disk_type->ops != NULL, return 0);
1230 PED_ASSERT (disk_type->ops->partition_set_system != NULL, return 0);
1232 return disk_type->ops->partition_set_system (part, fs_type);
1236 _assert_partition_name_feature (const PedDiskType* disk_type)
1238 if (!ped_disk_type_check_feature (
1239 disk_type, PED_DISK_TYPE_PARTITION_NAME)) {
1240 ped_exception_throw (
1241 PED_EXCEPTION_ERROR,
1242 PED_EXCEPTION_CANCEL,
1243 "%s disk labels do not support partition names.",
1251 * Sets the name of a partition.
1253 * \note This will only work if the disk label supports it.
1256 * ped_disk_type_check_feature (part->disk->type, PED_DISK_TYPE_PARTITION_NAME);
1258 * to check whether this feature is enabled for a label.
1260 * \note \p name will not be modified by libparted. It can be freed
1261 * by the caller immediately after ped_partition_set_name() is called.
1263 * \return \c 1 on success, \c 0 otherwise.
1266 ped_partition_set_name (PedPartition* part, const char* name)
1268 PED_ASSERT (part != NULL, return 0);
1269 PED_ASSERT (part->disk != NULL, return 0);
1270 PED_ASSERT (ped_partition_is_active (part), return 0);
1271 PED_ASSERT (name != NULL, return 0);
1273 if (!_assert_partition_name_feature (part->disk->type))
1276 PED_ASSERT (part->disk->type->ops->partition_set_name != NULL,
1278 part->disk->type->ops->partition_set_name (part, name);
1283 * Returns the name of a partition \p part. This will only work if the disk
1284 * label supports it.
1286 * \note The returned string should not be modified. It should
1287 * not be referenced after the partition is destroyed.
1290 ped_partition_get_name (const PedPartition* part)
1292 PED_ASSERT (part != NULL, return NULL);
1293 PED_ASSERT (part->disk != NULL, return 0);
1294 PED_ASSERT (ped_partition_is_active (part), return 0);
1296 if (!_assert_partition_name_feature (part->disk->type))
1299 PED_ASSERT (part->disk->type->ops->partition_get_name != NULL,
1301 return part->disk->type->ops->partition_get_name (part);
1307 * \addtogroup PedDisk
1313 ped_disk_extended_partition (const PedDisk* disk)
1317 PED_ASSERT (disk != NULL, return 0);
1319 for (walk = disk->part_list; walk; walk = walk->next) {
1320 if (walk->type == PED_PARTITION_EXTENDED)
1327 * Return the next partition after \p part on \p disk. If \p part is \c NULL,
1328 * return the first partition. If \p part is the last partition, returns
1329 * \c NULL. If \p part is an extended partition, returns the first logical
1330 * partition. If this is called repeatedly passing the return value as \p part,
1331 * a depth-first traversal is executed.
1333 * \return The next partition, \c NULL if no more partitions left.
1336 ped_disk_next_partition (const PedDisk* disk, const PedPartition* part)
1338 PED_ASSERT (disk != NULL, return 0);
1341 return disk->part_list;
1342 if (part->type == PED_PARTITION_EXTENDED)
1343 return part->part_list ? part->part_list : part->next;
1346 if (part->type & PED_PARTITION_LOGICAL)
1347 return ped_disk_extended_partition (disk)->next;
1355 _disk_check_sanity (PedDisk* disk)
1359 PED_ASSERT (disk != NULL, return 0);
1361 for (walk = disk->part_list; walk; walk = walk->next) {
1362 PED_ASSERT (!(walk->type & PED_PARTITION_LOGICAL), return 0);
1363 PED_ASSERT (!walk->prev || walk->prev->next == walk, return 0);
1366 if (!ped_disk_extended_partition (disk))
1369 for (walk = ped_disk_extended_partition (disk)->part_list; walk;
1370 walk = walk->next) {
1371 PED_ASSERT (walk->type & PED_PARTITION_LOGICAL, return 0);
1373 PED_ASSERT (walk->prev->next == walk, return 0);
1380 * Returns the partition numbered \p num.
1382 * \return \c NULL if the specified partition does not exist.
1385 ped_disk_get_partition (const PedDisk* disk, int num)
1389 PED_ASSERT (disk != NULL, return 0);
1391 for (walk = disk->part_list; walk;
1392 walk = ped_disk_next_partition (disk, walk)) {
1393 if (walk->num == num && !(walk->type & PED_PARTITION_FREESPACE))
1401 * Returns the partition that contains sect. If sect lies within a logical
1402 * partition, then the logical partition is returned (not the extended
1406 ped_disk_get_partition_by_sector (const PedDisk* disk, PedSector sect)
1410 PED_ASSERT (disk != NULL, return 0);
1412 for (walk = disk->part_list; walk;
1413 walk = ped_disk_next_partition (disk, walk)) {
1414 if (ped_geometry_test_sector_inside (&walk->geom, sect)
1415 && walk->type != PED_PARTITION_EXTENDED)
1419 /* should never get here, unless sect is outside of disk's useable
1420 * part, or we're in "update mode", and the free space place-holders
1421 * have been removed with _disk_remove_freespace()
1426 /* I'm beginning to agree with Sedgewick :-/ */
1428 _disk_raw_insert_before (PedDisk* disk, PedPartition* loc, PedPartition* part)
1430 PED_ASSERT (disk != NULL, return 0);
1431 PED_ASSERT (loc != NULL, return 0);
1432 PED_ASSERT (part != NULL, return 0);
1434 part->prev = loc->prev;
1437 part->prev->next = part;
1439 if (loc->type & PED_PARTITION_LOGICAL)
1440 ped_disk_extended_partition (disk)->part_list = part;
1442 disk->part_list = part;
1450 _disk_raw_insert_after (PedDisk* disk, PedPartition* loc, PedPartition* part)
1452 PED_ASSERT (disk != NULL, return 0);
1453 PED_ASSERT (loc != NULL, return 0);
1454 PED_ASSERT (part != NULL, return 0);
1457 part->next = loc->next;
1459 loc->next->prev = part;
1466 _disk_raw_remove (PedDisk* disk, PedPartition* part)
1468 PED_ASSERT (disk != NULL, return 0);
1469 PED_ASSERT (part != NULL, return 0);
1472 part->prev->next = part->next;
1474 part->next->prev = part->prev;
1476 if (part->type & PED_PARTITION_LOGICAL) {
1477 ped_disk_extended_partition (disk)->part_list
1480 disk->part_list = part->next;
1483 part->next->prev = NULL;
1493 _disk_raw_add (PedDisk* disk, PedPartition* part)
1497 PedPartition* ext_part;
1499 PED_ASSERT (disk->update_mode, return 0);
1501 ext_part = ped_disk_extended_partition (disk);
1504 walk = (part->type & PED_PARTITION_LOGICAL) ?
1505 ext_part->part_list : disk->part_list;
1507 for (; walk; last = walk, walk = walk->next) {
1508 if (walk->geom.start > part->geom.end)
1513 return _disk_raw_insert_before (disk, walk, part);
1516 return _disk_raw_insert_after (disk, last, part);
1518 if (part->type & PED_PARTITION_LOGICAL)
1519 ext_part->part_list = part;
1521 disk->part_list = part;
1528 static PedConstraint*
1529 _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
1531 PedSector min_start;
1534 PedGeometry free_space;
1536 PED_ASSERT (part->disk->update_mode, return NULL);
1537 PED_ASSERT (part->geom.dev == geom->dev, return NULL);
1539 if (part->type & PED_PARTITION_LOGICAL) {
1540 PedPartition* ext_part;
1542 ext_part = ped_disk_extended_partition (part->disk);
1543 PED_ASSERT (ext_part != NULL, return NULL);
1545 min_start = ext_part->geom.start;
1546 max_end = ext_part->geom.end;
1547 walk = ext_part->part_list;
1550 max_end = part->disk->dev->length - 1;
1551 walk = part->disk->part_list;
1555 && (walk->geom.start < geom->start
1556 || min_start >= walk->geom.start)) {
1558 min_start = walk->geom.end + 1;
1566 max_end = walk->geom.start - 1;
1568 if (min_start >= max_end)
1571 ped_geometry_init (&free_space, part->disk->dev,
1572 min_start, max_end - min_start + 1);
1573 return ped_constraint_new_from_max (&free_space);
1577 * Returns \c 0 if the partition, \p part overlaps with any partitions on the
1578 * \p disk. The geometry of \p part is taken to be \p geom, NOT \p part->geom
1579 * (the idea here is to check if \p geom is valid, before changing \p part).
1581 * This is useful for seeing if a resized partitions new geometry is going to
1582 * fit, without the existing geomtry getting in the way.
1584 * Note: overlap with an extended partition is also allowed, provided that
1585 * \p geom lies completely inside the extended partition.
1588 _disk_check_part_overlaps (PedDisk* disk, PedPartition* part)
1592 PED_ASSERT (disk != NULL, return 0);
1593 PED_ASSERT (part != NULL, return 0);
1595 for (walk = ped_disk_next_partition (disk, NULL); walk;
1596 walk = ped_disk_next_partition (disk, walk)) {
1597 if (walk->type & PED_PARTITION_FREESPACE)
1601 if (part->type & PED_PARTITION_EXTENDED
1602 && walk->type & PED_PARTITION_LOGICAL)
1605 if (ped_geometry_test_overlap (&walk->geom, &part->geom)) {
1606 if (walk->type & PED_PARTITION_EXTENDED
1607 && part->type & PED_PARTITION_LOGICAL
1608 && ped_geometry_test_inside (&walk->geom,
1619 _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
1621 PedPartition* ext_part = ped_disk_extended_partition (disk);
1623 PED_ASSERT (part->disk == disk, return 0);
1625 PED_ASSERT (part->geom.start >= 0, return 0);
1626 PED_ASSERT (part->geom.end < disk->dev->length, return 0);
1627 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1629 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
1630 && (part->type == PED_PARTITION_EXTENDED
1631 || part->type == PED_PARTITION_LOGICAL)) {
1632 ped_exception_throw (
1633 PED_EXCEPTION_ERROR,
1634 PED_EXCEPTION_CANCEL,
1635 _("%s disk labels don't support logical or extended "
1641 if (ped_partition_is_active (part)
1642 && ! (part->type & PED_PARTITION_LOGICAL)) {
1643 if (ped_disk_get_primary_partition_count (disk) + 1
1644 > ped_disk_get_max_primary_partition_count (disk)) {
1645 ped_exception_throw (
1646 PED_EXCEPTION_ERROR,
1647 PED_EXCEPTION_CANCEL,
1648 _("Too many primary partitions."));
1653 if ((part->type & PED_PARTITION_LOGICAL) && !ext_part) {
1654 ped_exception_throw (
1655 PED_EXCEPTION_ERROR,
1656 PED_EXCEPTION_CANCEL,
1657 _("Can't add a logical partition to %s, because "
1658 "there is no extended partition."),
1667 _check_extended_partition (PedDisk* disk, PedPartition* part)
1670 PedPartition* ext_part;
1672 PED_ASSERT (disk != NULL, return 0);
1673 ext_part = ped_disk_extended_partition (disk);
1674 if (!ext_part) ext_part = part;
1675 PED_ASSERT (ext_part != NULL, return 0);
1677 if (part != ext_part) {
1678 ped_exception_throw (
1679 PED_EXCEPTION_ERROR,
1680 PED_EXCEPTION_CANCEL,
1681 _("Can't have more than one extended partition on %s."),
1686 for (walk = ext_part->part_list; walk; walk = walk->next) {
1687 if (!ped_geometry_test_inside (&ext_part->geom, &walk->geom)) {
1688 ped_exception_throw (
1689 PED_EXCEPTION_ERROR,
1690 PED_EXCEPTION_CANCEL,
1691 _("Can't have logical partitions outside of "
1692 "the extended partition."));
1700 _check_partition (PedDisk* disk, PedPartition* part)
1702 PedPartition* ext_part = ped_disk_extended_partition (disk);
1704 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1706 if (part->type == PED_PARTITION_EXTENDED) {
1707 if (!_check_extended_partition (disk, part))
1711 if (part->type & PED_PARTITION_LOGICAL
1712 && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1713 ped_exception_throw (
1714 PED_EXCEPTION_ERROR,
1715 PED_EXCEPTION_CANCEL,
1716 _("Can't have a logical partition outside of the "
1717 "extended partition on %s."),
1722 if (!_disk_check_part_overlaps (disk, part)) {
1723 ped_exception_throw (
1724 PED_EXCEPTION_ERROR,
1725 PED_EXCEPTION_CANCEL,
1726 _("Can't have overlapping partitions."));
1730 if (! (part->type & PED_PARTITION_LOGICAL)
1731 && ext_part && ext_part != part
1732 && ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1733 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1734 _("Can't have a primary partition inside an extended "
1743 * Adds PedPartition \p part to PedPartition \p disk.
1745 * \warning The partition's geometry may be changed, subject to \p constraint.
1746 * You could set \p constraint to <tt>ped_constraint_exact(&part->geom)</tt>,
1747 * but many partition table schemes have special requirements on the start
1748 * and end of partitions. Therefore, having an overly strict constraint
1749 * will probably mean that this function will fail (in which
1750 * case \p part will be left unmodified)
1751 * \p part is assigned a number (\p part->num) in this process.
1753 * \return \c 0 on failure.
1756 ped_disk_add_partition (PedDisk* disk, PedPartition* part,
1757 const PedConstraint* constraint)
1759 PedConstraint* overlap_constraint = NULL;
1760 PedConstraint* constraints = NULL;
1762 PED_ASSERT (disk != NULL, return 0);
1763 PED_ASSERT (part != NULL, return 0);
1765 if (!_partition_check_basic_sanity (disk, part))
1768 _disk_push_update_mode (disk);
1770 if (ped_partition_is_active (part)) {
1772 = _partition_get_overlap_constraint (part, &part->geom);
1773 constraints = ped_constraint_intersect (overlap_constraint,
1776 if (!constraints && constraint) {
1777 ped_exception_throw (
1778 PED_EXCEPTION_ERROR,
1779 PED_EXCEPTION_CANCEL,
1780 _("Can't have overlapping partitions."));
1784 if (!_partition_enumerate (part))
1786 if (!_partition_align (part, constraints))
1789 if (!_check_partition (disk, part))
1791 if (!_disk_raw_add (disk, part))
1794 ped_constraint_destroy (overlap_constraint);
1795 ped_constraint_destroy (constraints);
1796 _disk_pop_update_mode (disk);
1798 if (!_disk_check_sanity (disk))
1804 ped_constraint_destroy (overlap_constraint);
1805 ped_constraint_destroy (constraints);
1806 _disk_pop_update_mode (disk);
1811 * Removes PedPartition \p part from PedDisk \p disk.
1813 * If \p part is an extended partition, it must not contain any logical
1814 * partitions. \p part is *NOT* destroyed. The caller must call
1815 * ped_partition_destroy(), or use ped_disk_delete_partition() instead.
1817 * \return \c 0 on error.
1820 ped_disk_remove_partition (PedDisk* disk, PedPartition* part)
1822 PED_ASSERT (disk != NULL, return 0);
1823 PED_ASSERT (part != NULL, return 0);
1825 _disk_push_update_mode (disk);
1826 PED_ASSERT (part->part_list == NULL, goto error);
1827 _disk_raw_remove (disk, part);
1828 _disk_pop_update_mode (disk);
1829 ped_disk_enumerate_partitions (disk);
1833 _disk_pop_update_mode (disk);
1838 ped_disk_delete_all_logical (PedDisk* disk);
1841 * Removes \p part from \p disk, and destroys \p part.
1843 * \return \c 0 on failure.
1846 ped_disk_delete_partition (PedDisk* disk, PedPartition* part)
1848 PED_ASSERT (disk != NULL, return 0);
1849 PED_ASSERT (part != NULL, return 0);
1851 _disk_push_update_mode (disk);
1852 if (part->type == PED_PARTITION_EXTENDED)
1853 ped_disk_delete_all_logical (disk);
1854 ped_disk_remove_partition (disk, part);
1855 ped_partition_destroy (part);
1856 _disk_pop_update_mode (disk);
1862 ped_disk_delete_all_logical (PedDisk* disk)
1866 PedPartition* ext_part;
1868 PED_ASSERT (disk != NULL, return 0);
1869 ext_part = ped_disk_extended_partition (disk);
1870 PED_ASSERT (ext_part != NULL, return 0);
1872 for (walk = ext_part->part_list; walk; walk = next) {
1875 if (!ped_disk_delete_partition (disk, walk))
1882 * Removes and destroys all partitions on \p disk.
1884 * \return \c 0 on failure.
1887 ped_disk_delete_all (PedDisk* disk)
1892 PED_ASSERT (disk != NULL, return 0);
1894 _disk_push_update_mode (disk);
1896 for (walk = disk->part_list; walk; walk = next) {
1899 if (!ped_disk_delete_partition (disk, walk))
1903 _disk_pop_update_mode (disk);
1909 * Sets the geometry of \p part (i.e. change a partitions location). This can
1910 * fail for many reasons, e.g. can't overlap with other partitions. If it
1911 * does fail, \p part will remain unchanged. Returns \c 0 on failure. \p part's
1912 * geometry may be set to something different from \p start and \p end subject
1915 * \warning The constraint warning from ped_disk_add_partition() applies.
1917 * \note this function does not modify the contents of the partition. You need
1918 * to call ped_file_system_resize() separately.
1921 ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part,
1922 const PedConstraint* constraint,
1923 PedSector start, PedSector end)
1925 PedConstraint* overlap_constraint = NULL;
1926 PedConstraint* constraints = NULL;
1927 PedGeometry old_geom;
1928 PedGeometry new_geom;
1930 PED_ASSERT (disk != NULL, return 0);
1931 PED_ASSERT (part != NULL, return 0);
1932 PED_ASSERT (part->disk == disk, return 0);
1934 old_geom = part->geom;
1935 ped_geometry_init (&new_geom, part->geom.dev, start, end - start + 1);
1937 _disk_push_update_mode (disk);
1940 = _partition_get_overlap_constraint (part, &new_geom);
1941 constraints = ped_constraint_intersect (overlap_constraint, constraint);
1942 if (!constraints && constraint) {
1943 ped_exception_throw (
1944 PED_EXCEPTION_ERROR,
1945 PED_EXCEPTION_CANCEL,
1946 _("Can't have overlapping partitions."));
1947 goto error_pop_update_mode;
1950 part->geom = new_geom;
1951 if (!_partition_align (part, constraints))
1952 goto error_pop_update_mode;
1953 if (!_check_partition (disk, part))
1954 goto error_pop_update_mode;
1956 /* remove and add, to ensure the ordering gets updated if necessary */
1957 _disk_raw_remove (disk, part);
1958 _disk_raw_add (disk, part);
1960 _disk_pop_update_mode (disk);
1962 ped_constraint_destroy (overlap_constraint);
1963 ped_constraint_destroy (constraints);
1966 error_pop_update_mode:
1967 _disk_pop_update_mode (disk);
1969 ped_constraint_destroy (overlap_constraint);
1970 ped_constraint_destroy (constraints);
1971 part->geom = old_geom;
1976 * Grow PedPartition \p part geometry to the maximum possible subject to
1977 * \p constraint. The new geometry will be a superset of the old geometry.
1979 * \return 0 on failure
1982 ped_disk_maximize_partition (PedDisk* disk, PedPartition* part,
1983 const PedConstraint* constraint)
1985 PedGeometry old_geom;
1986 PedSector global_min_start;
1987 PedSector global_max_end;
1988 PedSector new_start;
1990 PedPartition* ext_part = ped_disk_extended_partition (disk);
1991 PedConstraint* constraint_any;
1993 PED_ASSERT (disk != NULL, return 0);
1994 PED_ASSERT (part != NULL, return 0);
1996 if (part->type & PED_PARTITION_LOGICAL) {
1997 PED_ASSERT (ext_part != NULL, return 0);
1998 global_min_start = ext_part->geom.start;
1999 global_max_end = ext_part->geom.end;
2001 global_min_start = 0;
2002 global_max_end = disk->dev->length - 1;
2005 old_geom = part->geom;
2007 _disk_push_update_mode (disk);
2010 new_start = part->prev->geom.end + 1;
2012 new_start = global_min_start;
2015 new_end = part->next->geom.start - 1;
2017 new_end = global_max_end;
2019 if (!ped_disk_set_partition_geom (disk, part, constraint, new_start,
2023 _disk_pop_update_mode (disk);
2027 constraint_any = ped_constraint_any (disk->dev);
2028 ped_disk_set_partition_geom (disk, part, constraint_any,
2029 old_geom.start, old_geom.end);
2030 ped_constraint_destroy (constraint_any);
2031 _disk_pop_update_mode (disk);
2036 * Get the maximum geometry \p part can be grown to, subject to
2039 * \return \c NULL on failure.
2042 ped_disk_get_max_partition_geometry (PedDisk* disk, PedPartition* part,
2043 const PedConstraint* constraint)
2045 PedGeometry old_geom;
2046 PedGeometry* max_geom;
2047 PedConstraint* constraint_exact;
2049 PED_ASSERT(disk != NULL, return NULL);
2050 PED_ASSERT(part != NULL, return NULL);
2051 PED_ASSERT(ped_partition_is_active (part), return NULL);
2053 old_geom = part->geom;
2054 if (!ped_disk_maximize_partition (disk, part, constraint))
2056 max_geom = ped_geometry_duplicate (&part->geom);
2058 constraint_exact = ped_constraint_exact (&old_geom);
2059 ped_disk_set_partition_geom (disk, part, constraint_exact,
2060 old_geom.start, old_geom.end);
2061 ped_constraint_destroy (constraint_exact);
2063 /* this assertion should never fail, because the old
2064 * geometry was valid
2066 PED_ASSERT (ped_geometry_test_equal (&part->geom, &old_geom),
2073 * Reduce the size of the extended partition to a minimum while still wrapping
2074 * its logical partitions. If there are no logical partitions, remove the
2075 * extended partition.
2077 * \return 0 on failure.
2080 ped_disk_minimize_extended_partition (PedDisk* disk)
2082 PedPartition* first_logical;
2083 PedPartition* last_logical;
2085 PedPartition* ext_part;
2086 PedConstraint* constraint;
2089 PED_ASSERT (disk != NULL, return 0);
2091 ext_part = ped_disk_extended_partition (disk);
2095 _disk_push_update_mode (disk);
2097 first_logical = ext_part->part_list;
2098 if (!first_logical) {
2099 _disk_pop_update_mode (disk);
2100 return ped_disk_delete_partition (disk, ext_part);
2103 for (walk = first_logical; walk->next; walk = walk->next);
2104 last_logical = walk;
2106 constraint = ped_constraint_any (disk->dev);
2107 status = ped_disk_set_partition_geom (disk, ext_part, constraint,
2108 first_logical->geom.start,
2109 last_logical->geom.end);
2110 ped_constraint_destroy (constraint);
2112 _disk_pop_update_mode (disk);
2121 * \addtogroup PedPartition
2127 * Returns a name that seems mildly appropriate for a partition type \p type.
2129 * Eg, if you pass (PED_PARTITION_LOGICAL & PED_PARTITION_FREESPACE), it
2130 * will return "free". This isn't to be taken too seriously - it's just
2131 * useful for user interfaces, so you can show the user something ;-)
2133 * \note The returned string will be in English. However,
2134 * translations are provided, so the caller can call
2135 * dgettext("parted", RESULT) on the result.
2139 ped_partition_type_get_name (PedPartitionType type)
2141 if (type & PED_PARTITION_METADATA)
2142 return N_("metadata");
2143 else if (type & PED_PARTITION_FREESPACE)
2145 else if (type & PED_PARTITION_EXTENDED)
2146 return N_("extended");
2147 else if (type & PED_PARTITION_LOGICAL)
2148 return N_("logical");
2150 return N_("primary");
2155 * Returns a name for a \p flag, e.g. PED_PARTITION_BOOT will return "boot".
2157 * \note The returned string will be in English. However,
2158 * translations are provided, so the caller can call
2159 * dgettext("parted", RESULT) on the result.
2162 ped_partition_flag_get_name (PedPartitionFlag flag)
2165 case PED_PARTITION_BOOT:
2167 case PED_PARTITION_ROOT:
2169 case PED_PARTITION_SWAP:
2171 case PED_PARTITION_HIDDEN:
2172 return N_("hidden");
2173 case PED_PARTITION_RAID:
2175 case PED_PARTITION_LVM:
2177 case PED_PARTITION_LBA:
2179 case PED_PARTITION_HPSERVICE:
2180 return N_("hp-service");
2181 case PED_PARTITION_PALO:
2183 case PED_PARTITION_PREP:
2185 case PED_PARTITION_MSFT_RESERVED:
2186 return N_("msftres");
2189 ped_exception_throw (
2191 PED_EXCEPTION_CANCEL,
2192 _("Unknown partition flag, %d."),
2199 * Iterates through all flags.
2201 * ped_partition_flag_next(0) returns the first flag
2203 * \return the next flag, or 0 if there are no more flags
2206 ped_partition_flag_next (PedPartitionFlag flag)
2208 return (flag + 1) % (PED_PARTITION_LAST_FLAG + 1);
2212 * Returns the flag associated with \p name.
2214 * \p name can be the English
2215 * string, or the translation for the native language.
2218 ped_partition_flag_get_by_name (const char* name)
2220 PedPartitionFlag flag;
2221 const char* flag_name;
2223 for (flag = ped_partition_flag_next (0); flag;
2224 flag = ped_partition_flag_next (flag)) {
2225 flag_name = ped_partition_flag_get_name (flag);
2226 if (strcasecmp (name, flag_name) == 0
2227 || strcasecmp (name, _(flag_name)) == 0)
2235 ped_partition_print (PedPartition* part)
2237 PED_ASSERT (part != NULL, return);
2239 printf (" %-10s %02d (%d->%d)\n",
2240 ped_partition_type_get_name (part->type),
2242 (int) part->geom.start, (int) part->geom.end);
2248 * \addtogroup PedDisk
2254 * Prints a summary of disk's partitions. Useful for debugging.
2257 ped_disk_print (PedDisk* disk)
2261 PED_ASSERT (disk != NULL, return);
2263 for (part = disk->part_list; part;
2264 part = ped_disk_next_partition (disk, part))
2265 ped_partition_print (part);