Update blkid to 2.25.0
Break libblkid into 4 libraries: libblkid, libuuid, libutil-linux and libfdisk.

This should help in later patch updates.

Change-Id: I680d9a7feb031e5c29a603e9c58aff4b65826262
diff --git a/libblkid/libfdisk/src/label.c b/libblkid/libfdisk/src/label.c
new file mode 100644
index 0000000..750cfca
--- /dev/null
+++ b/libblkid/libfdisk/src/label.c
@@ -0,0 +1,569 @@
+
+#include "fdiskP.h"
+
+
+/**
+ * SECTION: label
+ * @title: Label
+ * @short_description: disk label (PT) specific data and functions
+ *
+ * The fdisk_new_context() initializes all label drivers, and allocate
+ * per-label specific data struct. This concept allows to store label specific
+ * settings to the label driver independently on the currently active label
+ * driver. Note that label struct cannot be deallocated, so there is no
+ * reference counting for fdisk_label objects. All is destroyed by
+ * fdisk_unref_context() only.
+ *
+ * Anyway, all label drives share in-memory first sector. The function
+ * fdisk_create_disklabel() overwrites the sector. But it's possible that
+ * label driver also uses another buffers, for example GPT uses more than only
+ * the first sector.
+ *
+ * All label operations are in-memory only, except fdisk_write_disklabel().
+ *
+ * All functions that use "struct fdisk_context" rather than "struct
+ * fdisk_label" use the currently active label driver.
+ */
+
+
+int fdisk_probe_labels(struct fdisk_context *cxt)
+{
+	size_t i;
+
+	cxt->label = NULL;
+
+	for (i = 0; i < cxt->nlabels; i++) {
+		struct fdisk_label *lb = cxt->labels[i];
+		struct fdisk_label *org = fdisk_get_label(cxt, NULL);
+		int rc;
+
+		if (!lb->op->probe)
+			continue;
+		if (lb->disabled) {
+			DBG(CXT, ul_debugobj(cxt, "%s: disabled -- ignore", lb->name));
+			continue;
+		}
+		DBG(CXT, ul_debugobj(cxt, "probing for %s", lb->name));
+
+		cxt->label = lb;
+		rc = lb->op->probe(cxt);
+		cxt->label = org;
+
+		if (rc != 1) {
+			if (lb->op->deinit)
+				lb->op->deinit(lb);	/* for sure */
+			continue;
+		}
+
+		__fdisk_switch_label(cxt, lb);
+		return 0;
+	}
+
+	DBG(CXT, ul_debugobj(cxt, "no label found"));
+	return 1; /* not found */
+}
+
+/**
+ * fdisk_label_get_name:
+ * @lb: label
+ *
+ * Returns: label name
+ */
+const char *fdisk_label_get_name(const struct fdisk_label *lb)
+{
+	return lb ? lb->name : NULL;
+}
+
+/**
+ * fdisk_label_is_labeltype:
+ * @lb: label
+ *
+ * Returns: FDISK_DISKLABEL_*.
+ */
+int fdisk_label_get_type(const struct fdisk_label *lb)
+{
+	return lb->id;
+}
+
+/**
+ * fdisk_label_require_geometry:
+ * @lb: label
+ *
+ * Returns: 1 if label requires CHS geometry
+ */
+int fdisk_label_require_geometry(const struct fdisk_label *lb)
+{
+	assert(lb);
+
+	return lb->flags & FDISK_LABEL_FL_REQUIRE_GEOMETRY ? 1 : 0;
+}
+
+/**
+ * fdisk_label_get_fields_ids
+ * @lb: label (or NULL for the current label)
+ * @cxt: context
+ * @ids: returns allocated array with FDISK_FIELD_* IDs
+ * @nids: returns number of items in fields
+ *
+ * This function returns the default fields for the label.
+ *
+ * Note that the set of the default fields depends on fdisk_enable_details()
+ * function. If the details are enabled then this function usually returns more
+ * fields.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_label_get_fields_ids(
+		const struct fdisk_label *lb,
+		struct fdisk_context *cxt,
+		int **ids, size_t *nids)
+{
+	size_t i, n;
+	int *c;
+
+	assert(cxt);
+
+	if (!lb)
+		lb = cxt->label;
+	if (!lb)
+		return -EINVAL;
+	if (!lb->fields || !lb->nfields)
+		return -ENOSYS;
+	c = calloc(lb->nfields, sizeof(int));
+	if (!c)
+		return -ENOMEM;
+	for (n = 0, i = 0; i < lb->nfields; i++) {
+		int id = lb->fields[i].id;
+
+		if ((fdisk_is_details(cxt) &&
+				(lb->fields[i].flags & FDISK_FIELDFL_EYECANDY))
+		     || (!fdisk_is_details(cxt) &&
+				(lb->fields[i].flags & FDISK_FIELDFL_DETAIL))
+		     || (id == FDISK_FIELD_SECTORS &&
+			         fdisk_use_cylinders(cxt))
+		     || (id == FDISK_FIELD_CYLINDERS &&
+			         !fdisk_use_cylinders(cxt)))
+			continue;
+
+		c[n++] = id;
+	}
+	if (ids)
+		*ids = c;
+	else
+		free(c);
+	if (nids)
+		*nids = n;
+	return 0;
+}
+
+/**
+ * fdisk_label_get_field:
+ * @lb: label
+ * @id: FDISK_FIELD_*
+ *
+ * The field struct describes data stored in struct fdisk_partition. The info
+ * about data is usable for example to generate human readable output (e.g.
+ * fdisk 'p'rint command). See fdisk_partition_to_stirng() and fdisk code.
+ *
+ * Returns: pointer to static instance of the field.
+ */
+const struct fdisk_field *fdisk_label_get_field(const struct fdisk_label *lb, int id)
+{
+	size_t i;
+
+	assert(lb);
+	assert(id > 0);
+
+	for (i = 0; i < lb->nfields; i++) {
+		if (lb->fields[i].id == id)
+			return &lb->fields[i];
+	}
+
+	return NULL;
+}
+
+/**
+ * fdisk_label_get_field_by_name
+ * @lb: label
+ * @name: field name
+ *
+ * Returns: pointer to static instance of the field.
+ */
+const struct fdisk_field *fdisk_label_get_field_by_name(
+				const struct fdisk_label *lb,
+				const char *name)
+{
+	size_t i;
+
+	assert(lb);
+	assert(name);
+
+	for (i = 0; i < lb->nfields; i++) {
+		if (lb->fields[i].name && strcasecmp(lb->fields[i].name, name) == 0)
+			return &lb->fields[i];
+	}
+
+	return NULL;
+}
+
+
+/**
+ * fdisk_field_get_id:
+ * @field: field instance
+ *
+ * Returns: field Id (FDISK_FIELD_*)
+ */
+int fdisk_field_get_id(const struct fdisk_field *field)
+{
+	return field ? field->id : -EINVAL;
+}
+
+/**
+ * fdisk_field_get_name:
+ * @field: field instance
+ *
+ * Returns: field name
+ */
+const char *fdisk_field_get_name(const struct fdisk_field *field)
+{
+	return field ? field->name : NULL;
+}
+
+/**
+ * fdisk_field_get_width:
+ * @field: field instance
+ *
+ * Returns: libsmartcols compatible width.
+ */
+double fdisk_field_get_width(const struct fdisk_field *field)
+{
+	return field ? field->width : -EINVAL;
+}
+
+/**
+ * fdisk_field_is_number:
+ * @field: field instance
+ *
+ * Returns: 1 if field represent number
+ */
+int fdisk_field_is_number(const struct fdisk_field *field)
+{
+	return field->flags ? field->flags & FDISK_FIELDFL_NUMBER : 0;
+}
+
+
+/**
+ * fdisk_write_disklabel:
+ * @cxt: fdisk context
+ *
+ * Write in-memory changes to disk. Be careful!
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_write_disklabel(struct fdisk_context *cxt)
+{
+	if (!cxt || !cxt->label || cxt->readonly)
+		return -EINVAL;
+	if (!cxt->label->op->write)
+		return -ENOSYS;
+	return cxt->label->op->write(cxt);
+}
+
+/**
+ * fdisk_verify_disklabel:
+ * @cxt: fdisk context
+ *
+ * Verifies the partition table.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_verify_disklabel(struct fdisk_context *cxt)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->verify)
+		return -ENOSYS;
+	if (fdisk_missing_geometry(cxt))
+		return -EINVAL;
+
+	return cxt->label->op->verify(cxt);
+}
+
+/**
+ * fdisk_list_disklabel:
+ * @cxt: fdisk context
+ *
+ * Lists details about disklabel, but no partitions.
+ *
+ * This function uses libfdisk ASK interface to print data. The details about
+ * partitions table are printed by FDISK_ASKTYPE_INFO.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_list_disklabel(struct fdisk_context *cxt)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->list)
+		return -ENOSYS;
+
+	return cxt->label->op->list(cxt);
+}
+
+/**
+ * fdisk_create_disklabel:
+ * @cxt: fdisk context
+ * @name: label name
+ *
+ * Creates a new disk label of type @name. If @name is NULL, then it will
+ * create a default system label type, either SUN or DOS. The function
+ * automaticaly switches the current label driver to @name. The function
+ * fdisk_get_label() returns the current label driver.
+ *
+ * The function modifies in-memory data only.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_create_disklabel(struct fdisk_context *cxt, const char *name)
+{
+	int haslabel = 0;
+	struct fdisk_label *lb;
+
+	if (!cxt)
+		return -EINVAL;
+
+	if (!name) { /* use default label creation */
+#ifdef __sparc__
+		name = "sun";
+#else
+		name = "dos";
+#endif
+	}
+
+	if (cxt->label) {
+		fdisk_deinit_label(cxt->label);
+		haslabel = 1;
+	}
+
+	lb = fdisk_get_label(cxt, name);
+	if (!lb || lb->disabled)
+		return -EINVAL;
+	if (!lb->op->create)
+		return -ENOSYS;
+
+	__fdisk_switch_label(cxt, lb);
+
+	if (haslabel && !cxt->parent)
+		fdisk_reset_device_properties(cxt);
+
+	DBG(CXT, ul_debugobj(cxt, "create a new %s label", lb->name));
+	return cxt->label->op->create(cxt);
+}
+
+/**
+ * fdisk_locate_disklabel:
+ * @cxt: context
+ * @n: N item
+ * @name: return item name
+ * @offset: return offset where is item
+ * @size: of the item
+ *
+ * Locate disklabel and returns info about @n item of the label. For example
+ * GPT is composed from two items, PMBR and GPT, n=0 return offset to PMBR and n=1
+ * return offset to GPT. For more details see 'D' expect fdisk command.
+ *
+ * Returns: 0 on succes, <0 on error, 1 no more items.
+ */
+int fdisk_locate_disklabel(struct fdisk_context *cxt, int n, const char **name,
+			   off_t *offset, size_t *size)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->locate)
+		return -ENOSYS;
+
+	DBG(CXT, ul_debugobj(cxt, "locating %d chunk of %s.", n, cxt->label->name));
+	return cxt->label->op->locate(cxt, n, name, offset, size);
+}
+
+
+/**
+ * fdisk_get_disklabel_id:
+ * @cxt: fdisk context
+ * @id: returns pointer to allocated string (MBR Id or GPT dirk UUID)
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_get_disklabel_id(struct fdisk_context *cxt, char **id)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->get_id)
+		return -ENOSYS;
+
+	DBG(CXT, ul_debugobj(cxt, "asking for disk %s ID", cxt->label->name));
+	return cxt->label->op->get_id(cxt, id);
+}
+
+/**
+ * fdisk_set_disklabel_id:
+ * @cxt: fdisk context
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_set_disklabel_id(struct fdisk_context *cxt)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->set_id)
+		return -ENOSYS;
+
+	DBG(CXT, ul_debugobj(cxt, "setting %s disk ID", cxt->label->name));
+	return cxt->label->op->set_id(cxt);
+}
+
+/**
+ * fdisk_set_partition_type:
+ * @cxt: fdisk context
+ * @partnum: partition number
+ * @t: new type
+ *
+ * Returns: 0 on success, < 0 on error.
+ */
+int fdisk_set_partition_type(struct fdisk_context *cxt,
+			     size_t partnum,
+			     struct fdisk_parttype *t)
+{
+	if (!cxt || !cxt->label || !t)
+		return -EINVAL;
+
+
+	if (cxt->label->op->set_part) {
+		struct fdisk_partition *pa = fdisk_new_partition();
+		int rc;
+
+		if (!pa)
+			return -ENOMEM;
+		fdisk_partition_set_type(pa, t);
+
+		DBG(CXT, ul_debugobj(cxt, "partition: %zd: set type", partnum));
+		rc = cxt->label->op->set_part(cxt, partnum, pa);
+		fdisk_unref_partition(pa);
+		return rc;
+	}
+
+	return -ENOSYS;
+}
+
+
+/**
+ * fdisk_toggle_partition_flag:
+ * @cxt: fdisk context
+ * @partnum: partition number
+ * @flag: flag ID
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_toggle_partition_flag(struct fdisk_context *cxt,
+			       size_t partnum,
+			       unsigned long flag)
+{
+	int rc;
+
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->part_toggle_flag)
+		return -ENOSYS;
+
+	rc = cxt->label->op->part_toggle_flag(cxt, partnum, flag);
+
+	DBG(CXT, ul_debugobj(cxt, "partition: %zd: toggle: 0x%04lx [rc=%d]", partnum, flag, rc));
+	return rc;
+}
+
+/**
+ * fdisk_reorder_partitions
+ * @cxt: fdisk context
+ *
+ * Sort partitions according to the partition start sector.
+ *
+ * Returns: 0 on success, otherwise, a corresponding error.
+ */
+int fdisk_reorder_partitions(struct fdisk_context *cxt)
+{
+	if (!cxt || !cxt->label)
+		return -EINVAL;
+	if (!cxt->label->op->reorder)
+		return -ENOSYS;
+
+	return cxt->label->op->reorder(cxt);
+}
+
+/*
+ * Resets the current used label driver to initial state
+ */
+void fdisk_deinit_label(struct fdisk_label *lb)
+{
+	assert(lb);
+
+	/* private label information */
+	if (lb->op->deinit)
+		lb->op->deinit(lb);
+}
+
+/**
+ * fdisk_label_set_changed:
+ * @lb: label
+ * @changed: 0/1
+ *
+ * Marks in-memory data as changed, to force fdisk_write_disklabel() to write
+ * to device. This should be unnecessar by default, the library keeps track
+ * about changes.
+ */
+void fdisk_label_set_changed(struct fdisk_label *lb, int changed)
+{
+	assert(lb);
+	lb->changed = changed ? 1 : 0;
+}
+
+/**
+ * fdisk_label_is_changed:
+ * @lb: label
+ *
+ * Returns: 1 if in-memory data has been changed.
+ */
+int fdisk_label_is_changed(const struct fdisk_label *lb)
+{
+	assert(lb);
+	return lb ? lb->changed : 0;
+}
+
+/**
+ * fdisk_label_set_disabled:
+ * @lb: label
+ * @disabled: 0 or 1
+ *
+ * Mark label as disabled, then libfdisk is going to ignore the label when
+ * probe device for labels.
+ */
+void fdisk_label_set_disabled(struct fdisk_label *lb, int disabled)
+{
+	assert(lb);
+
+	DBG(LABEL, ul_debug("%s label %s",
+				lb->name,
+				disabled ? "DISABLED" : "ENABLED"));
+	lb->disabled = disabled ? 1 : 0;
+}
+
+/**
+ * fdisk_label_is_disabled:
+ * @lb: label
+ *
+ * Returns: 1 if label driver disabled.
+ */
+int fdisk_label_is_disabled(const struct fdisk_label *lb)
+{
+	assert(lb);
+	return lb ? lb->disabled : 0;
+}