blob: 86fa0fb1f75801e5b5f787139b78595395e29147 [file] [log] [blame]
#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