10 * @short_description: generic label independent partition abstraction
12 * The fdisk_partition provides label independent abstraction. The partitions
13 * are not directly connected with partition table (label) data. Any change to
14 * fdisk_partition does not affects in-memory or on-disk label data.
16 * The fdisk_partition is possible to use as a template for
17 * fdisk_add_partition() or fdisk_set_partition() operations.
20 static void init_partition(struct fdisk_partition
*pa
)
22 FDISK_INIT_UNDEF(pa
->size
);
23 FDISK_INIT_UNDEF(pa
->start
);
24 FDISK_INIT_UNDEF(pa
->partno
);
25 FDISK_INIT_UNDEF(pa
->parent_partno
);
26 FDISK_INIT_UNDEF(pa
->boot
);
28 INIT_LIST_HEAD(&pa
->parts
);
32 * fdisk_new_partition:
34 * Returns: new instance.
36 struct fdisk_partition
*fdisk_new_partition(void)
38 struct fdisk_partition
*pa
= calloc(1, sizeof(*pa
));
42 DBG(PART
, ul_debugobj(pa
, "alloc"));
47 * fdisk_reset_partition:
50 * Resets partition content.
52 void fdisk_reset_partition(struct fdisk_partition
*pa
)
59 DBG(PART
, ul_debugobj(pa
, "reset"));
62 fdisk_unref_parttype(pa
->type
);
67 memset(pa
, 0, sizeof(*pa
));
74 * fdisk_ref_partition:
75 * @pa: partition pointer
77 * Incremparts reference counter.
79 void fdisk_ref_partition(struct fdisk_partition
*pa
)
86 * fdisk_unref_partition:
87 * @pa: partition pointer
89 * De-incremparts reference counter, on zero the @pa is automatically
92 void fdisk_unref_partition(struct fdisk_partition
*pa
)
98 if (pa
->refcount
<= 0) {
99 fdisk_reset_partition(pa
);
100 list_del(&pa
->parts
);
101 DBG(PART
, ul_debugobj(pa
, "free"));
107 * fdisk_partition_set_start:
109 * @off: offset in sectors, maximal is UINT64_MAX-1
111 * Note that zero is valid offset too. Use fdisk_partition_unset_start() to
112 * undefine the offset.
114 * Returns: 0 on success, <0 on error.
116 int fdisk_partition_set_start(struct fdisk_partition
*pa
, fdisk_sector_t off
)
120 if (FDISK_IS_UNDEF(off
))
127 * fdisk_partition_unset_start:
130 * Sets the size as undefined. See fdisk_partition_has_start().
132 * Returns: 0 on success, <0 on error.
134 int fdisk_partition_unset_start(struct fdisk_partition
*pa
)
138 FDISK_INIT_UNDEF(pa
->start
);
143 * fdisk_partition_get_start:
146 * The zero is also valid offset. The function may return random undefined
147 * value when start offset is undefined (for example after
148 * fdisk_partition_unset_start()). Always use fdisk_partition_has_start() to be
149 * sure that you work with valid numbers.
151 * Returns: start offset in sectors
153 fdisk_sector_t
fdisk_partition_get_start(struct fdisk_partition
*pa
)
159 * fdisk_partition_has_start:
164 int fdisk_partition_has_start(struct fdisk_partition
*pa
)
166 return pa
&& !FDISK_IS_UNDEF(pa
->start
);
171 * fdisk_partition_cmp_start:
175 * Compares partitions according to start offset, See fdisk_table_sort_partitions().
177 * Return: 0 if the same, <0 if @b greater, >0 if @a greater.
179 int fdisk_partition_cmp_start(struct fdisk_partition
*a
,
180 struct fdisk_partition
*b
)
182 int no_a
= FDISK_IS_UNDEF(a
->start
),
183 no_b
= FDISK_IS_UNDEF(b
->start
);
192 return cmp_numbers(a
->start
, b
->start
);
196 * fdisk_partition_start_follow_default
200 * When @pa used as a template for fdisk_add_partition() when force label driver
201 * to use the first possible space for the new partition.
203 * Returns: 0 on success, <0 on error.
205 int fdisk_partition_start_follow_default(struct fdisk_partition
*pa
, int enable
)
209 pa
->start_follow_default
= enable
? 1 : 0;
214 * fdisk_partition_start_is_default:
217 * See fdisk_partition_start_follow_default().
219 * Returns: 1 if the partition follows default
221 int fdisk_partition_start_is_default(struct fdisk_partition
*pa
)
224 return pa
->start_follow_default
;
229 * fdisk_partition_set_size:
231 * @sz: size in sectors, maximal is UIN64_MAX-1
233 * Note that zero is valid size too. Use fdisk_partition_unset_size() to
236 * Returns: 0 on success, <0 on error.
238 int fdisk_partition_set_size(struct fdisk_partition
*pa
, fdisk_sector_t sz
)
242 if (FDISK_IS_UNDEF(sz
))
249 * fdisk_partition_unset_size:
252 * Sets the size as undefined. See fdisk_partition_has_size().
254 * Returns: 0 on success, <0 on error.
256 int fdisk_partition_unset_size(struct fdisk_partition
*pa
)
260 FDISK_INIT_UNDEF(pa
->size
);
265 * fdisk_partition_get_size:
268 * The zero is also valid size. The function may return random undefined
269 * value when size is undefined (for example after fdisk_partition_unset_size()).
270 * Always use fdisk_partition_has_size() to be sure that you work with valid
273 * Returns: size offset in sectors
275 fdisk_sector_t
fdisk_partition_get_size(struct fdisk_partition
*pa
)
281 * fdisk_partition_has_size:
286 int fdisk_partition_has_size(struct fdisk_partition
*pa
)
288 return pa
&& !FDISK_IS_UNDEF(pa
->size
);
292 * fdisk_partition_size_explicit:
296 * By default libfdisk aligns the size when add the new partition (by
297 * fdisk_add_partition()). If you want to disable this functionality use
300 * Returns: 0 on success, <0 on error.
302 int fdisk_partition_size_explicit(struct fdisk_partition
*pa
, int enable
)
306 pa
->size_explicit
= enable
? 1 : 0;
311 * fdisk_partition_set_partno:
313 * @num: partitin number (0 is the first partition, maximal is SIZE_MAX-1)
315 * Note that zero is valid partno too. Use fdisk_partition_unset_partno() to
316 * undefine the partno.
318 * Returns: 0 on success, <0 on error.
320 int fdisk_partition_set_partno(struct fdisk_partition
*pa
, size_t num
)
324 if (FDISK_IS_UNDEF(num
))
331 * fdisk_partition_unset_partno:
334 * Sets the partno as undefined. See fdisk_partition_has_partno().
336 * Returns: 0 on success, <0 on error.
338 int fdisk_partition_unset_partno(struct fdisk_partition
*pa
)
342 FDISK_INIT_UNDEF(pa
->partno
);
347 * fdisk_partition_get_partno:
350 * The zero is also valid partition number. The function may return random
351 * value when partno is undefined (for example after fdisk_partition_unset_partno()).
352 * Always use fdisk_partition_has_partno() to be sure that you work with valid
355 * Returns: partition number (0 is the first partition)
357 size_t fdisk_partition_get_partno(struct fdisk_partition
*pa
)
363 * fdisk_partition_has_partno:
368 int fdisk_partition_has_partno(struct fdisk_partition
*pa
)
370 return pa
&& !FDISK_IS_UNDEF(pa
->partno
);
375 * fdisk_partition_cmp_partno:
379 * Compares partitions according to partition number See fdisk_table_sort_partitions().
381 * Return: 0 if the same, <0 if @b greater, >0 if @a greater.
383 int fdisk_partition_cmp_partno(struct fdisk_partition
*a
,
384 struct fdisk_partition
*b
)
386 return a
->partno
- b
->partno
;
390 * fdisk_partition_partno_follow_default
394 * When @pa used as a template for fdisk_add_partition() when force label driver
395 * to add a new partition to the default (next) position.
397 * Returns: 0 on success, <0 on error.
399 int fdisk_partition_partno_follow_default(struct fdisk_partition
*pa
, int enable
)
403 pa
->partno_follow_default
= enable
? 1 : 0;
408 * fdisk_partition_set_type:
410 * @type: partition type
412 * Sets parititon type.
414 * Returns: 0 on success, <0 on error.
416 int fdisk_partition_set_type(struct fdisk_partition
*pa
,
417 struct fdisk_parttype
*type
)
422 fdisk_ref_parttype(type
);
423 fdisk_unref_parttype(pa
->type
);
430 * fdisk_partition_get_type:
433 * Returns: pointer to partition type.
435 struct fdisk_parttype
*fdisk_partition_get_type(struct fdisk_partition
*pa
)
437 return pa
? pa
->type
: NULL
;
440 int fdisk_partition_set_name(struct fdisk_partition
*pa
, const char *name
)
456 const char *fdisk_partition_get_name(struct fdisk_partition
*pa
)
458 return pa
? pa
->name
: NULL
;
461 int fdisk_partition_set_uuid(struct fdisk_partition
*pa
, const char *uuid
)
478 * fdisk_partition_has_end:
481 * Returns: 1 if the partition has defined last sector
483 int fdisk_partition_has_end(struct fdisk_partition
*pa
)
485 return pa
&& !FDISK_IS_UNDEF(pa
->start
) && !FDISK_IS_UNDEF(pa
->size
);
489 * fdisk_partition_get_end:
492 * This function may returns absolute non-sense, always check
493 * fdisk_partition_has_end().
495 * Note that partition end is defined by fdisk_partition_set_start() and
496 * fdisk_partition_set_size().
498 * Returns: last partition sector LBA.
500 fdisk_sector_t
fdisk_partition_get_end(struct fdisk_partition
*pa
)
502 return pa
->start
+ pa
->size
- (pa
->size
== 0 ? 0 : 1);
506 * fdisk_partition_end_follow_default
510 * When @pa used as a template for fdisk_add_partition() when force label driver
511 * to use all the possible space for the new partition.
513 * Returns: 0 on success, <0 on error.
515 int fdisk_partition_end_follow_default(struct fdisk_partition
*pa
, int enable
)
519 pa
->end_follow_default
= enable
? 1 : 0;
524 * fdisk_partition_end_is_default:
527 * Returns: 1 if the partition follows default
529 int fdisk_partition_end_is_default(struct fdisk_partition
*pa
)
532 return pa
->end_follow_default
;
536 * fdisk_partition_get_uuid:
539 * Returns: partition UUID as string
541 const char *fdisk_partition_get_uuid(struct fdisk_partition
*pa
)
543 return pa
? pa
->uuid
: NULL
;
547 * fdisk_partition_get_attrs:
550 * Returns: partition attributes in string format
552 const char *fdisk_partition_get_attrs(struct fdisk_partition
*pa
)
554 return pa
? pa
->attrs
: NULL
;
558 * fdisk_partition_set_attrs:
562 * Sets @attrs to @pa.
564 * Return: 0 on success, <0 on error.
566 int fdisk_partition_set_attrs(struct fdisk_partition
*pa
, const char *attrs
)
583 * fdisk_partition_is_nested:
586 * Returns: 1 if the partition is nested (e.g. MBR logical partition)
588 int fdisk_partition_is_nested(struct fdisk_partition
*pa
)
590 return pa
&& !FDISK_IS_UNDEF(pa
->parent_partno
);
594 * fdisk_partition_is_container:
597 * Returns: 1 if the partition is container (e.g. MBR extended partition)
599 int fdisk_partition_is_container(struct fdisk_partition
*pa
)
601 return pa
&& pa
->container
;
605 * fdisk_partition_get_parent:
607 * @parent: parent parno
609 * Returns: returns devno of the parent
611 int fdisk_partition_get_parent(struct fdisk_partition
*pa
, size_t *parent
)
614 *parent
= pa
->parent_partno
;
621 * fdisk_partition_is_used:
624 * Returns: 1 if the partition points to some area
626 int fdisk_partition_is_used(struct fdisk_partition
*pa
)
628 return pa
&& pa
->used
;
632 * fdisk_partition_is_bootable:
635 * Returns: 1 if the partition has enabled boot flag
637 int fdisk_partition_is_bootable(struct fdisk_partition
*pa
)
639 return pa
&& pa
->boot
== 1;
643 * fdisk_partition_is_freespace:
646 * Returns: 1 if @pa points to freespace
648 int fdisk_partition_is_freespace(struct fdisk_partition
*pa
)
650 return pa
&& pa
->freespace
;
654 * fdisk_partition_is_wholedisk:
657 * Returns: 1 if the partition is special whole-disk (e.g. SUN) partition
659 int fdisk_partition_is_wholedisk(struct fdisk_partition
*pa
)
661 return pa
&& pa
->wholedisk
;
665 * fdisk_partition_next_partno:
668 * @n: returns partition number
670 * If partno-follow-default (see fdisk_partition_partno_follow_default())
671 * enabled then returns next expected partno, otherwise use Ask API to ask user
672 * for the next partno.
674 * Returns: 0 on success, <0 on error
676 int fdisk_partition_next_partno(
677 struct fdisk_partition
*pa
,
678 struct fdisk_context
*cxt
,
684 if (pa
&& pa
->partno_follow_default
) {
687 DBG(PART
, ul_debugobj(pa
, "next partno (follow default)"));
689 for (i
= 0; i
< cxt
->label
->nparts_max
; i
++) {
690 if (!fdisk_is_partition_used(cxt
, i
)) {
697 } else if (pa
&& fdisk_partition_has_partno(pa
)) {
699 DBG(PART
, ul_debugobj(pa
, "next partno (specified=%zu)", pa
->partno
));
701 if (pa
->partno
>= cxt
->label
->nparts_max
)
705 return fdisk_ask_partnum(cxt
, n
, 1);
711 * fdisk_partition_to_string:
714 * @id: field (FDISK_FIELD_*)
715 * @data: returns string with allocated data
717 * Returns info about partition converted to printable string.
722 * struct fdisk_parition *pa;
724 * fdisk_get_partition(cxt, 0, &pa);
725 * fdisk_partition_to_string(pa, FDISK_FIELD_UUID, &data);
726 * printf("first partition uuid: %s\n", data);
728 * fdisk_unref_partition(pa);
732 * returns UUID for the first partition.
734 * Returns: 0 on success, otherwise, a corresponding error.
736 int fdisk_partition_to_string(struct fdisk_partition
*pa
,
737 struct fdisk_context
*cxt
,
745 if (!pa
|| !cxt
|| !data
)
749 case FDISK_FIELD_DEVICE
:
751 p
= strdup(_("Free space"));
752 else if (fdisk_partition_has_partno(pa
) && cxt
->dev_path
) {
753 if (cxt
->label
->flags
& FDISK_LABEL_FL_INCHARS_PARTNO
)
754 rc
= asprintf(&p
, "%c", (int) pa
->partno
+ 'a');
756 p
= fdisk_partname(cxt
->dev_path
, pa
->partno
+ 1);
759 case FDISK_FIELD_BOOT
:
760 if (fdisk_partition_is_bootable(pa
))
761 rc
= asprintf(&p
, "%c", pa
->boot
? '*' : ' ');
763 case FDISK_FIELD_START
:
764 if (fdisk_partition_has_start(pa
)) {
765 x
= fdisk_cround(cxt
, pa
->start
);
766 rc
= pa
->start_post
?
767 asprintf(&p
, "%ju%c", x
, pa
->start_post
) :
768 asprintf(&p
, "%ju", x
);
771 case FDISK_FIELD_END
:
772 if (fdisk_partition_has_end(pa
)) {
773 x
= fdisk_cround(cxt
, fdisk_partition_get_end(pa
));
775 asprintf(&p
, "%ju%c", x
, pa
->end_post
) :
776 asprintf(&p
, "%ju", x
);
779 case FDISK_FIELD_SIZE
:
780 if (fdisk_partition_has_size(pa
)) {
781 uint64_t sz
= pa
->size
* cxt
->sector_size
;
783 switch (cxt
->sizeunit
) {
784 case FDISK_SIZEUNIT_BYTES
:
785 rc
= asprintf(&p
, "%ju", sz
);
787 case FDISK_SIZEUNIT_HUMAN
:
788 if (fdisk_is_details(cxt
))
790 asprintf(&p
, "%ju%c", sz
, pa
->size_post
) :
791 asprintf(&p
, "%ju", sz
);
793 p
= size_to_human_string(SIZE_SUFFIX_1LETTER
, sz
);
801 case FDISK_FIELD_CYLINDERS
:
802 rc
= asprintf(&p
, "%ju", (uintmax_t)
803 fdisk_cround(cxt
, fdisk_partition_has_size(pa
) ? pa
->size
: 0));
805 case FDISK_FIELD_SECTORS
:
806 rc
= asprintf(&p
, "%ju",
807 fdisk_partition_has_size(pa
) ? (uintmax_t) pa
->size
: 0);
809 case FDISK_FIELD_BSIZE
:
810 rc
= asprintf(&p
, "%ju", pa
->bsize
);
812 case FDISK_FIELD_FSIZE
:
813 rc
= asprintf(&p
, "%ju", pa
->fsize
);
815 case FDISK_FIELD_CPG
:
816 rc
= asprintf(&p
, "%ju", pa
->cpg
);
818 case FDISK_FIELD_TYPE
:
819 p
= pa
->type
&& pa
->type
->name
? strdup(_(pa
->type
->name
)) : NULL
;
821 case FDISK_FIELD_TYPEID
:
822 if (pa
->type
&& fdisk_parttype_get_string(pa
->type
))
823 rc
= asprintf(&p
, "%s", fdisk_parttype_get_string(pa
->type
));
825 rc
= asprintf(&p
, "%x", fdisk_parttype_get_code(pa
->type
));
827 case FDISK_FIELD_UUID
:
828 p
= pa
->uuid
&& *pa
->uuid
? strdup(pa
->uuid
) : NULL
;
830 case FDISK_FIELD_NAME
:
831 p
= pa
->name
&& *pa
->name
? strdup(pa
->name
) : NULL
;
833 case FDISK_FIELD_ATTR
:
834 p
= pa
->attrs
&& *pa
->attrs
? strdup(pa
->attrs
) : NULL
;
836 case FDISK_FIELD_SADDR
:
837 p
= pa
->start_chs
&& *pa
->start_chs
? strdup(pa
->start_chs
) : NULL
;
839 case FDISK_FIELD_EADDR
:
840 p
= pa
->end_chs
&& *pa
->end_chs
? strdup(pa
->end_chs
) : NULL
;
860 * fdisk_get_partition:
862 * @partno: partition number (0 is the first partition)
863 * @pa: returns data about partition
865 * Reads disklabel and fills in @pa with data about partition @n.
867 * Note that partno may address unused partition and then this function does
868 * not fill anything to @pa. See fdisk_is_partition_used(). If @pa points to
869 * NULL then the function allocates a newly allocated fdisk_partition struct,
870 * use fdisk_unref_partition() to deallocate.
872 * Returns: 0 on success, otherwise, a corresponding error.
874 int fdisk_get_partition(struct fdisk_context
*cxt
, size_t partno
,
875 struct fdisk_partition
**pa
)
878 struct fdisk_partition
*np
= NULL
;
880 if (!cxt
|| !cxt
->label
|| !pa
)
882 if (!cxt
->label
->op
->get_part
)
884 if (!fdisk_is_partition_used(cxt
, partno
))
888 np
= *pa
= fdisk_new_partition();
892 fdisk_reset_partition(*pa
);
894 (*pa
)->partno
= partno
;
895 rc
= cxt
->label
->op
->get_part(cxt
, partno
, *pa
);
899 fdisk_unref_partition(np
);
902 fdisk_reset_partition(*pa
);
904 (*pa
)->size_explicit
= 1;
909 * fdisk_set_partition:
911 * @partno: partition number (0 is the first partition)
912 * @pa: new partition setting
914 * Modifies disklabel according to setting with in @pa.
916 * Returns: 0 on success, <0 on error.
918 int fdisk_set_partition(struct fdisk_context
*cxt
, size_t partno
,
919 struct fdisk_partition
*pa
)
921 if (!cxt
|| !cxt
->label
|| !pa
)
923 if (!cxt
->label
->op
->set_part
)
926 DBG(CXT
, ul_debugobj(cxt
, "setting partition %zu %p (start=%ju, end=%ju, size=%ju, "
927 "defaults(start=%s, end=%s, partno=%s)",
929 (uintmax_t) fdisk_partition_get_start(pa
),
930 (uintmax_t) fdisk_partition_get_end(pa
),
931 (uintmax_t) fdisk_partition_get_size(pa
),
932 pa
->start_follow_default
? "yes" : "no",
933 pa
->end_follow_default
? "yes" : "no",
934 pa
->partno_follow_default
? "yes" : "no"));
936 return cxt
->label
->op
->set_part(cxt
, partno
, pa
);
940 * fdisk_add_partition:
941 * @cxt: fdisk context
942 * @pa: template for the partition (or NULL)
943 * @partno: NULL or returns new partition number
945 * If @pa is not specified or any @pa item is missiong the libfdisk will ask by
948 * Adds a new partition to disklabel.
950 * Returns: 0 on success, <0 on error.
952 int fdisk_add_partition(struct fdisk_context
*cxt
,
953 struct fdisk_partition
*pa
,
961 if (!cxt
|| !cxt
->label
)
963 if (!cxt
->label
->op
->add_part
)
965 if (fdisk_missing_geometry(cxt
))
969 DBG(CXT
, ul_debugobj(cxt
, "adding new partition %p (start=%ju, end=%ju, size=%ju, "
970 "defaults(start=%s, end=%s, partno=%s)",
972 (uintmax_t) fdisk_partition_get_start(pa
),
973 (uintmax_t) fdisk_partition_get_end(pa
),
974 (uintmax_t) fdisk_partition_get_size(pa
),
975 pa
->start_follow_default
? "yes" : "no",
976 pa
->end_follow_default
? "yes" : "no",
977 pa
->partno_follow_default
? "yes" : "no"));
979 DBG(CXT
, ul_debugobj(cxt
, "adding partition"));
981 rc
= cxt
->label
->op
->add_part(cxt
, pa
, partno
);
983 DBG(CXT
, ul_debugobj(cxt
, "add partition done (rc=%d)", rc
));
988 * fdisk_delete_partition:
989 * @cxt: fdisk context
990 * @partno: partition number to delete (0 is the first partition)
992 * Deletes a @partno partition from disklabel.
994 * Returns: 0 on success, <0 on error
996 int fdisk_delete_partition(struct fdisk_context
*cxt
, size_t partno
)
998 if (!cxt
|| !cxt
->label
)
1000 if (!cxt
->label
->op
->del_part
)
1003 DBG(CXT
, ul_debugobj(cxt
, "deleting %s partition number %zd",
1004 cxt
->label
->name
, partno
));
1005 return cxt
->label
->op
->del_part(cxt
, partno
);
1009 * fdisk_delete_all_partitions:
1010 * @cxt: fdisk context
1012 * Delete all used partitions from disklabel.
1014 * Returns: 0 on success, otherwise, a corresponding error.
1016 int fdisk_delete_all_partitions(struct fdisk_context
*cxt
)
1021 if (!cxt
|| !cxt
->label
)
1024 for (i
= 0; i
< cxt
->label
->nparts_max
; i
++) {
1026 if (!fdisk_is_partition_used(cxt
, i
))
1028 rc
= fdisk_delete_partition(cxt
, i
);
1037 * fdisk_is_partition_used:
1039 * @n: partition number (0 is the first partition)
1041 * This is faster than fdisk_get_partition() + fdisk_partition_is_used().
1045 int fdisk_is_partition_used(struct fdisk_context
*cxt
, size_t n
)
1047 if (!cxt
|| !cxt
->label
)
1049 if (!cxt
->label
->op
->part_is_used
)
1052 return cxt
->label
->op
->part_is_used(cxt
, n
);