summaryrefslogtreecommitdiffstats
path: root/libfdisk/src/partition.c
diff options
context:
space:
mode:
Diffstat (limited to 'libfdisk/src/partition.c')
-rw-r--r--libfdisk/src/partition.c137
1 files changed, 132 insertions, 5 deletions
diff --git a/libfdisk/src/partition.c b/libfdisk/src/partition.c
index 5e41eed0d..4fbd1e468 100644
--- a/libfdisk/src/partition.c
+++ b/libfdisk/src/partition.c
@@ -2,6 +2,10 @@
#include "c.h"
#include "strutils.h"
+#ifdef HAVE_LIBBLKID
+# include <blkid.h>
+#endif
+
#include "fdiskP.h"
/**
@@ -63,6 +67,9 @@ void fdisk_reset_partition(struct fdisk_partition *pa)
free(pa->name);
free(pa->uuid);
free(pa->attrs);
+ free(pa->fstype);
+ free(pa->fsuuid);
+ free(pa->fslabel);
memset(pa, 0, sizeof(*pa));
pa->refcount = ref;
@@ -85,6 +92,13 @@ static struct fdisk_partition *__copy_partition(struct fdisk_partition *o)
n->uuid = strdup(o->uuid);
if (o->attrs)
n->attrs = strdup(o->attrs);
+ if (o->fstype)
+ n->fstype = strdup(o->fstype);
+ if (o->fsuuid)
+ n->fsuuid = strdup(o->fsuuid);
+ if (o->fslabel)
+ n->fslabel = strdup(o->fslabel);
+
return n;
}
@@ -127,7 +141,7 @@ void fdisk_unref_partition(struct fdisk_partition *pa)
* @off: offset in sectors, maximal is UINT64_MAX-1
*
* Note that zero is valid offset too. Use fdisk_partition_unset_start() to
- * undefine the offset.
+ * undefine the offset.
*
* Returns: 0 on success, <0 on error.
*/
@@ -138,6 +152,7 @@ int fdisk_partition_set_start(struct fdisk_partition *pa, fdisk_sector_t off)
if (FDISK_IS_UNDEF(off))
return -ERANGE;
pa->start = off;
+ pa->fs_probed = 0;
return 0;
}
@@ -154,6 +169,7 @@ int fdisk_partition_unset_start(struct fdisk_partition *pa)
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->start);
+ pa->fs_probed = 0;
return 0;
}
@@ -259,6 +275,7 @@ int fdisk_partition_set_size(struct fdisk_partition *pa, fdisk_sector_t sz)
if (FDISK_IS_UNDEF(sz))
return -ERANGE;
pa->size = sz;
+ pa->fs_probed = 0;
return 0;
}
@@ -275,6 +292,7 @@ int fdisk_partition_unset_size(struct fdisk_partition *pa)
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->size);
+ pa->fs_probed = 0;
return 0;
}
@@ -724,6 +742,60 @@ int fdisk_partition_next_partno(
return 0;
}
+static int probe_partition_content(struct fdisk_context *cxt, struct fdisk_partition *pa)
+{
+ int rc = 1; /* nothing */
+
+ DBG(PART, ul_debugobj(pa, "start probe #%zu partition [cxt %p] >>>", pa->partno, cxt));
+
+ /* zeroize the current setting */
+ strdup_to_struct_member(pa, fstype, NULL);
+ strdup_to_struct_member(pa, fsuuid, NULL);
+ strdup_to_struct_member(pa, fslabel, NULL);
+
+ if (!fdisk_partition_has_start(pa) ||
+ !fdisk_partition_has_size(pa))
+ goto done;
+
+#ifdef HAVE_LIBBLKID
+ else {
+ uintmax_t start, size;
+
+ blkid_probe pr = blkid_new_probe();
+ if (!pr)
+ goto done;
+
+ DBG(PART, ul_debugobj(pa, "blkid prober: %p", pr));
+
+ start = fdisk_partition_get_start(pa) * fdisk_get_sector_size(cxt);
+ size = fdisk_partition_get_size(pa) * fdisk_get_sector_size(cxt);
+
+ if (blkid_probe_set_device(pr, cxt->dev_fd, start, size) == 0
+ && blkid_do_fullprobe(pr) == 0) {
+
+ const char *data;
+ rc = 0;
+
+ if (!blkid_probe_lookup_value(pr, "TYPE", &data, NULL))
+ rc = strdup_to_struct_member(pa, fstype, data);
+
+ if (!rc && !blkid_probe_lookup_value(pr, "LABEL", &data, NULL))
+ rc = strdup_to_struct_member(pa, fslabel, data);
+
+ if (!rc && !blkid_probe_lookup_value(pr, "UUID", &data, NULL))
+ rc = strdup_to_struct_member(pa, fsuuid, data);
+ }
+
+ blkid_free_probe(pr);
+ pa->fs_probed = 1;
+ }
+#endif /* HAVE_LIBBLKID */
+
+done:
+ DBG(PART, ul_debugobj(pa, "<<< end probe #%zu partition[cxt %p, rc=%d]", pa->partno, cxt, rc));
+ return rc;
+}
+
/**
* fdisk_partition_to_string:
* @pa: partition
@@ -859,6 +931,18 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
case FDISK_FIELD_EADDR:
p = pa->end_chs && *pa->end_chs? strdup(pa->end_chs) : NULL;
break;
+ case FDISK_FIELD_FSUUID:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fsuuid && *pa->fsuuid ? strdup(pa->fsuuid) : NULL;
+ break;
+ case FDISK_FIELD_FSLABEL:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fslabel && *pa->fslabel ? strdup(pa->fslabel) : NULL;
+ break;
+ case FDISK_FIELD_FSTYPE:
+ if (pa->fs_probed || probe_partition_content(cxt, pa) == 0)
+ p = pa->fstype && *pa->fstype ? strdup(pa->fstype) : NULL;
+ break;
default:
return -EINVAL;
}
@@ -876,6 +960,7 @@ int fdisk_partition_to_string(struct fdisk_partition *pa,
return rc;
}
+
/**
* fdisk_get_partition:
* @cxt: context
@@ -1140,14 +1225,16 @@ erange:
int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
struct fdisk_partition *pa)
{
- struct fdisk_partition *xpa = pa;
- int rc;
+ struct fdisk_partition *xpa = pa, *tmp = NULL;
+ int rc, wipe = 0;
if (!cxt || !cxt->label || !pa)
return -EINVAL;
if (!cxt->label->op->set_part)
return -ENOSYS;
+ pa->fs_probed = 0;
+
if (pa->resize || fdisk_partition_has_start(pa) || fdisk_partition_has_size(pa)) {
xpa = __copy_partition(pa);
xpa->movestart = 0;
@@ -1166,7 +1253,19 @@ int fdisk_set_partition(struct fdisk_context *cxt, size_t partno,
(uintmax_t) fdisk_partition_get_end(xpa),
(uintmax_t) fdisk_partition_get_size(xpa)));
+ /* disable wipe for old offset/size setting */
+ if (fdisk_get_partition(cxt, partno, &tmp) == 0 && tmp) {
+ wipe = fdisk_set_wipe_area(cxt, fdisk_partition_get_start(tmp),
+ fdisk_partition_get_size(tmp), FALSE);
+ fdisk_unref_partition(tmp);
+ }
+
+ /* call label driver */
rc = cxt->label->op->set_part(cxt, partno, xpa);
+
+ /* enable wipe for new offset/size */
+ if (!rc && wipe)
+ fdisk_wipe_partition(cxt, partno, TRUE);
done:
DBG(CXT, ul_debugobj(cxt, "set_partition() rc=%d", rc));
if (xpa != pa)
@@ -1174,6 +1273,31 @@ done:
return rc;
}
+/**
+ * fdisk_wipe_partition:
+ * @cxt: fdisk context
+ * @partno: partition number
+ * @enable: 0 or 1
+ *
+ * Enable/disable filesystems/RAIDs wiping in area defined by partition start and size.
+ *
+ * Returns: <0 in case of error, 0 on success
+ */
+int fdisk_wipe_partition(struct fdisk_context *cxt, size_t partno, int enable)
+{
+ struct fdisk_partition *pa = NULL;
+ int rc;
+
+ rc = fdisk_get_partition(cxt, partno, &pa);
+ if (rc)
+ return rc;
+
+ rc = fdisk_set_wipe_area(cxt, fdisk_partition_get_start(pa),
+ fdisk_partition_get_size(pa), enable);
+ fdisk_unref_partition(pa);
+ return rc < 0 ? rc : 0;
+}
+
/**
* fdisk_add_partition:
@@ -1201,7 +1325,8 @@ int fdisk_add_partition(struct fdisk_context *cxt,
if (fdisk_missing_geometry(cxt))
return -EINVAL;
- if (pa)
+ if (pa) {
+ pa->fs_probed = 0;
DBG(CXT, ul_debugobj(cxt, "adding new partition %p (start=%ju, end=%ju, size=%ju, "
"defaults(start=%s, end=%s, partno=%s)",
pa,
@@ -1211,7 +1336,7 @@ int fdisk_add_partition(struct fdisk_context *cxt,
pa->start_follow_default ? "yes" : "no",
pa->end_follow_default ? "yes" : "no",
pa->partno_follow_default ? "yes" : "no"));
- else
+ } else
DBG(CXT, ul_debugobj(cxt, "adding partition"));
rc = cxt->label->op->add_part(cxt, pa, partno);
@@ -1236,6 +1361,8 @@ int fdisk_delete_partition(struct fdisk_context *cxt, size_t partno)
if (!cxt->label->op->del_part)
return -ENOSYS;
+ fdisk_wipe_partition(cxt, partno, 0);
+
DBG(CXT, ul_debugobj(cxt, "deleting %s partition number %zd",
cxt->label->name, partno));
return cxt->label->op->del_part(cxt, partno);