diff options
Diffstat (limited to 'libfdisk/src/item.c')
-rw-r--r-- | libfdisk/src/item.c | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/libfdisk/src/item.c b/libfdisk/src/item.c new file mode 100644 index 0000000..671f9ad --- /dev/null +++ b/libfdisk/src/item.c @@ -0,0 +1,255 @@ + +#include <inttypes.h> + +#include "fdiskP.h" + +/** + * SECTION: item + * @title: Labelitem + * @short_description: disk label items + * + * The labelitem is label specific items stored in the partition table header. + * The information provided by labelitems are not specific to the partitions. + * + * For example + * + * <informalexample> + * <programlisting> + * struct fdisk_labelitem *item = fdisk_new_labelitem(); + * + * fdisk_get_disklabel_item(cxt, GPT_LABELITEM_ALTLBA, item); + * print("Backup header LBA: %ju\n", fdisk_labelitem_get_data_u64(item)); + * + * fdisk_unref_labelitem(item); + * </programlisting> + * </informalexample> + * + * returns LBA of the alternative GPT header. + * + * See also fdisk_get_disklabel_item(). The IDs are generic (e.g. + * FDISK_LABEL_ITEM_*) and label specific ((e.g. GPT_LABELITEM_*). + */ + +/** + * fdisk_new_labelitem + * + * Returns: new instance. + * Since: 2.29 + */ +struct fdisk_labelitem *fdisk_new_labelitem(void) +{ + struct fdisk_labelitem *li = calloc(1, sizeof(*li)); + + if (!li) + return NULL; + + li->refcount = 1; + DBG(ITEM, ul_debugobj(li, "alloc")); + return li; +} + +/** + * fdisk_ref_labelitem: + * @li: label item + * + * Increments reference counter. + * Since: 2.29 + */ +void fdisk_ref_labelitem(struct fdisk_labelitem *li) +{ + if (li) { + /* me sure we do not use refcouting for static items */ + assert(li->refcount > 0); + li->refcount++; + } +} + +/** + * fdisk_reset_labelitem: + * @li: label item + * + * Zeroize data stored in the @li (does not modify anything in disk label). + * + * Returns: 0 on success, or <0 in case of error + * Since: 2.29 + */ +int fdisk_reset_labelitem(struct fdisk_labelitem *li) +{ + int refcount; + + if (!li) + return -EINVAL; + if (li->type == 's') + free(li->data.str); + + refcount = li->refcount; + memset(li, 0, sizeof(*li)); + li->refcount = refcount; + return 0; +} + +/** + * fdisk_unref_labelitem: + * @li: label item + * + * Decrements reference counter, on zero the @li is automatically + * deallocated. + * + * Since: 2.29 + */ +void fdisk_unref_labelitem(struct fdisk_labelitem *li) +{ + if (!li) + return; + + /* me sure we do not use refcouting for static items */ + assert(li->refcount > 0); + + li->refcount--; + if (li->refcount <= 0) { + DBG(ITEM, ul_debugobj(li, "free")); + fdisk_reset_labelitem(li); + free(li); + } +} + +/** + * fdisk_labelitem_get_name: + * @li: label item + * + * Returns: item name or NULL. + * Since: 2.29 + */ +const char *fdisk_labelitem_get_name(struct fdisk_labelitem *li) +{ + return li ? li->name : NULL; +} + +/** + * fdisk_labelitem_get_id: + * @li: label item + * + * Returns: item Id or <0 in case of error. + * Since: 2.29 + */ +int fdisk_labelitem_get_id(struct fdisk_labelitem *li) +{ + return li ? li->id : -EINVAL; +} + + +/** + * fdisk_labelitem_get_data_u64: + * @li: label item + * @data: returns data + * + * Returns: 0 on success, <0 on error + * Since: 2.29 + */ +int fdisk_labelitem_get_data_u64(struct fdisk_labelitem *li, uint64_t *data) +{ + if (!li || li->type != 'j') + return -EINVAL; + + if (data) + *data = li->data.num64; + return 0; +} + +/** + * fdisk_labelitem_get_data_string: + * @li: label item + * @data: returns data + * + * Returns: 0 on success, <0 on error. + * Since: 2.29 + */ +int fdisk_labelitem_get_data_string(struct fdisk_labelitem *li, const char **data) +{ + if (!li || li->type != 's') + return -EINVAL; + + if (data) + *data = li->data.str; + return 0; +} + +/** + * fdisk_labelitem_is_string: + * @li: label item + * + * Returns: 0 or 1 + * Since: 2.29 + */ +int fdisk_labelitem_is_string(struct fdisk_labelitem *li) +{ + return li && li->type == 's'; +} + +/** + * fdisk_labelitem_is_number: + * @li: label item + * + * Returns: 0 or 1 + * Since: 2.29 + */ +int fdisk_labelitem_is_number(struct fdisk_labelitem *li) +{ + return li && li->type == 'j'; +} + +#ifdef TEST_PROGRAM +static int test_listitems(struct fdisk_test *ts, int argc, char *argv[]) +{ + const char *disk = argv[1]; + struct fdisk_context *cxt; + struct fdisk_labelitem *item; + int i = 0, rc; + + cxt = fdisk_new_context(); + item = fdisk_new_labelitem(); + + fdisk_assign_device(cxt, disk, 1); + + do { + rc = fdisk_get_disklabel_item(cxt, i++, item); + switch (rc) { + case 0: /* success */ + { + const char *name = fdisk_labelitem_get_name(item); + const char *str; + uint64_t num; + + if (fdisk_labelitem_is_string(item) + && fdisk_labelitem_get_data_string(item, &str) == 0) + printf("%s: %s\n", name, str); + else if (fdisk_labelitem_get_data_u64(item, &num) == 0) + printf("%s: %"PRIu64"\n", name, num); + break; + } + case 1: /* item unsupported by label -- ignore */ + rc = 0; + break; + case 2: /* end (out of range) */ + break; + default: /* error */ + break; + } + } while (rc == 0); + + fdisk_unref_labelitem(item); + fdisk_unref_context(cxt); + return rc < 0 ? rc : 0; +} + +int main(int argc, char *argv[]) +{ + struct fdisk_test tss[] = { + { "--list-items", test_listitems, "<disk> list items" }, + { NULL } + }; + + return fdisk_run_test(tss, argc, argv); +} + +#endif |