9 * @short_description: disk label (PT) specific data and functions
11 * The fdisk_new_context() initializes all label drivers, and allocate
12 * per-label specific data struct. This concept can be used to store label specific
13 * settings to the label driver independently on the currently active label
14 * driver. Note that label struct cannot be deallocated, so there is no
15 * reference counting for fdisk_label objects. All is destroyed by
16 * fdisk_unref_context() only.
18 * Anyway, all label drives share in-memory first sector. The function
19 * fdisk_create_disklabel() overwrites this in-memory sector. But it's possible that
20 * label driver also uses another buffers, for example GPT reads more sectors
23 * All label operations are in-memory only, except fdisk_write_disklabel().
25 * All functions that use "struct fdisk_context" rather than "struct
26 * fdisk_label" use the currently active label driver.
30 int fdisk_probe_labels(struct fdisk_context
*cxt
)
36 for (i
= 0; i
< cxt
->nlabels
; i
++) {
37 struct fdisk_label
*lb
= cxt
->labels
[i
];
38 struct fdisk_label
*org
= fdisk_get_label(cxt
, NULL
);
44 DBG(CXT
, ul_debugobj(cxt
, "%s: disabled -- ignore", lb
->name
));
47 DBG(CXT
, ul_debugobj(cxt
, "probing for %s", lb
->name
));
50 rc
= lb
->op
->probe(cxt
);
55 lb
->op
->deinit(lb
); /* for sure */
59 __fdisk_switch_label(cxt
, lb
);
63 DBG(CXT
, ul_debugobj(cxt
, "no label found"));
64 return 1; /* not found */
68 * fdisk_label_get_name:
73 const char *fdisk_label_get_name(const struct fdisk_label
*lb
)
75 return lb
? lb
->name
: NULL
;
79 * fdisk_label_is_labeltype:
82 * Returns: FDISK_DISKLABEL_*.
84 int fdisk_label_get_type(const struct fdisk_label
*lb
)
90 * fdisk_label_require_geometry:
93 * Returns: 1 if label requires CHS geometry
95 int fdisk_label_require_geometry(const struct fdisk_label
*lb
)
99 return lb
->flags
& FDISK_LABEL_FL_REQUIRE_GEOMETRY
? 1 : 0;
103 * fdisk_label_get_fields_ids
104 * @lb: label (or NULL for the current label)
106 * @ids: returns allocated array with FDISK_FIELD_* IDs
107 * @nids: returns number of items in fields
109 * This function returns the default fields for the label.
111 * Note that the set of the default fields depends on fdisk_enable_details()
112 * function. If the details are enabled then this function usually returns more
115 * Returns: 0 on success, otherwise, a corresponding error.
117 int fdisk_label_get_fields_ids(
118 const struct fdisk_label
*lb
,
119 struct fdisk_context
*cxt
,
120 int **ids
, size_t *nids
)
125 if (!cxt
|| (!lb
&& !cxt
->label
))
129 if (!lb
->fields
|| !lb
->nfields
)
131 c
= calloc(lb
->nfields
, sizeof(int));
134 for (n
= 0, i
= 0; i
< lb
->nfields
; i
++) {
135 int id
= lb
->fields
[i
].id
;
137 if ((fdisk_is_details(cxt
) &&
138 (lb
->fields
[i
].flags
& FDISK_FIELDFL_EYECANDY
))
139 || (!fdisk_is_details(cxt
) &&
140 (lb
->fields
[i
].flags
& FDISK_FIELDFL_DETAIL
))
141 || (id
== FDISK_FIELD_SECTORS
&&
142 fdisk_use_cylinders(cxt
))
143 || (id
== FDISK_FIELD_CYLINDERS
&&
144 !fdisk_use_cylinders(cxt
)))
159 * fdisk_label_get_fields_ids_all
160 * @lb: label (or NULL for the current label)
162 * @ids: returns allocated array with FDISK_FIELD_* IDs
163 * @nids: returns number of items in fields
165 * This function returns all fields for the label.
167 * Returns: 0 on success, otherwise, a corresponding error.
169 int fdisk_label_get_fields_ids_all(
170 const struct fdisk_label
*lb
,
171 struct fdisk_context
*cxt
,
172 int **ids
, size_t *nids
)
177 if (!cxt
|| (!lb
&& !cxt
->label
))
181 if (!lb
->fields
|| !lb
->nfields
)
183 c
= calloc(lb
->nfields
, sizeof(int));
186 for (n
= 0, i
= 0; i
< lb
->nfields
; i
++)
187 c
[n
++] = lb
->fields
[i
].id
;
198 * fdisk_label_get_field:
202 * The field struct describes data stored in struct fdisk_partition. The info
203 * about data is usable for example to generate human readable output (e.g.
204 * fdisk 'p'rint command). See fdisk_partition_to_string() and fdisk code.
206 * Returns: pointer to static instance of the field.
208 const struct fdisk_field
*fdisk_label_get_field(const struct fdisk_label
*lb
, int id
)
215 for (i
= 0; i
< lb
->nfields
; i
++) {
216 if (lb
->fields
[i
].id
== id
)
217 return &lb
->fields
[i
];
224 * fdisk_label_get_field_by_name
228 * Returns: pointer to static instance of the field.
230 const struct fdisk_field
*fdisk_label_get_field_by_name(
231 const struct fdisk_label
*lb
,
239 for (i
= 0; i
< lb
->nfields
; i
++) {
240 if (lb
->fields
[i
].name
&& c_strcasecmp(lb
->fields
[i
].name
, name
) == 0)
241 return &lb
->fields
[i
];
248 * fdisk_write_disklabel:
249 * @cxt: fdisk context
251 * This function wipes the device (if enabled by fdisk_enable_wipe()) and then
252 * it writes in-memory changes to disk. Be careful!
254 * Returns: 0 on success, otherwise, a corresponding error.
256 int fdisk_write_disklabel(struct fdisk_context
*cxt
)
258 if (!cxt
|| !cxt
->label
|| cxt
->readonly
)
260 if (!cxt
->label
->op
->write
)
264 return cxt
->label
->op
->write(cxt
);
268 * fdisk_verify_disklabel:
269 * @cxt: fdisk context
271 * Verifies the partition table.
273 * Returns: 0 on success, <1 runtime or option errors, >0 number of detected issues
275 int fdisk_verify_disklabel(struct fdisk_context
*cxt
)
277 if (!cxt
|| !cxt
->label
)
279 if (!cxt
->label
->op
->verify
)
281 if (fdisk_missing_geometry(cxt
))
284 return cxt
->label
->op
->verify(cxt
);
288 * fdisk_list_disklabel:
289 * @cxt: fdisk context
291 * Lists details about disklabel, but no partitions.
293 * This function is based on fdisk_get_disklabel_item() and prints all label
294 * specific information by ASK interface (FDISK_ASKTYPE_INFO, aka fdisk_info()).
295 * The function requires enabled "details" by fdisk_enable_details().
297 * It's recommended to use fdisk_get_disklabel_item() if you need better
298 * control on output and formatting.
300 * Returns: 0 on success, otherwise, a corresponding error.
302 int fdisk_list_disklabel(struct fdisk_context
*cxt
)
305 struct fdisk_labelitem item
= { .id
= id
};
307 if (!cxt
|| !cxt
->label
)
310 if (!cxt
->display_details
)
313 /* List all label items */
315 /* rc: < 0 error, 0 success, 1 unknown item, 2 out of range */
316 rc
= fdisk_get_disklabel_item(cxt
, id
++, &item
);
321 fdisk_info(cxt
, "%s: %ju", item
.name
, item
.data
.num64
);
324 if (item
.data
.str
&& item
.name
)
325 fdisk_info(cxt
, "%s: %s", item
.name
, item
.data
.str
);
328 fdisk_reset_labelitem(&item
);
329 } while (rc
== 0 || rc
== 1);
331 return rc
< 0 ? rc
: 0;
335 * fdisk_create_disklabel:
336 * @cxt: fdisk context
339 * Creates a new disk label of type @name. If @name is NULL, then it will
340 * create a default system label type, either SUN or DOS. The function
341 * automatically switches the current label driver to @name. The function
342 * fdisk_get_label() returns the current label driver.
344 * The function modifies in-memory data only.
346 * Returns: 0 on success, otherwise, a corresponding error.
348 int fdisk_create_disklabel(struct fdisk_context
*cxt
, const char *name
)
350 int haslabel
= 0, rc
;
351 struct fdisk_label
*lb
;
356 if (!name
) { /* use default label creation */
365 fdisk_deinit_label(cxt
->label
);
369 lb
= fdisk_get_label(cxt
, name
);
370 if (!lb
|| lb
->disabled
)
373 if (!haslabel
|| (lb
&& cxt
->label
!= lb
))
374 fdisk_check_collisions(cxt
);
379 rc
= __fdisk_switch_label(cxt
, lb
);
383 assert(cxt
->label
== lb
);
385 if (haslabel
&& !cxt
->parent
) {
386 rc
= fdisk_reset_device_properties(cxt
);
391 DBG(CXT
, ul_debugobj(cxt
, "creating a new %s label", lb
->name
));
392 return lb
->op
->create(cxt
);
396 * fdisk_locate_disklabel:
399 * @name: return item name
400 * @offset: return offset where is item
403 * Locate disklabel and returns info about @n item of the label.
405 * For example GPT is composed from three items, PMBR and GPT, n=0 return
406 * offset to PMBR and n=1 return offset to GPT Header and n=2 returns offset to
407 * GPT array of partitions, n=3 and n=4 returns location of the backup GPT
408 * label at the end of the disk.
410 * The function returns the current in-memory situation. It's possible that a
411 * header location is modified by write operation, for example when enabled
412 * minimization (see fdisk_gpt_enable_minimize()). In this case it's better to
413 * call this function after fdisk_write_disklabel().
415 * For more details see 'D' expert fdisk command.
417 * Returns: 0 on success, <0 on error, 1 no more items.
419 int fdisk_locate_disklabel(struct fdisk_context
*cxt
, int n
, const char **name
,
420 uint64_t *offset
, size_t *size
)
422 if (!cxt
|| !cxt
->label
)
424 if (!cxt
->label
->op
->locate
)
427 DBG(CXT
, ul_debugobj(cxt
, "locating %d chunk of %s.", n
, cxt
->label
->name
));
428 return cxt
->label
->op
->locate(cxt
, n
, name
, offset
, size
);
433 * fdisk_get_disklabel_id:
434 * @cxt: fdisk context
435 * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID)
437 * Returns: 0 on success, otherwise, a corresponding error.
439 int fdisk_get_disklabel_id(struct fdisk_context
*cxt
, char **id
)
441 struct fdisk_labelitem item
= FDISK_LABELITEM_INIT
;
444 if (!cxt
|| !cxt
->label
|| !id
)
447 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s ID", cxt
->label
->name
));
449 rc
= fdisk_get_disklabel_item(cxt
, FDISK_LABELITEM_ID
, &item
);
452 item
.data
.str
= NULL
;
454 fdisk_reset_labelitem(&item
);
461 * fdisk_get_disklabel_item:
462 * @cxt: fdisk context
463 * @id: item ID (FDISK_LABELITEM_* or *_LABELITEM_*)
464 * @item: specifies and returns the item
466 * Note that @id is always in range 0..N. It's fine to use the function in loop
467 * until it returns error or 2, the result in @item should be ignored when
468 * function returns 1. Don't forget to use fdisk_reset_labelitem() or fdisk_unref_labelitem().
470 * Returns: 0 on success, < 0 on error, 1 on unsupported item, 2 id out of range
472 int fdisk_get_disklabel_item(struct fdisk_context
*cxt
, int id
, struct fdisk_labelitem
*item
)
474 if (!cxt
|| !cxt
->label
|| !item
)
477 fdisk_reset_labelitem(item
);
479 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s item %d", cxt
->label
->name
, item
->id
));
481 if (!cxt
->label
->op
->get_item
)
484 return cxt
->label
->op
->get_item(cxt
, item
);
488 * fdisk_set_disklabel_id:
489 * @cxt: fdisk context
491 * Returns: 0 on success, otherwise, a corresponding error.
493 int fdisk_set_disklabel_id(struct fdisk_context
*cxt
)
495 if (!cxt
|| !cxt
->label
)
497 if (!cxt
->label
->op
->set_id
)
500 DBG(CXT
, ul_debugobj(cxt
, "setting %s disk ID", cxt
->label
->name
));
501 return cxt
->label
->op
->set_id(cxt
, NULL
);
505 * fdisk_set_disklabel_id_from_string
506 * @cxt: fdisk context
509 * Returns: 0 on success, otherwise, a corresponding error.
513 int fdisk_set_disklabel_id_from_string(struct fdisk_context
*cxt
, const char *str
)
515 if (!cxt
|| !cxt
->label
|| !str
)
517 if (!cxt
->label
->op
->set_id
)
520 DBG(CXT
, ul_debugobj(cxt
, "setting %s disk ID from '%s'", cxt
->label
->name
, str
));
521 return cxt
->label
->op
->set_id(cxt
, str
);
525 * fdisk_set_partition_type:
526 * @cxt: fdisk context
527 * @partnum: partition number
530 * Returns: 0 on success, < 0 on error.
532 int fdisk_set_partition_type(struct fdisk_context
*cxt
,
534 struct fdisk_parttype
*t
)
536 if (!cxt
|| !cxt
->label
|| !t
)
540 if (cxt
->label
->op
->set_part
) {
541 struct fdisk_partition
*pa
= fdisk_new_partition();
546 fdisk_partition_set_type(pa
, t
);
548 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: set type", partnum
));
549 rc
= cxt
->label
->op
->set_part(cxt
, partnum
, pa
);
550 fdisk_unref_partition(pa
);
559 * fdisk_toggle_partition_flag:
560 * @cxt: fdisk context
561 * @partnum: partition number
564 * Returns: 0 on success, otherwise, a corresponding error.
566 int fdisk_toggle_partition_flag(struct fdisk_context
*cxt
,
572 if (!cxt
|| !cxt
->label
)
574 if (!cxt
->label
->op
->part_toggle_flag
)
577 rc
= cxt
->label
->op
->part_toggle_flag(cxt
, partnum
, flag
);
579 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum
, flag
, rc
));
584 * fdisk_reorder_partitions
585 * @cxt: fdisk context
587 * Sort partitions according to the partition start sector.
589 * Returns: 0 on success, 1 reorder unnecessary, otherwise a corresponding error.
591 int fdisk_reorder_partitions(struct fdisk_context
*cxt
)
595 if (!cxt
|| !cxt
->label
)
597 if (!cxt
->label
->op
->reorder
)
600 rc
= cxt
->label
->op
->reorder(cxt
);
604 fdisk_info(cxt
, _("Partitions order fixed."));
607 fdisk_info(cxt
, _("Nothing to do. Ordering is correct already."));
610 fdisk_warnx(cxt
, _("Failed to fix partitions order."));
618 * Resets the current used label driver to initial state
620 void fdisk_deinit_label(struct fdisk_label
*lb
)
624 /* private label information */
630 * fdisk_label_set_changed:
634 * Marks in-memory data as changed, to force fdisk_write_disklabel() to write
635 * to device. This should be unnecessary by default, the library keeps track
638 void fdisk_label_set_changed(struct fdisk_label
*lb
, int changed
)
641 lb
->changed
= changed
? 1 : 0;
645 * fdisk_label_is_changed:
648 * Returns: 1 if in-memory data has been changed.
650 int fdisk_label_is_changed(const struct fdisk_label
*lb
)
652 return lb
? lb
->changed
: 0;
656 * fdisk_label_set_disabled:
660 * Mark label as disabled, then libfdisk is going to ignore the label when
661 * probe device for labels.
663 void fdisk_label_set_disabled(struct fdisk_label
*lb
, int disabled
)
667 DBG(LABEL
, ul_debug("%s label %s",
669 disabled
? "DISABLED" : "ENABLED"));
670 lb
->disabled
= disabled
? 1 : 0;
674 * fdisk_label_is_disabled:
677 * Returns: 1 if label driver disabled.
679 int fdisk_label_is_disabled(const struct fdisk_label
*lb
)
682 return lb
? lb
->disabled
: 0;
686 * fdisk_label_get_geomrange_sectors:
688 * @mi: minimal number
689 * @ma: maximal number
691 * The function provides minimal and maximal geometry supported for the label,
692 * if no range defined by library then returns -ENOSYS.
696 * Returns: 0 on success, otherwise, a corresponding error.
698 int fdisk_label_get_geomrange_sectors(const struct fdisk_label
*lb
,
699 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
701 if (!lb
|| lb
->geom_min
.sectors
== 0)
704 *mi
= lb
->geom_min
.sectors
;
706 *ma
= lb
->geom_max
.sectors
;
711 * fdisk_label_get_geomrange_heads:
713 * @mi: minimal number
714 * @ma: maximal number
716 * The function provides minimal and maximal geometry supported for the label,
717 * if no range defined by library then returns -ENOSYS.
721 * Returns: 0 on success, otherwise, a corresponding error.
723 int fdisk_label_get_geomrange_heads(const struct fdisk_label
*lb
,
724 unsigned int *mi
, unsigned int *ma
)
726 if (!lb
|| lb
->geom_min
.heads
== 0)
729 *mi
= lb
->geom_min
.heads
;
731 *ma
= lb
->geom_max
.heads
;
736 * fdisk_label_get_geomrange_cylinders:
738 * @mi: minimal number
739 * @ma: maximal number
741 * The function provides minimal and maximal geometry supported for the label,
742 * if no range defined by library then returns -ENOSYS.
746 * Returns: 0 on success, otherwise, a corresponding error.
748 int fdisk_label_get_geomrange_cylinders(const struct fdisk_label
*lb
,
749 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
751 if (!lb
|| lb
->geom_min
.cylinders
== 0)
754 *mi
= lb
->geom_min
.cylinders
;
756 *ma
= lb
->geom_max
.cylinders
;