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 * This function wipes the device (if eanbled by fdisk_enable_wipe() and than
251 * it writes in-memory changes to disk. Be careful!
253 * Returns: 0 on success, otherwise, a corresponding error.
255 int fdisk_write_disklabel(struct fdisk_context
*cxt
)
257 if (!cxt
|| !cxt
->label
|| cxt
->readonly
)
259 if (!cxt
->label
->op
->write
)
263 return cxt
->label
->op
->write(cxt
);
267 * fdisk_verify_disklabel:
268 * @cxt: fdisk context
270 * Verifies the partition table.
272 * Returns: 0 on success, otherwise, a corresponding error.
274 int fdisk_verify_disklabel(struct fdisk_context
*cxt
)
276 if (!cxt
|| !cxt
->label
)
278 if (!cxt
->label
->op
->verify
)
280 if (fdisk_missing_geometry(cxt
))
283 return cxt
->label
->op
->verify(cxt
);
287 * fdisk_list_disklabel:
288 * @cxt: fdisk context
290 * Lists details about disklabel, but no partitions.
292 * This function is based on fdisk_get_disklabel_item() and prints all label
293 * specific information by ASK interface (FDISK_ASKTYPE_INFO, aka fdisk_info()).
294 * The function requires enabled "details" by fdisk_enable_details().
296 * It's recommended to use fdisk_get_disklabel_item() if you need better
297 * control on output and formatting.
299 * Returns: 0 on success, otherwise, a corresponding error.
301 int fdisk_list_disklabel(struct fdisk_context
*cxt
)
304 struct fdisk_labelitem item
= { .id
= id
};
306 if (!cxt
|| !cxt
->label
)
309 if (!cxt
->display_details
)
312 /* List all label items */
314 /* rc: < 0 error, 0 success, 1 unknown item, 2 out of range */
315 rc
= fdisk_get_disklabel_item(cxt
, id
++, &item
);
320 fdisk_info(cxt
, "%s: %ju", item
.name
, item
.data
.num64
);
323 if (item
.data
.str
&& item
.name
)
324 fdisk_info(cxt
, "%s: %s", item
.name
, item
.data
.str
);
327 fdisk_reset_labelitem(&item
);
328 } while (rc
== 0 || rc
== 1);
330 return rc
< 0 ? rc
: 0;
334 * fdisk_create_disklabel:
335 * @cxt: fdisk context
338 * Creates a new disk label of type @name. If @name is NULL, then it will
339 * create a default system label type, either SUN or DOS. The function
340 * automatically switches the current label driver to @name. The function
341 * fdisk_get_label() returns the current label driver.
343 * The function modifies in-memory data only.
345 * Returns: 0 on success, otherwise, a corresponding error.
347 int fdisk_create_disklabel(struct fdisk_context
*cxt
, const char *name
)
350 struct fdisk_label
*lb
;
355 if (!name
) { /* use default label creation */
364 fdisk_deinit_label(cxt
->label
);
368 lb
= fdisk_get_label(cxt
, name
);
369 if (!lb
|| lb
->disabled
)
372 if (!haslabel
|| (lb
&& cxt
->label
!= lb
))
373 fdisk_check_collisions(cxt
);
378 __fdisk_switch_label(cxt
, lb
);
379 assert(cxt
->label
== lb
);
381 if (haslabel
&& !cxt
->parent
)
382 fdisk_reset_device_properties(cxt
);
384 DBG(CXT
, ul_debugobj(cxt
, "create a new %s label", lb
->name
));
385 return lb
->op
->create(cxt
);
389 * fdisk_locate_disklabel:
392 * @name: return item name
393 * @offset: return offset where is item
396 * Locate disklabel and returns info about @n item of the label. For example
397 * GPT is composed from two items, PMBR and GPT, n=0 return offset to PMBR and n=1
398 * return offset to GPT. For more details see 'D' expert fdisk command.
400 * Returns: 0 on success, <0 on error, 1 no more items.
402 int fdisk_locate_disklabel(struct fdisk_context
*cxt
, int n
, const char **name
,
403 uint64_t *offset
, size_t *size
)
405 if (!cxt
|| !cxt
->label
)
407 if (!cxt
->label
->op
->locate
)
410 DBG(CXT
, ul_debugobj(cxt
, "locating %d chunk of %s.", n
, cxt
->label
->name
));
411 return cxt
->label
->op
->locate(cxt
, n
, name
, offset
, size
);
416 * fdisk_get_disklabel_id:
417 * @cxt: fdisk context
418 * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID)
420 * Returns: 0 on success, otherwise, a corresponding error.
422 int fdisk_get_disklabel_id(struct fdisk_context
*cxt
, char **id
)
424 struct fdisk_labelitem item
= FDISK_LABELITEM_INIT
;
427 if (!cxt
|| !cxt
->label
|| !id
)
430 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s ID", cxt
->label
->name
));
432 rc
= fdisk_get_disklabel_item(cxt
, FDISK_LABELITEM_ID
, &item
);
435 item
.data
.str
= NULL
;
437 fdisk_reset_labelitem(&item
);
444 * fdisk_get_disklabel_item:
445 * @cxt: fdisk context
446 * @id: item ID (FDISK_LABELITEM_* or *_LABELITEM_*)
447 * @item: specifies and returns the item
449 * Note that @id is always in range 0..N. It's fine to use the function in loop
450 * until it returns error or 2, the result in @item should be ignored when
451 * function returns 1. Don't forget to use fdisk_reset_labelitem() or fdisk_unref_labelitem().
453 * Returns: 0 on success, < 0 on error, 1 on unsupported item, 2 id out of range
455 int fdisk_get_disklabel_item(struct fdisk_context
*cxt
, int id
, struct fdisk_labelitem
*item
)
457 if (!cxt
|| !cxt
->label
|| !item
)
460 fdisk_reset_labelitem(item
);
462 DBG(CXT
, ul_debugobj(cxt
, "asking for disk %s item %d", cxt
->label
->name
, item
->id
));
464 if (!cxt
->label
->op
->get_item
)
467 return cxt
->label
->op
->get_item(cxt
, item
);
471 * fdisk_set_disklabel_id:
472 * @cxt: fdisk context
474 * Returns: 0 on success, otherwise, a corresponding error.
476 int fdisk_set_disklabel_id(struct fdisk_context
*cxt
)
478 if (!cxt
|| !cxt
->label
)
480 if (!cxt
->label
->op
->set_id
)
483 DBG(CXT
, ul_debugobj(cxt
, "setting %s disk ID", cxt
->label
->name
));
484 return cxt
->label
->op
->set_id(cxt
);
488 * fdisk_set_partition_type:
489 * @cxt: fdisk context
490 * @partnum: partition number
493 * Returns: 0 on success, < 0 on error.
495 int fdisk_set_partition_type(struct fdisk_context
*cxt
,
497 struct fdisk_parttype
*t
)
499 if (!cxt
|| !cxt
->label
|| !t
)
503 if (cxt
->label
->op
->set_part
) {
504 struct fdisk_partition
*pa
= fdisk_new_partition();
509 fdisk_partition_set_type(pa
, t
);
511 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: set type", partnum
));
512 rc
= cxt
->label
->op
->set_part(cxt
, partnum
, pa
);
513 fdisk_unref_partition(pa
);
522 * fdisk_toggle_partition_flag:
523 * @cxt: fdisk context
524 * @partnum: partition number
527 * Returns: 0 on success, otherwise, a corresponding error.
529 int fdisk_toggle_partition_flag(struct fdisk_context
*cxt
,
535 if (!cxt
|| !cxt
->label
)
537 if (!cxt
->label
->op
->part_toggle_flag
)
540 rc
= cxt
->label
->op
->part_toggle_flag(cxt
, partnum
, flag
);
542 DBG(CXT
, ul_debugobj(cxt
, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum
, flag
, rc
));
547 * fdisk_reorder_partitions
548 * @cxt: fdisk context
550 * Sort partitions according to the partition start sector.
552 * Returns: 0 on success, 1 reorder unnecessary, otherwise a corresponding error.
554 int fdisk_reorder_partitions(struct fdisk_context
*cxt
)
556 if (!cxt
|| !cxt
->label
)
558 if (!cxt
->label
->op
->reorder
)
561 return cxt
->label
->op
->reorder(cxt
);
565 * Resets the current used label driver to initial state
567 void fdisk_deinit_label(struct fdisk_label
*lb
)
571 /* private label information */
577 * fdisk_label_set_changed:
581 * Marks in-memory data as changed, to force fdisk_write_disklabel() to write
582 * to device. This should be unnecessary by default, the library keeps track
585 void fdisk_label_set_changed(struct fdisk_label
*lb
, int changed
)
588 lb
->changed
= changed
? 1 : 0;
592 * fdisk_label_is_changed:
595 * Returns: 1 if in-memory data has been changed.
597 int fdisk_label_is_changed(const struct fdisk_label
*lb
)
600 return lb
? lb
->changed
: 0;
604 * fdisk_label_set_disabled:
608 * Mark label as disabled, then libfdisk is going to ignore the label when
609 * probe device for labels.
611 void fdisk_label_set_disabled(struct fdisk_label
*lb
, int disabled
)
615 DBG(LABEL
, ul_debug("%s label %s",
617 disabled
? "DISABLED" : "ENABLED"));
618 lb
->disabled
= disabled
? 1 : 0;
622 * fdisk_label_is_disabled:
625 * Returns: 1 if label driver disabled.
627 int fdisk_label_is_disabled(const struct fdisk_label
*lb
)
630 return lb
? lb
->disabled
: 0;
634 * fdisk_label_get_geomrange_sectors:
636 * @mi: minimal number
637 * @ma: maximal number
639 * The function provides minimal and maximal geometry supported for the label,
640 * if no range defined by library than returns -ENOSYS.
644 * Returns: 0 on success, otherwise, a corresponding error.
646 int fdisk_label_get_geomrange_sectors(const struct fdisk_label
*lb
,
647 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
649 if (!lb
|| lb
->geom_min
.sectors
== 0)
652 *mi
= lb
->geom_min
.sectors
;
654 *ma
= lb
->geom_max
.sectors
;
659 * fdisk_label_get_geomrange_heads:
661 * @mi: minimal number
662 * @ma: maximal number
664 * The function provides minimal and maximal geometry supported for the label,
665 * if no range defined by library than returns -ENOSYS.
669 * Returns: 0 on success, otherwise, a corresponding error.
671 int fdisk_label_get_geomrange_heads(const struct fdisk_label
*lb
,
672 unsigned int *mi
, unsigned int *ma
)
674 if (!lb
|| lb
->geom_min
.heads
== 0)
677 *mi
= lb
->geom_min
.heads
;
679 *ma
= lb
->geom_max
.heads
;
684 * fdisk_label_get_geomrange_cylinders:
686 * @mi: minimal number
687 * @ma: maximal number
689 * The function provides minimal and maximal geometry supported for the label,
690 * if no range defined by library than returns -ENOSYS.
694 * Returns: 0 on success, otherwise, a corresponding error.
696 int fdisk_label_get_geomrange_cylinders(const struct fdisk_label
*lb
,
697 fdisk_sector_t
*mi
, fdisk_sector_t
*ma
)
699 if (!lb
|| lb
->geom_min
.cylinders
== 0)
702 *mi
= lb
->geom_min
.cylinders
;
704 *ma
= lb
->geom_max
.cylinders
;