summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/item.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfdisk/src/item.c')
-rw-r--r--libfdisk/src/item.c252
1 files changed, 252 insertions, 0 deletions
diff --git a/libfdisk/src/item.c b/libfdisk/src/item.c
new file mode 100644
index 0000000..86fa0fb
--- /dev/null
+++ b/libfdisk/src/item.c
@@ -0,0 +1,252 @@
+
+#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));
+
+ 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