8 * @short_description: disk label (PT) specific data and functions
10 * The fdisk_new_context() initializes all label drivers, and allocate
11 * per-label specific data struct. This concept allows to store label specific
12 * settings to the label driver independently on the currently active label
13 * driver. Note that label struct cannot be deallocated, so there is no
14 * reference counting for fdisk_label objects. All is destroyed by
15 * fdisk_unref_context() only.
17 * Anyway, all label drives share in-memory first sector. The function
18 * fdisk_create_disklabel() overwrites this in-memory sector. But it's possible that
19 * label driver also uses another buffers, for example GPT reads more sectors
22 * All label operations are in-memory only, except fdisk_write_disklabel().
24 * All functions that use "struct fdisk_context" rather than "struct
25 * fdisk_label" use the currently active label driver.
29 int fdisk_probe_labels(struct fdisk_context
*cxt
)
35 for (i
= 0; i
< cxt
->nlabels
; i
++) {
36 struct fdisk_label
*lb
= cxt
->labels
[i
];
37 struct fdisk_label
*org
= fdisk_get_label(cxt
, NULL
);
43 DBG(CXT
, ul_debugobj(cxt
, "%s: disabled -- ignore", lb
->name
));
46 DBG(CXT
, ul_debugobj(cxt
, "probing for %s", lb
->name
));
49 rc
= lb
->op
->probe(cxt
);
54 lb
->op
->deinit(lb
); /* for sure */
58 __fdisk_switch_label(cxt
, lb
);
62 DBG(CXT
, ul_debugobj(cxt
, "no label found"));
63 return 1; /* not found */
67 * fdisk_label_get_name:
72 const char *fdisk_label_get_name(const struct fdisk_label
*lb
)
74 return lb
? lb
->name
: NULL
;
78 * fdisk_label_is_labeltype:
81 * Returns: FDISK_DISKLABEL_*.
83 int fdisk_label_get_type(const struct fdisk_label
*lb
)
89 * fdisk_label_require_geometry:
92 * Returns: 1 if label requires CHS geometry
94 int fdisk_label_require_geometry(const struct fdisk_label
*lb
)
98 return lb
->flags
& FDISK_LABEL_FL_REQUIRE_GEOMETRY
? 1 : 0;
102 * fdisk_label_get_fields_ids
103 * @lb: label (or NULL for the current label)
105 * @ids: returns allocated array with FDISK_FIELD_* IDs
106 * @nids: returns number of items in fields
108 * This function returns the default fields for the label.
110 * Note that the set of the default fields depends on fdisk_enable_details()
111 * function. If the details are enabled then this function usually returns more
114 * Returns: 0 on success, otherwise, a corresponding error.
116 int fdisk_label_get_fields_ids(
117 const struct fdisk_label
*lb
,
118 struct fdisk_context
*cxt
,
119 int **ids
, size_t *nids
)
124 if (!cxt
|| (!lb
&& !cxt
->label
))
128 if (!lb
->fields
|| !lb
->nfields
)
130 c
= calloc(lb
->nfields
, sizeof(int));
133 for (n
= 0, i
= 0; i
< lb
->nfields
; i
++) {
134 int id
= lb
->fields
[i
].id
;
136 if ((fdisk_is_details(cxt
) &&
137 (lb
->fields
[i
].flags
& FDISK_FIELDFL_EYECANDY
))
138 || (!fdisk_is_details(cxt
) &&
139 (lb
->fields
[i
].flags
& FDISK_FIELDFL_DETAIL
))
140 || (id
== FDISK_FIELD_SECTORS
&&
141 fdisk_use_cylinders(cxt
))
142 || (id
== FDISK_FIELD_CYLINDERS
&&
143 !fdisk_use_cylinders(cxt
)))
158 * fdisk_label_get_fields_ids_all
159 * @lb: label (or NULL for the current label)
161 * @ids: returns allocated array with FDISK_FIELD_* IDs
162 * @nids: returns number of items in fields
164 * This function returns all fields for the label.
166 * Returns: 0 on success, otherwise, a corresponding error.
168 int fdisk_label_get_fields_ids_all(
169 const struct fdisk_label
*lb
,
170 struct fdisk_context
*cxt
,
171 int **ids
, size_t *nids
)
176 if (!cxt
|| (!lb
&& !cxt
->label
))
180 if (!lb
->fields
|| !lb
->nfields
)
182 c
= calloc(lb
->nfields
, sizeof(int));
185 for (n
= 0, i
= 0; i
< lb
->nfields
; i
++)
186 c
[n
++] = lb
->fields
[i
].id
;
197 * fdisk_label_get_field:
201 * The field struct describes data stored in struct fdisk_partition. The info
202 * about data is usable for example to generate human readable output (e.g.
203 * fdisk 'p'rint command). See fdisk_partition_to_string() and fdisk code.
205 * Returns: pointer to static instance of the field.
207 const struct fdisk_field
*fdisk_label_get_field(const struct fdisk_label
*lb
, int id
)
214 for (i
= 0; i
< lb
->nfields
; i
++) {
215 if (lb
->fields
[i
].id
== id
)
216 return &lb
->fields
[i
];
223 * fdisk_label_get_field_by_name
227 * Returns: pointer to static instance of the field.
229 const struct fdisk_field
*fdisk_label_get_field_by_name(
230 const struct fdisk_label
*lb
,
238 for (i
= 0; i
< lb
->nfields
; i
++) {
239 if (lb
->fields
[i
].name
&& strcasecmp(lb
->fields
[i
].name
, name
) == 0)
240 return &lb
->fields
[i
];
247 * fdisk_write_disklabel:
248 * @cxt: fdisk context
250 * Write in-memory changes to disk. Be careful!
252 * Returns: 0 on success, otherwise, a corresponding error.
254 int fdisk_write_disklabel(struct fdisk_context
*cxt
)
256 if (!cxt
|| !cxt
->label
|| cxt
->readonly
)
258 if (!cxt
->label
->op
->write
)
262 return cxt
->label
->op
->write(cxt
);
266 * fdisk_verify_disklabel:
267 * @cxt: fdisk context
269 * Verifies the partition table.
271 * Returns: 0 on success, otherwise, a corresponding error.
273 int fdisk_verify_disklabel(struct fdisk_context
*cxt
)
275 if (!cxt
|| !cxt
->label
)
277 if (!cxt
->label
->op
->verify
)
279 if (fdisk_missing_geometry(cxt
))
282 return cxt
->label
->op
->verify(cxt
);
286 * fdisk_list_disklabel:
287 * @cxt: fdisk context
289 * Lists details about disklabel, but no partitions.
291 * This function is based on fdisk_get_disklabel_item() and prints all label
292 * specific information by ASK interface (FDISK_ASKTYPE_INFO, aka fdisk_info()).
293 * The function requires enabled "details" by fdisk_enable_details().
295 * It's recommended to use fdisk_get_disklabel_item() if you need better
296 * control on output and formatting.
298 * Returns: 0 on success, otherwise, a corresponding error.
300 int fdisk_list_disklabel(struct fdisk_context
*cxt
)
303 struct fdisk_labelitem item
= { .id
= id
};
305 if (!cxt
|| !cxt
->label
)
308 if (!cxt
->display_details
)
311 /* List all label items */
313 /* rc: < 0 error, 0 success, 1 unknown item, 2 out of range */
314 rc
= fdisk_get_disklabel_item(cxt
, id
++, &item
);
319 fdisk_info(cxt
, "%s: %ju", item
.name
, item
.data
.num64
);
322 if (item
.data
.str
&& item
.name
)
323 fdisk_info(cxt
, "%s: %s", item
.name
, item
.data
.str
);
326 fdisk_reset_labelitem(&item
);
327 } while (rc
== 0 || rc
== 1);
329 return rc
< 0 ? rc
: 0;
333 * fdisk_create_disklabel:
334 * @cxt: fdisk context
337 * Creates a new disk label of type @name. If @name is NULL, then it will
338 * create a default system label type, either SUN or DOS. The function
339 * automatically switches the current label driver to @name. The function
340 * fdisk_get_label() returns the current label driver.
342 * The function modifies in-memory data only.
344 * Returns: 0 on success, otherwise, a corresponding error.
346 int fdisk_create_disklabel(struct fdisk_context
*cxt
, const char *name
)
349 struct fdisk_label
*lb
;
354 if (!name
) { /* use default label creation */
363 fdisk_deinit_label(cxt
->label
);
367 lb
= fdisk_get_label(cxt
, name
);
368 if (!lb
|| lb
->disabled
)
371 if (!haslabel
|| (lb
&& cxt
->label
!= lb
))
372 fdisk_check_collisions(cxt
);
377 __fdisk_switch_label(cxt
, lb
);
378 assert(cxt
->label
== lb
);
380 if (haslabel
&& !cxt
->parent
)
381 fdisk_reset_device_properties(cxt
);
383 DBG(CXT
, ul_debugobj(cxt
, "create a new %s label", lb
->name
));
384 return lb
->op
->create(cxt
);
388 * fdisk_locate_disklabel:
391 * @name: return item name
392 * @offset: return offset where is item
395 * Locate disklabel and returns info about @n item of the label. For example
396 * GPT is composed from two items, PMBR and GPT, n=0 return offset to PMBR and n=1
397 * return offset to GPT. For more details see 'D' expert fdisk command.
399 * Returns: 0 on success, <0 on error, 1 no more items.
401 int fdisk_locate_disklabel(struct fdisk_context
*cxt
, int n
, const char **name
,
402 uint64_t *offset
, size_t *size
)
404 if (!cxt
|| !cxt
->label
)
406 if (!cxt
->label
->op
->locate
)
409 DBG(CXT
, ul_debugobj(cxt
, "locating %d chunk of %s.", n
, cxt
->label
->name
));
410 return cxt
->label
->op
->locate(cxt
, n
, name
, offset
, size
);
415 * fdisk_get_disklabel_id:
416 * @cxt: fdisk context
417 * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID)
419 * Returns: 0 on success, otherwise, a corresponding error.
421 int fdisk_get_disklabel_id(struct fdisk_context
*cxt
, char **id
)
423 struct fdisk_labelitem item
= FDISK_LABELITEM_INIT
;
426 if (!cxt
|| !cxt
->label
|| !id
)
429 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s ID", cxt
->label
->name
));
431 rc
= fdisk_get_disklabel_item(cxt
, FDISK_LABELITEM_ID
, &item
);
434 item
.data
.str
= NULL
;
436 fdisk_reset_labelitem(&item
);
443 * fdisk_get_disklabel_item:
444 * @cxt: fdisk context
445 * @id: item ID (FDISK_LABELITEM_* or *_LABELITEM_*)
446 * @item: specifies and returns the item
448 * Note that @id is always in range 0..N. It's fine to use the function in loop
449 * until it returns error or 2, the result in @item should be ignored when
450 * function returns 1. Don't forget to use fdisk_reset_labelitem() or fdisk_unref_labelitem().
452 * Returns: 0 on success, < 0 on error, 1 on unsupported item, 2 id out of range
454 int fdisk_get_disklabel_item(struct fdisk_context
*cxt
, int id
, struct fdisk_labelitem
*item
)
456 if (!cxt
|| !cxt
->label
|| !item
)
459 fdisk_reset_labelitem(item
);
461 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s item %d", cxt
->label
->name
, item
->id
));
463 if (!cxt
->label
->op
->get_item
)
466 return cxt
->label
->op
->get_item(cxt
, item
);
470 * fdisk_set_disklabel_id:
471 * @cxt: fdisk context
473 * Returns: 0 on success, otherwise, a corresponding error.
475 int fdisk_set_disklabel_id(struct fdisk_context
*cxt
)
477 if (!cxt
|| !cxt
->label
)
479 if (!cxt
->label
->op
->set_id
)
482 DBG(CXT
, ul_debugobj(cxt
, "setting %s disk ID", cxt
->label
->name
));
483 return cxt
->label
->op
->set_id(cxt
);
487 * fdisk_set_partition_type:
488 * @cxt: fdisk context
489 * @partnum: partition number
492 * Returns: 0 on success, < 0 on error.
494 int fdisk_set_partition_type(struct fdisk_context
*cxt
,
496 struct fdisk_parttype
*t
)
498 if (!cxt
|| !cxt
->label
|| !t
)
502 if (cxt
->label
->op
->set_part
) {
503 struct fdisk_partition
*pa
= fdisk_new_partition();
508 fdisk_partition_set_type(pa
, t
);
510 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: set type", partnum
));
511 rc
= cxt
->label
->op
->set_part(cxt
, partnum
, pa
);
512 fdisk_unref_partition(pa
);
521 * fdisk_toggle_partition_flag:
522 * @cxt: fdisk context
523 * @partnum: partition number
526 * Returns: 0 on success, otherwise, a corresponding error.
528 int fdisk_toggle_partition_flag(struct fdisk_context
*cxt
,
534 if (!cxt
|| !cxt
->label
)
536 if (!cxt
->label
->op
->part_toggle_flag
)
539 rc
= cxt
->label
->op
->part_toggle_flag(cxt
, partnum
, flag
);
541 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum
, flag
, rc
));
546 * fdisk_reorder_partitions
547 * @cxt: fdisk context
549 * Sort partitions according to the partition start sector.
551 * Returns: 0 on success, 1 reorder unnecessary, otherwise a corresponding error.
553 int fdisk_reorder_partitions(struct fdisk_context
*cxt
)
555 if (!cxt
|| !cxt
->label
)
557 if (!cxt
->label
->op
->reorder
)
560 return cxt
->label
->op
->reorder(cxt
);
564 * Resets the current used label driver to initial state
566 void fdisk_deinit_label(struct fdisk_label
*lb
)
570 /* private label information */
576 * fdisk_label_set_changed:
580 * Marks in-memory data as changed, to force fdisk_write_disklabel() to write
581 * to device. This should be unnecessary by default, the library keeps track
584 void fdisk_label_set_changed(struct fdisk_label
*lb
, int changed
)
587 lb
->changed
= changed
? 1 : 0;
591 * fdisk_label_is_changed:
594 * Returns: 1 if in-memory data has been changed.
596 int fdisk_label_is_changed(const struct fdisk_label
*lb
)
599 return lb
? lb
->changed
: 0;
603 * fdisk_label_set_disabled:
607 * Mark label as disabled, then libfdisk is going to ignore the label when
608 * probe device for labels.
610 void fdisk_label_set_disabled(struct fdisk_label
*lb
, int disabled
)
614 DBG(LABEL
, ul_debug("%s label %s",
616 disabled
? "DISABLED" : "ENABLED"));
617 lb
->disabled
= disabled
? 1 : 0;
621 * fdisk_label_is_disabled:
624 * Returns: 1 if label driver disabled.
626 int fdisk_label_is_disabled(const struct fdisk_label
*lb
)
629 return lb
? lb
->disabled
: 0;
633 * fdisk_label_get_geomrange_sectors:
635 * @mi: minimal number
636 * @ma: maximal number
638 * The function provides minimal and maximal geometry supported for the label,
639 * if no range defined by library than returns -ENOSYS.
643 * Returns: 0 on success, otherwise, a corresponding error.
645 int fdisk_label_get_geomrange_sectors(const struct fdisk_label
*lb
,
646 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
648 if (!lb
|| lb
->geom_min
.sectors
== 0)
651 *mi
= lb
->geom_min
.sectors
;
653 *ma
= lb
->geom_max
.sectors
;
658 * fdisk_label_get_geomrange_heads:
660 * @mi: minimal number
661 * @ma: maximal number
663 * The function provides minimal and maximal geometry supported for the label,
664 * if no range defined by library than returns -ENOSYS.
668 * Returns: 0 on success, otherwise, a corresponding error.
670 int fdisk_label_get_geomrange_heads(const struct fdisk_label
*lb
,
671 unsigned int *mi
, unsigned int *ma
)
673 if (!lb
|| lb
->geom_min
.heads
== 0)
676 *mi
= lb
->geom_min
.heads
;
678 *ma
= lb
->geom_max
.heads
;
683 * fdisk_label_get_geomrange_cylinders:
685 * @mi: minimal number
686 * @ma: maximal number
688 * The function provides minimal and maximal geometry supported for the label,
689 * if no range defined by library than returns -ENOSYS.
693 * Returns: 0 on success, otherwise, a corresponding error.
695 int fdisk_label_get_geomrange_cylinders(const struct fdisk_label
*lb
,
696 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
698 if (!lb
|| lb
->geom_min
.cylinders
== 0)
701 *mi
= lb
->geom_min
.cylinders
;
703 *ma
= lb
->geom_max
.cylinders
;