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 */
52 /* UPDATE MODE functions */
54 static int _disk_check_sanity (PedDisk* disk);
56 static void _disk_push_update_mode (PedDisk* disk);
57 static void _disk_pop_update_mode (PedDisk* disk);
58 static int _disk_raw_insert_before (PedDisk* disk, PedPartition* loc,
60 static int _disk_raw_insert_after (PedDisk* disk, PedPartition* loc,
62 static int _disk_raw_remove (PedDisk* disk, PedPartition* part);
63 static int _disk_raw_add (PedDisk* disk, PedPartition* part);
65 static PedDiskType* disk_types = NULL;
68 ped_register_disk_type (PedDiskType* type)
70 PED_ASSERT (type != NULL, return);
71 PED_ASSERT (type->ops != NULL, return);
72 PED_ASSERT (type->name != NULL, return);
74 ((struct _PedDiskType*) type)->next = disk_types;
75 disk_types = (struct _PedDiskType*) type;
78 void ped_unregister_disk_type (PedDiskType* type)
81 PedDiskType* last = NULL;
83 PED_ASSERT (disk_types != NULL, return);
84 PED_ASSERT (type != NULL, return);
86 for (walk = disk_types; walk; last = walk, walk = walk->next) {
87 if (walk == type) break;
90 PED_ASSERT (walk != NULL, return);
92 ((struct _PedDiskType*) last)->next = type->next;
94 disk_types = type->next;
98 * Return the next disk type registers, after "type". If "type" is
99 * NULL, returns the first disk type.
101 * \return Next disk; NULL if "type" is the last registered disk type.
104 ped_disk_type_get_next (PedDiskType* type)
113 * Return the disk type with a name of "name".
115 * \return Disk type; NULL if no match.
118 ped_disk_type_get (const char* name)
120 PedDiskType* walk = NULL;
122 PED_ASSERT (name != NULL, return NULL);
125 walk = ped_disk_type_get_next (walk);
127 if (strcasecmp (walk->name, name) == 0) break;
133 * Return the type of partition table detected on "dev".
135 * \return Type; NULL if none was detected.
138 ped_disk_probe (PedDevice* dev)
140 PedDiskType* walk = NULL;
142 PED_ASSERT (dev != NULL, return NULL);
144 if (!ped_device_open (dev))
147 ped_exception_fetch_all ();
149 walk = ped_disk_type_get_next (walk);
151 if (walk->ops->probe (dev)) break;
154 ped_exception_catch ();
155 ped_exception_leave_all ();
157 ped_device_close (dev);
162 * Read the partition table off a device (if one is found).
164 * \warning May modify \p dev->cylinders, \p dev->heads and \p dev->sectors
165 * if the partition table indicates that the existing values
168 * \return A new \link _PedDisk PedDisk \endlink object;
169 * NULL on failure (e.g. partition table not detected).
172 ped_disk_new (PedDevice* dev)
177 PED_ASSERT (dev != NULL, return NULL);
179 if (!ped_device_open (dev))
182 type = ped_disk_probe (dev);
184 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
185 _("Unable to open %s - unrecognised disk label."),
187 goto error_close_dev;
189 disk = ped_disk_new_fresh (dev, type);
191 goto error_close_dev;
192 if (!type->ops->read (disk))
193 goto error_destroy_disk;
194 disk->needs_clobber = 0;
195 ped_device_close (dev);
199 ped_disk_destroy (disk);
201 ped_device_close (dev);
207 _add_duplicate_part (PedDisk* disk, PedPartition* old_part)
209 PedPartition* new_part;
210 PedConstraint* constraint_exact;
212 new_part = disk->type->ops->partition_duplicate (old_part);
215 new_part->disk = disk;
217 constraint_exact = ped_constraint_exact (&new_part->geom);
218 if (!constraint_exact)
219 goto error_destroy_new_part;
220 if (!ped_disk_add_partition (disk, new_part, constraint_exact))
221 goto error_destroy_constraint_exact;
222 ped_constraint_destroy (constraint_exact);
225 error_destroy_constraint_exact:
226 ped_constraint_destroy (constraint_exact);
227 error_destroy_new_part:
228 ped_partition_destroy (new_part);
234 * Clone a \link _PedDisk PedDisk \endlink object.
236 * \return Deep copy of \p old_disk, NULL on failure.
239 ped_disk_duplicate (const PedDisk* old_disk)
242 PedPartition* old_part;
244 PED_ASSERT (old_disk != NULL, return NULL);
245 PED_ASSERT (!old_disk->update_mode, return NULL);
246 PED_ASSERT (old_disk->type->ops->duplicate != NULL, return NULL);
247 PED_ASSERT (old_disk->type->ops->partition_duplicate != NULL,
250 new_disk = old_disk->type->ops->duplicate (old_disk);
254 _disk_push_update_mode (new_disk);
255 for (old_part = ped_disk_next_partition (old_disk, NULL); old_part;
256 old_part = ped_disk_next_partition (old_disk, old_part)) {
257 if (ped_partition_is_active (old_part)) {
258 if (!_add_duplicate_part (new_disk, old_part))
259 goto error_destroy_new_disk;
262 _disk_pop_update_mode (new_disk);
265 error_destroy_new_disk:
266 ped_disk_destroy (new_disk);
272 * Remove all identifying signatures of a partition table,
273 * except for partition tables of a given type.
275 * \return 0 on error, 1 otherwise.
277 * \sa ped_disk_clobber()
280 ped_disk_clobber_exclude (PedDevice* dev, const PedDiskType* exclude)
284 PED_ASSERT (dev != NULL, goto error);
286 if (!ped_device_open (dev))
289 for (walk = ped_disk_type_get_next (NULL); walk;
290 walk = ped_disk_type_get_next (walk)) {
296 ped_exception_fetch_all ();
297 probed = walk->ops->probe (dev);
299 ped_exception_catch ();
300 ped_exception_leave_all ();
302 if (probed && walk->ops->clobber) {
303 if (!walk->ops->clobber (dev))
304 goto error_close_dev;
307 ped_device_close (dev);
311 ped_device_close (dev);
317 * Remove all identifying signatures of a partition table,
319 * \return 0 on error, 1 otherwise.
321 * \sa ped_disk_clobber_exclude()
324 ped_disk_clobber (PedDevice* dev)
326 return ped_disk_clobber_exclude (dev, NULL);
330 * Create a new partition table on \p dev.
332 * This new partition table is only created in-memory, and nothing is written
333 * to disk until ped_disk_commit_to_dev() is called.
335 * \return The newly constructed \link _PedDisk PedDisk \endlink,
339 ped_disk_new_fresh (PedDevice* dev, const PedDiskType* type)
343 PED_ASSERT (dev != NULL, return NULL);
344 PED_ASSERT (type != NULL, return NULL);
345 PED_ASSERT (type->ops->alloc != NULL, return NULL);
347 disk = type->ops->alloc (dev);
350 _disk_pop_update_mode (disk);
351 PED_ASSERT (disk->update_mode == 0, goto error_destroy_disk);
353 disk->needs_clobber = 1;
357 ped_disk_destroy (disk);
363 _ped_disk_alloc (const PedDevice* dev, const PedDiskType* disk_type)
367 disk = (PedDisk*) ped_malloc (sizeof (PedDisk));
371 disk->dev = (PedDevice*)dev;
372 disk->type = disk_type;
373 disk->update_mode = 1;
374 disk->part_list = NULL;
384 _ped_disk_free (PedDisk* disk)
386 _disk_push_update_mode (disk);
387 ped_disk_delete_all (disk);
394 * What this function does depends on the PedDiskType of \p disk,
395 * but you can generally assume that outstanding writes are flushed
396 * (this mainly means that _ped_disk_free is called).
399 ped_disk_destroy (PedDisk* disk)
401 PED_ASSERT (disk != NULL, return);
402 PED_ASSERT (!disk->update_mode, return);
404 disk->type->ops->free (disk);
408 * Tell the operating system kernel about the partition table layout
411 * This is rather loosely defined: for example, on old versions of Linux,
412 * it simply calls the BLKRRPART ioctl, which tells the kernel to
413 * reread the partition table. On newer versions (2.4.x), it will
414 * use the new blkpg interface to tell Linux where each partition
415 * starts/ends, etc. In this case, Linux does not need to have support for
416 * a specific type of partition table.
418 * \return 0 on failure, 1 otherwise.
421 ped_disk_commit_to_os (PedDisk* disk)
423 PED_ASSERT (disk != NULL, return 0);
425 if (!ped_device_open (disk->dev))
427 if (!ped_architecture->disk_ops->disk_commit (disk))
428 goto error_close_dev;
429 ped_device_close (disk->dev);
433 ped_device_close (disk->dev);
439 * Write the changes made to the in-memory description
440 * of a partition table to the device.
442 * \return 0 on failure, 1 otherwise.
445 ped_disk_commit_to_dev (PedDisk* disk)
447 PED_ASSERT (disk != NULL, goto error);
448 PED_ASSERT (!disk->update_mode, goto error);
450 if (!disk->type->ops->write) {
451 ped_exception_throw (
453 PED_EXCEPTION_CANCEL,
454 _("This libparted doesn't have write support for "
455 "%s. Perhaps it was compiled read-only."),
460 if (!ped_device_open (disk->dev))
463 if (disk->needs_clobber) {
464 if (!ped_disk_clobber_exclude (disk->dev, disk->type))
465 goto error_close_dev;
466 disk->needs_clobber = 0;
468 if (!disk->type->ops->write (disk))
469 goto error_close_dev;
470 ped_device_close (disk->dev);
474 ped_device_close (disk->dev);
480 * This function writes the in-memory changes to a partition table to
481 * disk and informs the operating system of the changes.
483 * \note Equivalent to calling first ped_disk_commit_to_dev(), then
484 * ped_disk_commit_to_os().
486 * \return 0 on failure, 1 otherwise.
489 ped_disk_commit (PedDisk* disk)
491 if (!ped_disk_commit_to_dev (disk))
493 return ped_disk_commit_to_os (disk);
497 * \addtogroup PedPartition
503 * Check whether a partition is mounted or busy in some
506 * \note An extended partition is busy if any logical partitions are mounted.
508 * \return \c 1 if busy.
511 ped_partition_is_busy (const PedPartition* part)
513 PED_ASSERT (part != NULL, return 1);
515 return ped_architecture->disk_ops->partition_is_busy (part);
519 * Return a path that can be used to address the partition in the
523 ped_partition_get_path (const PedPartition* part)
525 PED_ASSERT (part != NULL, return NULL);
527 return ped_architecture->disk_ops->partition_get_path (part);
533 * \addtogroup PedDisk
539 * Perform a sanity check on a partition table.
541 * \note The check performed is generic (i.e. it does not depends on the label
544 * \throws PED_EXCEPTION_WARNING if a partition type ID does not match the file
547 * \return 0 if the check fails, 1 otherwise.
550 ped_disk_check (PedDisk* disk)
554 PED_ASSERT (disk != NULL, return 0);
556 for (walk = disk->part_list; walk;
557 walk = ped_disk_next_partition (disk, walk)) {
558 const PedFileSystemType* fs_type = walk->fs_type;
560 PedSector length_error;
561 PedSector max_length_error;
563 if (!ped_partition_is_active (walk) || !fs_type)
566 geom = ped_file_system_probe_specific (fs_type, &walk->geom);
570 length_error = abs (walk->geom.length - geom->length);
571 max_length_error = PED_MAX (4096, walk->geom.length / 100);
572 if (!ped_geometry_test_inside (&walk->geom, geom)
573 || length_error > max_length_error) {
574 char* part_size = ped_unit_format (disk->dev, walk->geom.length);
575 char* fs_size = ped_unit_format (disk->dev, geom->length);
576 PedExceptionOption choice;
578 choice = ped_exception_throw (
579 PED_EXCEPTION_WARNING,
580 PED_EXCEPTION_IGNORE_CANCEL,
581 _("Partition %d is %s, but the file system is "
583 walk->num, part_size, fs_size);
585 ped_free (part_size);
588 if (choice != PED_EXCEPTION_IGNORE)
597 * This function checks if a particular type of partition table supports
600 * \return 1 if \p disk_type supports \p feature, 0 otherwise.
603 ped_disk_type_check_feature (const PedDiskType* disk_type,
604 PedDiskTypeFeature feature)
606 return (disk_type->features & feature) != 0;
610 * Get the number of primary partitions.
613 ped_disk_get_primary_partition_count (PedDisk* disk)
618 PED_ASSERT (disk != NULL, return 0);
620 for (walk = disk->part_list; walk;
621 walk = ped_disk_next_partition (disk, walk)) {
622 if (ped_partition_is_active (walk)
623 && ! (walk->type & PED_PARTITION_LOGICAL))
631 * Get the highest partition number on \p disk.
634 ped_disk_get_last_partition_num (PedDisk* disk)
639 PED_ASSERT (disk != NULL, return 0);
641 for (walk = disk->part_list; walk;
642 walk = ped_disk_next_partition (disk, walk)) {
643 if (walk->num > highest)
651 * Get the maximum number of (primary) partitions the disk label supports.
653 * For example, MacIntosh partition maps can have different sizes,
654 * and accordingly support a different number of partitions.
657 ped_disk_get_max_primary_partition_count (const PedDisk* disk)
659 PED_ASSERT (disk->type != NULL, return 0);
660 PED_ASSERT (disk->type->ops->get_max_primary_partition_count != NULL,
663 return disk->type->ops->get_max_primary_partition_count (disk);
667 * \internal We turned a really nasty bureaucracy problem into an elegant maths
668 * problem :-) Basically, there are some constraints to a partition's
671 * (1) it must start and end on a "disk" block, determined by the disk label
672 * (not the hardware). (constraint represented by a PedAlignment)
674 * (2) if we're resizing a partition, we MIGHT need to keep each block aligned.
675 * Eg: if an ext2 file system has 4k blocks, then we can only move the start
676 * by a multiple of 4k. (constraint represented by a PedAlignment)
678 * (3) we need to keep the start and end within the device's physical
679 * boundaries. (constraint represented by a PedGeometry)
681 * Satisfying (1) and (2) simultaneously required a bit of fancy maths ;-) See
682 * ped_alignment_intersect()
684 * The application of these constraints is in disk_*.c's *_partition_align()
688 _partition_align (PedPartition* part, const PedConstraint* constraint)
690 const PedDiskType* disk_type;
692 PED_ASSERT (part != NULL, return 0);
693 PED_ASSERT (part->num != -1, return 0);
694 PED_ASSERT (part->disk != NULL, return 0);
695 disk_type = part->disk->type;
696 PED_ASSERT (disk_type != NULL, return 0);
697 PED_ASSERT (disk_type->ops->partition_align != NULL, return 0);
698 PED_ASSERT (part->disk->update_mode, return 0);
700 return disk_type->ops->partition_align (part, constraint);
704 _partition_enumerate (PedPartition* part)
706 const PedDiskType* disk_type;
708 PED_ASSERT (part != NULL, return 0);
709 PED_ASSERT (part->disk != NULL, return 0);
710 disk_type = part->disk->type;
711 PED_ASSERT (disk_type != NULL, return 0);
712 PED_ASSERT (disk_type->ops->partition_enumerate != NULL, return 0);
714 return disk_type->ops->partition_enumerate (part);
718 * Gives all the (active) partitions a number. It should preserve the numbers
719 * and orders as much as possible.
722 ped_disk_enumerate_partitions (PedDisk* disk)
728 PED_ASSERT (disk != NULL, return 0);
730 /* first "sort" already-numbered partitions. (e.g. if a logical partition
731 * is removed, then all logical partitions that were number higher MUST be
734 end = ped_disk_get_last_partition_num (disk);
735 for (i=1; i<=end; i++) {
736 walk = ped_disk_get_partition (disk, i);
738 if (!_partition_enumerate (walk))
743 /* now, number un-numbered partitions */
744 for (walk = disk->part_list; walk;
745 walk = ped_disk_next_partition (disk, walk)) {
746 if (ped_partition_is_active (walk) && walk->num == -1) {
747 if (!_partition_enumerate (walk))
756 _disk_remove_metadata (PedDisk* disk)
758 PedPartition* walk = NULL;
761 PED_ASSERT (disk != NULL, return 0);
763 next = ped_disk_next_partition (disk, walk);
768 next = ped_disk_next_partition (disk, next);
769 if (!next || next->type & PED_PARTITION_METADATA)
772 if (walk->type & PED_PARTITION_METADATA)
773 ped_disk_delete_partition (disk, walk);
779 _disk_alloc_metadata (PedDisk* disk)
781 PED_ASSERT (disk != NULL, return 0);
783 if (!disk->update_mode)
784 _disk_remove_metadata (disk);
786 return disk->type->ops->alloc_metadata (disk);
790 _disk_remove_freespace (PedDisk* disk)
795 walk = ped_disk_next_partition (disk, NULL);
796 for (; walk; walk = next) {
797 next = ped_disk_next_partition (disk, walk);
799 if (walk->type & PED_PARTITION_FREESPACE) {
800 _disk_raw_remove (disk, walk);
801 ped_partition_destroy (walk);
809 _alloc_extended_freespace (PedDisk* disk)
814 PedPartition* free_space;
815 PedPartition* extended_part;
817 extended_part = ped_disk_extended_partition (disk);
821 last_end = extended_part->geom.start;
824 for (walk = extended_part->part_list; walk; walk = walk->next) {
825 if (walk->geom.start > last_end + 1) {
826 free_space = ped_partition_new (
828 PED_PARTITION_FREESPACE
829 | PED_PARTITION_LOGICAL,
831 last_end + 1, walk->geom.start - 1);
832 _disk_raw_insert_before (disk, walk, free_space);
836 last_end = last->geom.end;
839 if (last_end < extended_part->geom.end) {
840 free_space = ped_partition_new (
842 PED_PARTITION_FREESPACE | PED_PARTITION_LOGICAL,
844 last_end + 1, extended_part->geom.end);
847 return _disk_raw_insert_after (disk, last, free_space);
849 extended_part->part_list = free_space;
856 _disk_alloc_freespace (PedDisk* disk)
861 PedPartition* free_space;
863 if (!_disk_remove_freespace (disk))
865 if (!_alloc_extended_freespace (disk))
871 for (walk = disk->part_list; walk; walk = walk->next) {
872 if (walk->geom.start > last_end + 1) {
873 free_space = ped_partition_new (disk,
874 PED_PARTITION_FREESPACE, NULL,
875 last_end + 1, walk->geom.start - 1);
876 _disk_raw_insert_before (disk, walk, free_space);
880 last_end = last->geom.end;
883 if (last_end < disk->dev->length - 1) {
884 free_space = ped_partition_new (disk,
885 PED_PARTITION_FREESPACE, NULL,
886 last_end + 1, disk->dev->length - 1);
888 return _disk_raw_insert_after (disk, last, free_space);
890 disk->part_list = free_space;
897 * Update mode: used when updating the internal representation of the partition
898 * table. In update mode, the metadata and freespace placeholder/virtual
899 * partitions are removed, making it much easier for various manipulation
903 _disk_push_update_mode (PedDisk* disk)
905 if (!disk->update_mode) {
907 _disk_check_sanity (disk);
910 _disk_remove_freespace (disk);
912 _disk_remove_metadata (disk);
915 _disk_check_sanity (disk);
923 _disk_pop_update_mode (PedDisk* disk)
925 PED_ASSERT (disk->update_mode, return);
927 if (disk->update_mode == 1) {
928 /* re-allocate metadata BEFORE leaving update mode, to prevent infinite
929 * recursion (metadata allocation requires update mode)
932 _disk_check_sanity (disk);
935 _disk_alloc_metadata (disk);
937 _disk_alloc_freespace (disk);
940 _disk_check_sanity (disk);
950 * \addtogroup PedPartition
952 * \brief Partition access.
958 _ped_partition_alloc (const PedDisk* disk, PedPartitionType type,
959 const PedFileSystemType* fs_type,
960 PedSector start, PedSector end)
964 PED_ASSERT (disk != NULL, return 0);
966 part = (PedPartition*) ped_malloc (sizeof (PedPartition));
973 part->disk = (PedDisk*) disk;
974 if (!ped_geometry_init (&part->geom, disk->dev, start, end - start + 1))
975 goto error_free_part;
979 part->part_list = NULL;
980 part->fs_type = fs_type;
991 _ped_partition_free (PedPartition* part)
997 _ped_partition_attempt_align (PedPartition* part,
998 const PedConstraint* external,
999 PedConstraint* internal)
1001 PedConstraint* intersection;
1002 PedGeometry* solution;
1004 intersection = ped_constraint_intersect (external, internal);
1005 ped_constraint_destroy (internal);
1009 solution = ped_constraint_solve_nearest (intersection, &part->geom);
1011 goto fail_free_intersection;
1012 ped_geometry_set (&part->geom, solution->start, solution->length);
1013 ped_geometry_destroy (solution);
1014 ped_constraint_destroy (intersection);
1017 fail_free_intersection:
1018 ped_constraint_destroy (intersection);
1024 * Create a new \link _PedPartition PedPartition \endlink on \p disk.
1026 * \param type One of \p PED_PARTITION_PRIMARY, \p PED_PARTITION_EXTENDED,
1027 * \p PED_PARTITION_LOGICAL.
1029 * \note The constructed partition is not added to <tt>disk</tt>'s
1030 * partition table. Use ped_disk_add_partition() to do this.
1032 * \return A new \link _PedPartition PedPartition \endlink object,
1035 * \throws PED_EXCEPTION_ERROR if \p type is \p EXTENDED or \p LOGICAL but the
1036 * label does not support this concept.
1039 ped_partition_new (const PedDisk* disk, PedPartitionType type,
1040 const PedFileSystemType* fs_type, PedSector start,
1043 int supports_extended;
1046 PED_ASSERT (disk != NULL, return NULL);
1047 PED_ASSERT (disk->type->ops->partition_new != NULL, return NULL);
1049 supports_extended = ped_disk_type_check_feature (disk->type,
1050 PED_DISK_TYPE_EXTENDED);
1052 if (!supports_extended
1053 && (type == PED_PARTITION_EXTENDED
1054 || type == PED_PARTITION_LOGICAL)) {
1055 ped_exception_throw (
1056 PED_EXCEPTION_ERROR,
1057 PED_EXCEPTION_CANCEL,
1058 _("%s disk labels do not support extended "
1064 part = disk->type->ops->partition_new (disk, type, fs_type, start, end);
1068 if (fs_type || part->type == PED_PARTITION_EXTENDED) {
1069 if (!ped_partition_set_system (part, fs_type))
1070 goto error_destroy_part;
1075 ped_partition_destroy (part);
1081 * Destroy a \link _PedPartition PedPartition \endlink object.
1083 * \note Should not be called on a partition that is in a partition table.
1084 * Use ped_disk_delete_partition() instead.
1087 ped_partition_destroy (PedPartition* part)
1089 PED_ASSERT (part != NULL, return);
1090 PED_ASSERT (part->disk != NULL, return);
1091 PED_ASSERT (part->disk->type->ops->partition_new != NULL, return);
1093 part->disk->type->ops->partition_destroy (part);
1098 * Return whether or not the partition is "active".
1100 * A partition is active if \p part->type is neither \p PED_PARTITION_METADATA
1101 * nor \p PED_PARTITION_FREE.
1104 ped_partition_is_active (const PedPartition* part)
1106 PED_ASSERT (part != NULL, return 0);
1108 return !(part->type & PED_PARTITION_FREESPACE
1109 || part->type & PED_PARTITION_METADATA);
1113 * Set the state (\c 1 or \c 0) of a flag on a partition.
1115 * Flags are disk label specific, although they have a global
1116 * "namespace": the flag PED_PARTITION_BOOT, for example, roughly means
1117 * "this" partition is bootable". But this means different things on different
1118 * disk labels (and may not be defined on some disk labels). For example,
1119 * on MS-DOS disk labels, there can only be one boot partition, and this
1120 * refers to the partition that will be booted from on startup. On PC98
1121 * disk labels, the user can choose from any bootable partition on startup.
1123 * \note It is an error to call this on an unavailable flag -- use
1124 * ped_partition_is_flag_available() to determine which flags are available
1125 * for a given disk label.
1127 * \throws PED_EXCEPTION_ERROR if the requested flag is not available for this
1131 ped_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1135 PED_ASSERT (part != NULL, return 0);
1136 PED_ASSERT (part->disk != NULL, return 0);
1137 PED_ASSERT (ped_partition_is_active (part), return 0);
1139 ops = part->disk->type->ops;
1140 PED_ASSERT (ops->partition_set_flag != NULL, return 0);
1141 PED_ASSERT (ops->partition_is_flag_available != NULL, return 0);
1143 if (!ops->partition_is_flag_available (part, flag)) {
1144 ped_exception_throw (
1145 PED_EXCEPTION_ERROR,
1146 PED_EXCEPTION_CANCEL,
1147 "The flag '%s' is not available for %s disk labels.",
1148 ped_partition_flag_get_name (flag),
1149 part->disk->type->name);
1153 return ops->partition_set_flag (part, flag, state);
1157 * Get the state (\c 1 or \c 0) of a flag on a partition.
1159 * See ped_partition_set_flag() for conditions that must hold.
1161 * \todo Where's the check for flag availability?
1164 ped_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1166 PED_ASSERT (part != NULL, return 0);
1167 PED_ASSERT (part->disk != NULL, return 0);
1168 PED_ASSERT (part->disk->type->ops->partition_get_flag != NULL,
1170 PED_ASSERT (ped_partition_is_active (part), return 0);
1172 return part->disk->type->ops->partition_get_flag (part, flag);
1176 * Check whether a given flag is available on a partition.
1178 * \return \c 1 if the flag is available.
1181 ped_partition_is_flag_available (const PedPartition* part,
1182 PedPartitionFlag flag)
1184 PED_ASSERT (part != NULL, return 0);
1185 PED_ASSERT (part->disk != NULL, return 0);
1186 PED_ASSERT (part->disk->type->ops->partition_is_flag_available != NULL,
1188 PED_ASSERT (ped_partition_is_active (part), return 0);
1190 return part->disk->type->ops->partition_is_flag_available (part, flag);
1194 * Sets the system type on the partition to \p fs_type.
1196 * \note The file system may be opened, to get more information about the
1197 * file system, e.g. to determine if it's FAT16 or FAT32.
1199 * \return \c 0 on failure.
1202 ped_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1205 const PedDiskType* disk_type;
1207 PED_ASSERT (part != NULL, return 0);
1208 PED_ASSERT (ped_partition_is_active (part), return 0);
1209 PED_ASSERT (part->disk != NULL, return 0);
1210 disk_type = part->disk->type;
1211 PED_ASSERT (disk_type != NULL, return 0);
1212 PED_ASSERT (disk_type->ops != NULL, return 0);
1213 PED_ASSERT (disk_type->ops->partition_set_system != NULL, return 0);
1215 return disk_type->ops->partition_set_system (part, fs_type);
1219 _assert_partition_name_feature (const PedDiskType* disk_type)
1221 if (!ped_disk_type_check_feature (
1222 disk_type, PED_DISK_TYPE_PARTITION_NAME)) {
1223 ped_exception_throw (
1224 PED_EXCEPTION_ERROR,
1225 PED_EXCEPTION_CANCEL,
1226 "%s disk labels do not support partition names.",
1234 * Sets the name of a partition.
1236 * \note This will only work if the disk label supports it.
1239 * ped_disk_type_check_feature (part->disk->type, PED_DISK_TYPE_PARTITION_NAME);
1241 * to check whether this feature is enabled for a label.
1243 * \note \p name will not be modified by libparted. It can be freed
1244 * by the caller immediately after ped_partition_set_name() is called.
1246 * \return \c 1 on success, \c 0 otherwise.
1249 ped_partition_set_name (PedPartition* part, const char* name)
1251 PED_ASSERT (part != NULL, return 0);
1252 PED_ASSERT (part->disk != NULL, return 0);
1253 PED_ASSERT (ped_partition_is_active (part), return 0);
1254 PED_ASSERT (name != NULL, return 0);
1256 if (!_assert_partition_name_feature (part->disk->type))
1259 PED_ASSERT (part->disk->type->ops->partition_set_name != NULL,
1261 part->disk->type->ops->partition_set_name (part, name);
1266 * Returns the name of a partition \p part. This will only work if the disk
1267 * label supports it.
1269 * \note The returned string should not be modified. It should
1270 * not be referenced after the partition is destroyed.
1273 ped_partition_get_name (const PedPartition* part)
1275 PED_ASSERT (part != NULL, return NULL);
1276 PED_ASSERT (part->disk != NULL, return 0);
1277 PED_ASSERT (ped_partition_is_active (part), return 0);
1279 if (!_assert_partition_name_feature (part->disk->type))
1282 PED_ASSERT (part->disk->type->ops->partition_get_name != NULL,
1284 return part->disk->type->ops->partition_get_name (part);
1290 * \addtogroup PedDisk
1296 ped_disk_extended_partition (const PedDisk* disk)
1300 PED_ASSERT (disk != NULL, return 0);
1302 for (walk = disk->part_list; walk; walk = walk->next) {
1303 if (walk->type == PED_PARTITION_EXTENDED)
1310 * Return the next partition after \p part on \p disk. If \p part is \c NULL,
1311 * return the first partition. If \p part is the last partition, returns
1312 * \c NULL. If \p part is an extended partition, returns the first logical
1313 * partition. If this is called repeatedly passing the return value as \p part,
1314 * a depth-first traversal is executed.
1316 * \return The next partition, \c NULL if no more partitions left.
1319 ped_disk_next_partition (const PedDisk* disk, const PedPartition* part)
1321 PED_ASSERT (disk != NULL, return 0);
1324 return disk->part_list;
1325 if (part->type == PED_PARTITION_EXTENDED)
1326 return part->part_list ? part->part_list : part->next;
1329 if (part->type & PED_PARTITION_LOGICAL)
1330 return ped_disk_extended_partition (disk)->next;
1338 _disk_check_sanity (PedDisk* disk)
1342 PED_ASSERT (disk != NULL, return 0);
1344 for (walk = disk->part_list; walk; walk = walk->next) {
1345 PED_ASSERT (!(walk->type & PED_PARTITION_LOGICAL), return 0);
1346 PED_ASSERT (!walk->prev || walk->prev->next == walk, return 0);
1349 if (!ped_disk_extended_partition (disk))
1352 for (walk = ped_disk_extended_partition (disk)->part_list; walk;
1353 walk = walk->next) {
1354 PED_ASSERT (walk->type & PED_PARTITION_LOGICAL, return 0);
1356 PED_ASSERT (walk->prev->next == walk, return 0);
1363 * Returns the partition numbered \p num.
1365 * \return \c NULL if the specified partition does not exist.
1368 ped_disk_get_partition (const PedDisk* disk, int num)
1372 PED_ASSERT (disk != NULL, return 0);
1374 for (walk = disk->part_list; walk;
1375 walk = ped_disk_next_partition (disk, walk)) {
1376 if (walk->num == num && !(walk->type & PED_PARTITION_FREESPACE))
1384 * Returns the partition that contains sect. If sect lies within a logical
1385 * partition, then the logical partition is returned (not the extended
1389 ped_disk_get_partition_by_sector (const PedDisk* disk, PedSector sect)
1393 PED_ASSERT (disk != NULL, return 0);
1395 for (walk = disk->part_list; walk;
1396 walk = ped_disk_next_partition (disk, walk)) {
1397 if (ped_geometry_test_sector_inside (&walk->geom, sect)
1398 && walk->type != PED_PARTITION_EXTENDED)
1402 /* should never get here, unless sect is outside of disk's useable
1403 * part, or we're in "update mode", and the free space place-holders
1404 * have been removed with _disk_remove_freespace()
1409 /* I'm beginning to agree with Sedgewick :-/ */
1411 _disk_raw_insert_before (PedDisk* disk, PedPartition* loc, PedPartition* part)
1413 PED_ASSERT (disk != NULL, return 0);
1414 PED_ASSERT (loc != NULL, return 0);
1415 PED_ASSERT (part != NULL, return 0);
1417 part->prev = loc->prev;
1420 part->prev->next = part;
1422 if (loc->type & PED_PARTITION_LOGICAL)
1423 ped_disk_extended_partition (disk)->part_list = part;
1425 disk->part_list = part;
1433 _disk_raw_insert_after (PedDisk* disk, PedPartition* loc, PedPartition* part)
1435 PED_ASSERT (disk != NULL, return 0);
1436 PED_ASSERT (loc != NULL, return 0);
1437 PED_ASSERT (part != NULL, return 0);
1440 part->next = loc->next;
1442 loc->next->prev = part;
1449 _disk_raw_remove (PedDisk* disk, PedPartition* part)
1451 PED_ASSERT (disk != NULL, return 0);
1452 PED_ASSERT (part != NULL, return 0);
1455 part->prev->next = part->next;
1457 part->next->prev = part->prev;
1459 if (part->type & PED_PARTITION_LOGICAL) {
1460 ped_disk_extended_partition (disk)->part_list
1463 disk->part_list = part->next;
1466 part->next->prev = NULL;
1476 _disk_raw_add (PedDisk* disk, PedPartition* part)
1480 PedPartition* ext_part;
1482 PED_ASSERT (disk->update_mode, return 0);
1484 ext_part = ped_disk_extended_partition (disk);
1487 walk = (part->type & PED_PARTITION_LOGICAL) ?
1488 ext_part->part_list : disk->part_list;
1490 for (; walk; last = walk, walk = walk->next) {
1491 if (walk->geom.start > part->geom.end)
1496 return _disk_raw_insert_before (disk, walk, part);
1499 return _disk_raw_insert_after (disk, last, part);
1501 if (part->type & PED_PARTITION_LOGICAL)
1502 ext_part->part_list = part;
1504 disk->part_list = part;
1511 static PedConstraint*
1512 _partition_get_overlap_constraint (PedPartition* part, PedGeometry* geom)
1514 PedSector min_start;
1517 PedGeometry free_space;
1519 PED_ASSERT (part->disk->update_mode, return NULL);
1520 PED_ASSERT (part->geom.dev == geom->dev, return NULL);
1522 if (part->type & PED_PARTITION_LOGICAL) {
1523 PedPartition* ext_part;
1525 ext_part = ped_disk_extended_partition (part->disk);
1526 PED_ASSERT (ext_part != NULL, return NULL);
1528 min_start = ext_part->geom.start;
1529 max_end = ext_part->geom.end;
1530 walk = ext_part->part_list;
1533 max_end = part->disk->dev->length - 1;
1534 walk = part->disk->part_list;
1538 && (walk->geom.start < geom->start
1539 || min_start >= walk->geom.start)) {
1541 min_start = walk->geom.end + 1;
1549 max_end = walk->geom.start - 1;
1551 if (min_start >= max_end)
1554 ped_geometry_init (&free_space, part->disk->dev,
1555 min_start, max_end - min_start + 1);
1556 return ped_constraint_new_from_max (&free_space);
1560 * Returns \c 0 if the partition, \p part overlaps with any partitions on the
1561 * \p disk. The geometry of \p part is taken to be \p geom, NOT \p part->geom
1562 * (the idea here is to check if \p geom is valid, before changing \p part).
1564 * This is useful for seeing if a resized partitions new geometry is going to
1565 * fit, without the existing geomtry getting in the way.
1567 * Note: overlap with an extended partition is also allowed, provided that
1568 * \p geom lies completely inside the extended partition.
1571 _disk_check_part_overlaps (PedDisk* disk, PedPartition* part)
1575 PED_ASSERT (disk != NULL, return 0);
1576 PED_ASSERT (part != NULL, return 0);
1578 for (walk = ped_disk_next_partition (disk, NULL); walk;
1579 walk = ped_disk_next_partition (disk, walk)) {
1580 if (walk->type & PED_PARTITION_FREESPACE)
1584 if (part->type & PED_PARTITION_EXTENDED
1585 && walk->type & PED_PARTITION_LOGICAL)
1588 if (ped_geometry_test_overlap (&walk->geom, &part->geom)) {
1589 if (walk->type & PED_PARTITION_EXTENDED
1590 && part->type & PED_PARTITION_LOGICAL
1591 && ped_geometry_test_inside (&walk->geom,
1602 _partition_check_basic_sanity (PedDisk* disk, PedPartition* part)
1604 PedPartition* ext_part = ped_disk_extended_partition (disk);
1606 PED_ASSERT (part->disk == disk, return 0);
1608 PED_ASSERT (part->geom.start >= 0, return 0);
1609 PED_ASSERT (part->geom.end < disk->dev->length, return 0);
1610 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1612 if (!ped_disk_type_check_feature (disk->type, PED_DISK_TYPE_EXTENDED)
1613 && (part->type == PED_PARTITION_EXTENDED
1614 || part->type == PED_PARTITION_LOGICAL)) {
1615 ped_exception_throw (
1616 PED_EXCEPTION_ERROR,
1617 PED_EXCEPTION_CANCEL,
1618 _("%s disk labels don't support logical or extended "
1624 if (ped_partition_is_active (part)
1625 && ! (part->type & PED_PARTITION_LOGICAL)) {
1626 if (ped_disk_get_primary_partition_count (disk) + 1
1627 > ped_disk_get_max_primary_partition_count (disk)) {
1628 ped_exception_throw (
1629 PED_EXCEPTION_ERROR,
1630 PED_EXCEPTION_CANCEL,
1631 _("Too many primary partitions."));
1636 if ((part->type & PED_PARTITION_LOGICAL) && !ext_part) {
1637 ped_exception_throw (
1638 PED_EXCEPTION_ERROR,
1639 PED_EXCEPTION_CANCEL,
1640 _("Can't add a logical partition to %s, because "
1641 "there is no extended partition."),
1650 _check_extended_partition (PedDisk* disk, PedPartition* part)
1653 PedPartition* ext_part;
1655 PED_ASSERT (disk != NULL, return 0);
1656 ext_part = ped_disk_extended_partition (disk);
1657 if (!ext_part) ext_part = part;
1658 PED_ASSERT (ext_part != NULL, return 0);
1660 if (part != ext_part) {
1661 ped_exception_throw (
1662 PED_EXCEPTION_ERROR,
1663 PED_EXCEPTION_CANCEL,
1664 _("Can't have more than one extended partition on %s."),
1669 for (walk = ext_part->part_list; walk; walk = walk->next) {
1670 if (!ped_geometry_test_inside (&ext_part->geom, &walk->geom)) {
1671 ped_exception_throw (
1672 PED_EXCEPTION_ERROR,
1673 PED_EXCEPTION_CANCEL,
1674 _("Can't have logical partitions outside of "
1675 "the extended partition."));
1683 _check_partition (PedDisk* disk, PedPartition* part)
1685 PedPartition* ext_part = ped_disk_extended_partition (disk);
1687 PED_ASSERT (part->geom.start <= part->geom.end, return 0);
1689 if (part->type == PED_PARTITION_EXTENDED) {
1690 if (!_check_extended_partition (disk, part))
1694 if (part->type & PED_PARTITION_LOGICAL
1695 && !ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1696 ped_exception_throw (
1697 PED_EXCEPTION_ERROR,
1698 PED_EXCEPTION_CANCEL,
1699 _("Can't have a logical partition outside of the "
1700 "extended partition on %s."),
1705 if (!_disk_check_part_overlaps (disk, part)) {
1706 ped_exception_throw (
1707 PED_EXCEPTION_ERROR,
1708 PED_EXCEPTION_CANCEL,
1709 _("Can't have overlapping partitions."));
1713 if (! (part->type & PED_PARTITION_LOGICAL)
1714 && ext_part && ext_part != part
1715 && ped_geometry_test_inside (&ext_part->geom, &part->geom)) {
1716 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
1717 _("Can't have a primary partition inside an extended "
1726 * Adds PedPartition \p part to PedPartition \p disk.
1728 * \warning The partition's geometry may be changed, subject to \p constraint.
1729 * You could set \p constraint to <tt>ped_constraint_exact(&part->geom)</tt>,
1730 * but many partition table schemes have special requirements on the start
1731 * and end of partitions. Therefore, having an overly strict constraint
1732 * will probably mean that this function will fail (in which
1733 * case \p part will be left unmodified)
1734 * \p part is assigned a number (\p part->num) in this process.
1736 * \return \c 0 on failure.
1739 ped_disk_add_partition (PedDisk* disk, PedPartition* part,
1740 const PedConstraint* constraint)
1742 PedConstraint* overlap_constraint = NULL;
1743 PedConstraint* constraints = NULL;
1745 PED_ASSERT (disk != NULL, return 0);
1746 PED_ASSERT (part != NULL, return 0);
1748 if (!_partition_check_basic_sanity (disk, part))
1751 _disk_push_update_mode (disk);
1753 if (ped_partition_is_active (part)) {
1755 = _partition_get_overlap_constraint (part, &part->geom);
1756 constraints = ped_constraint_intersect (overlap_constraint,
1759 if (!constraints && constraint) {
1760 ped_exception_throw (
1761 PED_EXCEPTION_ERROR,
1762 PED_EXCEPTION_CANCEL,
1763 _("Can't have overlapping partitions."));
1767 if (!_partition_enumerate (part))
1769 if (!_partition_align (part, constraints))
1772 if (!_check_partition (disk, part))
1774 if (!_disk_raw_add (disk, part))
1777 ped_constraint_destroy (overlap_constraint);
1778 ped_constraint_destroy (constraints);
1779 _disk_pop_update_mode (disk);
1781 if (!_disk_check_sanity (disk))
1787 ped_constraint_destroy (overlap_constraint);
1788 ped_constraint_destroy (constraints);
1789 _disk_pop_update_mode (disk);
1794 * Removes PedPartition \p part from PedDisk \p disk.
1796 * If \p part is an extended partition, it must not contain any logical
1797 * partitions. \p part is *NOT* destroyed. The caller must call
1798 * ped_partition_destroy(), or use ped_disk_delete_partition() instead.
1800 * \return \c 0 on error.
1803 ped_disk_remove_partition (PedDisk* disk, PedPartition* part)
1805 PED_ASSERT (disk != NULL, return 0);
1806 PED_ASSERT (part != NULL, return 0);
1808 _disk_push_update_mode (disk);
1809 PED_ASSERT (part->part_list == NULL, goto error);
1810 _disk_raw_remove (disk, part);
1811 _disk_pop_update_mode (disk);
1812 ped_disk_enumerate_partitions (disk);
1816 _disk_pop_update_mode (disk);
1821 ped_disk_delete_all_logical (PedDisk* disk);
1824 * Removes \p part from \p disk, and destroys \p part.
1826 * \return \c 0 on failure.
1829 ped_disk_delete_partition (PedDisk* disk, PedPartition* part)
1831 PED_ASSERT (disk != NULL, return 0);
1832 PED_ASSERT (part != NULL, return 0);
1834 _disk_push_update_mode (disk);
1835 if (part->type == PED_PARTITION_EXTENDED)
1836 ped_disk_delete_all_logical (disk);
1837 ped_disk_remove_partition (disk, part);
1838 ped_partition_destroy (part);
1839 _disk_pop_update_mode (disk);
1845 ped_disk_delete_all_logical (PedDisk* disk)
1849 PedPartition* ext_part;
1851 PED_ASSERT (disk != NULL, return 0);
1852 ext_part = ped_disk_extended_partition (disk);
1853 PED_ASSERT (ext_part != NULL, return 0);
1855 for (walk = ext_part->part_list; walk; walk = next) {
1858 if (!ped_disk_delete_partition (disk, walk))
1865 * Removes and destroys all partitions on \p disk.
1867 * \return \c 0 on failure.
1870 ped_disk_delete_all (PedDisk* disk)
1875 PED_ASSERT (disk != NULL, return 0);
1877 _disk_push_update_mode (disk);
1879 for (walk = disk->part_list; walk; walk = next) {
1882 if (!ped_disk_delete_partition (disk, walk))
1886 _disk_pop_update_mode (disk);
1892 * Sets the geometry of \p part (i.e. change a partitions location). This can
1893 * fail for many reasons, e.g. can't overlap with other partitions. If it
1894 * does fail, \p part will remain unchanged. Returns \c 0 on failure. \p part's
1895 * geometry may be set to something different from \p start and \p end subject
1898 * \warning The constraint warning from ped_disk_add_partition() applies.
1900 * \note this function does not modify the contents of the partition. You need
1901 * to call ped_file_system_resize() separately.
1904 ped_disk_set_partition_geom (PedDisk* disk, PedPartition* part,
1905 const PedConstraint* constraint,
1906 PedSector start, PedSector end)
1908 PedConstraint* overlap_constraint = NULL;
1909 PedConstraint* constraints = NULL;
1910 PedGeometry old_geom;
1911 PedGeometry new_geom;
1913 PED_ASSERT (disk != NULL, return 0);
1914 PED_ASSERT (part != NULL, return 0);
1915 PED_ASSERT (part->disk == disk, return 0);
1917 old_geom = part->geom;
1918 ped_geometry_init (&new_geom, part->geom.dev, start, end - start + 1);
1920 _disk_push_update_mode (disk);
1923 = _partition_get_overlap_constraint (part, &new_geom);
1924 constraints = ped_constraint_intersect (overlap_constraint, constraint);
1925 if (!constraints && constraint) {
1926 ped_exception_throw (
1927 PED_EXCEPTION_ERROR,
1928 PED_EXCEPTION_CANCEL,
1929 _("Can't have overlapping partitions."));
1930 goto error_pop_update_mode;
1933 part->geom = new_geom;
1934 if (!_partition_align (part, constraints))
1935 goto error_pop_update_mode;
1936 if (!_check_partition (disk, part))
1937 goto error_pop_update_mode;
1939 /* remove and add, to ensure the ordering gets updated if necessary */
1940 _disk_raw_remove (disk, part);
1941 _disk_raw_add (disk, part);
1943 _disk_pop_update_mode (disk);
1945 ped_constraint_destroy (overlap_constraint);
1946 ped_constraint_destroy (constraints);
1949 error_pop_update_mode:
1950 _disk_pop_update_mode (disk);
1952 ped_constraint_destroy (overlap_constraint);
1953 ped_constraint_destroy (constraints);
1954 part->geom = old_geom;
1959 * Grow PedPartition \p part geometry to the maximum possible subject to
1960 * \p constraint. The new geometry will be a superset of the old geometry.
1962 * \return 0 on failure
1965 ped_disk_maximize_partition (PedDisk* disk, PedPartition* part,
1966 const PedConstraint* constraint)
1968 PedGeometry old_geom;
1969 PedSector global_min_start;
1970 PedSector global_max_end;
1971 PedSector new_start;
1973 PedPartition* ext_part = ped_disk_extended_partition (disk);
1974 PedConstraint* constraint_any;
1976 PED_ASSERT (disk != NULL, return 0);
1977 PED_ASSERT (part != NULL, return 0);
1979 if (part->type & PED_PARTITION_LOGICAL) {
1980 PED_ASSERT (ext_part != NULL, return 0);
1981 global_min_start = ext_part->geom.start;
1982 global_max_end = ext_part->geom.end;
1984 global_min_start = 0;
1985 global_max_end = disk->dev->length - 1;
1988 old_geom = part->geom;
1990 _disk_push_update_mode (disk);
1993 new_start = part->prev->geom.end + 1;
1995 new_start = global_min_start;
1998 new_end = part->next->geom.start - 1;
2000 new_end = global_max_end;
2002 if (!ped_disk_set_partition_geom (disk, part, constraint, new_start,
2006 _disk_pop_update_mode (disk);
2010 constraint_any = ped_constraint_any (disk->dev);
2011 ped_disk_set_partition_geom (disk, part, constraint_any,
2012 old_geom.start, old_geom.end);
2013 ped_constraint_destroy (constraint_any);
2014 _disk_pop_update_mode (disk);
2019 * Get the maximum geometry \p part can be grown to, subject to
2022 * \return \c NULL on failure.
2025 ped_disk_get_max_partition_geometry (PedDisk* disk, PedPartition* part,
2026 const PedConstraint* constraint)
2028 PedGeometry old_geom;
2029 PedGeometry* max_geom;
2030 PedConstraint* constraint_exact;
2032 PED_ASSERT(disk != NULL, return NULL);
2033 PED_ASSERT(part != NULL, return NULL);
2034 PED_ASSERT(ped_partition_is_active (part), return NULL);
2036 old_geom = part->geom;
2037 if (!ped_disk_maximize_partition (disk, part, constraint))
2039 max_geom = ped_geometry_duplicate (&part->geom);
2041 constraint_exact = ped_constraint_exact (&old_geom);
2042 ped_disk_set_partition_geom (disk, part, constraint_exact,
2043 old_geom.start, old_geom.end);
2044 ped_constraint_destroy (constraint_exact);
2046 /* this assertion should never fail, because the old
2047 * geometry was valid
2049 PED_ASSERT (ped_geometry_test_equal (&part->geom, &old_geom),
2056 * Reduce the size of the extended partition to a minimum while still wrapping
2057 * its logical partitions. If there are no logical partitions, remove the
2058 * extended partition.
2060 * \return 0 on failure.
2063 ped_disk_minimize_extended_partition (PedDisk* disk)
2065 PedPartition* first_logical;
2066 PedPartition* last_logical;
2068 PedPartition* ext_part;
2069 PedConstraint* constraint;
2072 PED_ASSERT (disk != NULL, return 0);
2074 ext_part = ped_disk_extended_partition (disk);
2078 _disk_push_update_mode (disk);
2080 first_logical = ext_part->part_list;
2081 if (!first_logical) {
2082 _disk_pop_update_mode (disk);
2083 return ped_disk_delete_partition (disk, ext_part);
2086 for (walk = first_logical; walk->next; walk = walk->next);
2087 last_logical = walk;
2089 constraint = ped_constraint_any (disk->dev);
2090 status = ped_disk_set_partition_geom (disk, ext_part, constraint,
2091 first_logical->geom.start,
2092 last_logical->geom.end);
2093 ped_constraint_destroy (constraint);
2095 _disk_pop_update_mode (disk);
2104 * \addtogroup PedPartition
2110 * Returns a name that seems mildly appropriate for a partition type \p type.
2112 * Eg, if you pass (PED_PARTITION_LOGICAL & PED_PARTITION_FREESPACE), it
2113 * will return "free". This isn't to be taken too seriously - it's just
2114 * useful for user interfaces, so you can show the user something ;-)
2116 * \note The returned string will be in English. However,
2117 * translations are provided, so the caller can call
2118 * dgettext("parted", RESULT) on the result.
2122 ped_partition_type_get_name (PedPartitionType type)
2124 if (type & PED_PARTITION_METADATA)
2125 return N_("metadata");
2126 else if (type & PED_PARTITION_FREESPACE)
2128 else if (type & PED_PARTITION_EXTENDED)
2129 return N_("extended");
2130 else if (type & PED_PARTITION_LOGICAL)
2131 return N_("logical");
2133 return N_("primary");
2138 * Returns a name for a \p flag, e.g. PED_PARTITION_BOOT will return "boot".
2140 * \note The returned string will be in English. However,
2141 * translations are provided, so the caller can call
2142 * dgettext("parted", RESULT) on the result.
2145 ped_partition_flag_get_name (PedPartitionFlag flag)
2148 case PED_PARTITION_BOOT:
2150 case PED_PARTITION_ROOT:
2152 case PED_PARTITION_SWAP:
2154 case PED_PARTITION_HIDDEN:
2155 return N_("hidden");
2156 case PED_PARTITION_RAID:
2158 case PED_PARTITION_LVM:
2160 case PED_PARTITION_LBA:
2162 case PED_PARTITION_HPSERVICE:
2163 return N_("hp-service");
2164 case PED_PARTITION_PALO:
2166 case PED_PARTITION_PREP:
2168 case PED_PARTITION_MSFT_RESERVED:
2169 return N_("msftres");
2172 ped_exception_throw (
2174 PED_EXCEPTION_CANCEL,
2175 _("Unknown partition flag, %d."),
2182 * Iterates through all flags.
2184 * ped_partition_flag_next(0) returns the first flag
2186 * \return the next flag, or 0 if there are no more flags
2189 ped_partition_flag_next (PedPartitionFlag flag)
2191 return (flag + 1) % (PED_PARTITION_LAST_FLAG + 1);
2195 * Returns the flag associated with \p name.
2197 * \p name can be the English
2198 * string, or the translation for the native language.
2201 ped_partition_flag_get_by_name (const char* name)
2203 PedPartitionFlag flag;
2204 const char* flag_name;
2206 for (flag = ped_partition_flag_next (0); flag;
2207 flag = ped_partition_flag_next (flag)) {
2208 flag_name = ped_partition_flag_get_name (flag);
2209 if (strcasecmp (name, flag_name) == 0
2210 || strcasecmp (name, _(flag_name)) == 0)
2218 ped_partition_print (PedPartition* part)
2220 PED_ASSERT (part != NULL, return);
2222 printf (" %-10s %02d (%d->%d)\n",
2223 ped_partition_type_get_name (part->type),
2225 (int) part->geom.start, (int) part->geom.end);
2231 * \addtogroup PedDisk
2237 * Prints a summary of disk's partitions. Useful for debugging.
2240 ped_disk_print (PedDisk* disk)
2244 PED_ASSERT (disk != NULL, return);
2246 for (part = disk->part_list; part;
2247 part = ped_disk_next_partition (disk, part))
2248 ped_partition_print (part);