diff options
Diffstat (limited to 'libfdisk')
-rw-r--r-- | libfdisk/docs/libfdisk-sections.txt | 31 | ||||
-rw-r--r-- | libfdisk/src/Makemodule.am | 9 | ||||
-rw-r--r-- | libfdisk/src/fdiskP.h | 4 | ||||
-rw-r--r-- | libfdisk/src/init.c | 1 | ||||
-rw-r--r-- | libfdisk/src/item.c | 243 | ||||
-rw-r--r-- | libfdisk/src/label.c | 11 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.h.in | 14 | ||||
-rw-r--r-- | libfdisk/src/libfdisk.sym | 10 |
8 files changed, 309 insertions, 14 deletions
diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt index 14d770b7e..7ae7d9a96 100644 --- a/libfdisk/docs/libfdisk-sections.txt +++ b/libfdisk/docs/libfdisk-sections.txt @@ -91,13 +91,6 @@ fdisk_get_nlabels fdisk_next_label fdisk_get_npartitions <SUBSECTION> -fdisk_field -fdisk_field_get_id -fdisk_field_get_name -fdisk_field_get_width -fdisk_field_is_number -fdisk_fieldtype -<SUBSECTION> fdisk_label fdisk_is_label fdisk_label_get_field @@ -347,3 +340,27 @@ fdisk_iter_get_direction fdisk_new_iter fdisk_reset_iter </SECTION> + +<SECTION> +<FILE>item</FILE> +fdisk_new_labelitem +fdisk_ref_labelitem +fdisk_reset_labelitem +fdisk_unref_labelitem +fdisk_labelitem_get_name +fdisk_labelitem_get_id +fdisk_labelitem_get_data_u64 +fdisk_labelitem_get_data_string +fdisk_labelitem_is_string +fdisk_labelitem_is_number +</SECTION> + +<SECTION> +<FILE>field</FILE> +fdisk_field +fdisk_field_get_id +fdisk_field_get_name +fdisk_field_get_width +fdisk_field_is_number +fdisk_fieldtype +</SECTION> diff --git a/libfdisk/src/Makemodule.am b/libfdisk/src/Makemodule.am index e24ae5620..e3baf9038 100644 --- a/libfdisk/src/Makemodule.am +++ b/libfdisk/src/Makemodule.am @@ -10,6 +10,7 @@ libfdisk_la_SOURCES = \ libfdisk/src/fdiskP.h \ libfdisk/src/init.c \ libfdisk/src/field.c \ + libfdisk/src/item.c \ libfdisk/src/test.c \ libfdisk/src/ask.c \ libfdisk/src/alignment.c \ @@ -72,7 +73,8 @@ check_PROGRAMS += \ test_fdisk_gpt \ test_fdisk_script \ test_fdisk_utils \ - test_fdisk_version + test_fdisk_version \ + test_fdisk_item libfdisk_tests_cflags = -DTEST_PROGRAM $(libfdisk_la_CFLAGS) $(NO_UNUSED_WARN_CFLAGS) libfdisk_tests_ldflags = libuuid.la -static @@ -107,6 +109,11 @@ test_fdisk_version_CFLAGS = $(libfdisk_tests_cflags) test_fdisk_version_LDFLAGS = $(libfdisk_tests_ldflags) test_fdisk_version_LDADD = $(libfdisk_tests_ldadd) +test_fdisk_item_SOURCES = libfdisk/src/item.c +test_fdisk_item_CFLAGS = $(libfdisk_tests_cflags) +test_fdisk_item_LDFLAGS = $(libfdisk_tests_ldflags) +test_fdisk_item_LDADD = $(libfdisk_tests_ldadd) + endif # BUILD_LIBFDISK_TESTS diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h index 6444c3d3e..e20723e61 100644 --- a/libfdisk/src/fdiskP.h +++ b/libfdisk/src/fdiskP.h @@ -39,6 +39,7 @@ #define LIBFDISK_DEBUG_TAB (1 << 8) #define LIBFDISK_DEBUG_SCRIPT (1 << 9) #define LIBFDISK_DEBUG_WIPE (1 << 10) +#define LIBFDISK_DEBUG_ITEM (1 << 11) #define LIBFDISK_DEBUG_ALL 0xFFFF UL_DEBUG_DECLARE_MASK(libfdisk); @@ -420,9 +421,10 @@ extern int fdisk_probe_labels(struct fdisk_context *cxt); extern void fdisk_deinit_label(struct fdisk_label *lb); struct fdisk_labelitem { + int refcount; /* reference counter */ int id; /* <label>_ITEM_* */ char type; /* s = string, j = uint64 */ - const char *name; + const char *name; /* human readable name */ union { char *str; diff --git a/libfdisk/src/init.c b/libfdisk/src/init.c index b4de57cd0..2bb25c700 100644 --- a/libfdisk/src/init.c +++ b/libfdisk/src/init.c @@ -22,6 +22,7 @@ UL_DEBUG_DEFINE_MASKNAMES(libfdisk) = { "script", LIBFDISK_DEBUG_SCRIPT, "sfdisk-like scripts" }, { "tab", LIBFDISK_DEBUG_TAB, "table utils"}, { "wipe", LIBFDISK_DEBUG_WIPE, "wipe area utils" }, + { "item", LIBFDISK_DEBUG_WIPE, "disklabel items" }, { NULL, 0 } }; diff --git a/libfdisk/src/item.c b/libfdisk/src/item.c new file mode 100644 index 000000000..6da00796d --- /dev/null +++ b/libfdisk/src/item.c @@ -0,0 +1,243 @@ + +#include "fdiskP.h" + +/** + * SECTION: labelitem + * @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: v2.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 + * + * Incremparts reference counter. + * + * Since: v2.29 + */ +void fdisk_ref_labelitem(struct fdisk_labelitem *li) +{ + if (li) + li->refcount++; +} + +/** + * fdisk_reset_labelitem: + * @li: label item + * + * Zeroize data stored in the @li (does not modify anything in disk label). + * + * Since: v2.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 + * + * De-incremparts reference counter, on zero the @li is automatically + * deallocated. + * + * Since: v2.29 + */ +void fdisk_unref_labelitem(struct fdisk_labelitem *li) +{ + if (!li) + return; + + 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: v2.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: v2.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: v2.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: v2.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 + */ +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 + */ +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: %ju\n", name, num); + break; + } + case 1: /* item unssuported 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 diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c index 3410ed9ba..78fc5e78c 100644 --- a/libfdisk/src/label.c +++ b/libfdisk/src/label.c @@ -321,10 +321,9 @@ int fdisk_list_disklabel(struct fdisk_context *cxt) case 's': if (item.data.str && item.name) fdisk_info(cxt, "%s: %s", item.name, item.data.str); - free(item.data.str); - item.data.str = NULL; break; } + fdisk_reset_labelitem(&item); } while (rc == 0 || rc == 1); return rc < 0 ? rc : 0; @@ -426,8 +425,11 @@ int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id) DBG(CXT, ul_debugobj(cxt, "asking for disk %s ID", cxt->label->name)); rc = fdisk_get_disklabel_item(cxt, FDISK_LABELITEM_ID, &item); - if (rc == 0) + if (rc == 0) { *id = item.data.str; + item.data.str = NULL; + } + fdisk_reset_labelitem(&item); if (rc > 0) rc = 0; return rc; @@ -441,7 +443,7 @@ int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id) * * Note that @id is always in range 0..N. It's fine to use the function in loop * until it returns error or 2, the result in @item should be ignored when - * function returns 1. + * function returns 1. Don't forget to use fdisk_reset_labelitem() or fdisk_unref_labelitem(). * * Returns: 0 on success, < 0 on error, 1 on unssupported item, 2 @id out of range */ @@ -450,6 +452,7 @@ int fdisk_get_disklabel_item(struct fdisk_context *cxt, int id, struct fdisk_lab if (!cxt || !cxt->label || !item) return -EINVAL; + fdisk_reset_labelitem(item); item->id = id; DBG(CXT, ul_debugobj(cxt, "asking for disk %s item %d", cxt->label->name, item->id)); diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in index 2e1a9b5ee..7de305a82 100644 --- a/libfdisk/src/libfdisk.h.in +++ b/libfdisk/src/libfdisk.h.in @@ -148,7 +148,6 @@ enum fdisk_asktype { FDISK_ASKTYPE_MENU /* ask for menu item */ }; - /* init.c */ extern void fdisk_init_debug(int mask); @@ -325,7 +324,20 @@ enum fdisk_labelitem_gen { __FDISK_NLABELITEMS = 8 /* Specifies reserved range for generic items (0..7) */ }; +/* item.c */ +extern struct fdisk_labelitem *fdisk_new_labelitem(void); +extern void fdisk_ref_labelitem(struct fdisk_labelitem *li); +extern int fdisk_reset_labelitem(struct fdisk_labelitem *li); +extern void fdisk_unref_labelitem(struct fdisk_labelitem *li); +extern const char *fdisk_labelitem_get_name(struct fdisk_labelitem *li); +extern int fdisk_labelitem_get_id(struct fdisk_labelitem *li); +extern int fdisk_labelitem_get_data_u64(struct fdisk_labelitem *li, uint64_t *data); +extern int fdisk_labelitem_get_data_string(struct fdisk_labelitem *li, const char **data); +extern int fdisk_labelitem_is_string(struct fdisk_labelitem *li); +extern int fdisk_labelitem_is_number(struct fdisk_labelitem *li); + extern int fdisk_get_disklabel_item(struct fdisk_context *cxt, int id, struct fdisk_labelitem *item); + extern int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id); extern int fdisk_set_disklabel_id(struct fdisk_context *cxt); diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym index c5aeac68e..49415b3d9 100644 --- a/libfdisk/src/libfdisk.sym +++ b/libfdisk/src/libfdisk.sym @@ -262,4 +262,14 @@ FDISK_2.28 { FDISK_2.29 { fdisk_wipe_partition; + fdisk_new_labelitem; + fdisk_ref_labelitem; + fdisk_reset_labelitem; + fdisk_unref_labelitem; + fdisk_labelitem_get_name; + fdisk_labelitem_get_id; + fdisk_labelitem_get_data_u64; + fdisk_labelitem_get_data_string; + fdisk_labelitem_is_string; + fdisk_labelitem_is_number; } FDISK_2.28; |