summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
authorKarel Zak2016-05-04 12:32:52 +0200
committerKarel Zak2016-05-04 12:32:52 +0200
commit131e38a28ea055548a098611eeba94078a17c19d (patch)
tree73a6f3d50e0b961740f1970d2a7f79abe93f2a3d /libfdisk
parentlibblkid: make I/O errors on CDROMs non-fatal (diff)
downloadkernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.tar.gz
kernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.tar.xz
kernel-qcow2-util-linux-131e38a28ea055548a098611eeba94078a17c19d.zip
libfdisk: add fdisk_wipe_partition()
Now libfdisk provides functionality wipe disk device only ([s]fdisk option --wipe). This patch allows to probe for filesystems/RAIDs on newly created partitions. It means we can remove signatures before the partition node (device) is created. This reduces udev events and it's unnecessary to call wipefs for all partitions. For example sfdisk --wipe=always --wipe-partitions=always /dev/sda <<< ... EOF is a elegant way how to create new disk layout without any obsolete filesystems/RAIDs. Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'libfdisk')
-rw-r--r--libfdisk/docs/libfdisk-sections.txt1
-rw-r--r--libfdisk/src/Makemodule.am1
-rw-r--r--libfdisk/src/context.c57
-rw-r--r--libfdisk/src/fdiskP.h16
-rw-r--r--libfdisk/src/init.c1
-rw-r--r--libfdisk/src/label.c6
-rw-r--r--libfdisk/src/libfdisk.h.in8
-rw-r--r--libfdisk/src/libfdisk.sym4
-rw-r--r--libfdisk/src/partition.c137
-rw-r--r--libfdisk/src/wipe.c143
10 files changed, 324 insertions, 50 deletions
diff --git a/libfdisk/docs/libfdisk-sections.txt b/libfdisk/docs/libfdisk-sections.txt
index dd8df21ef..14d770b7e 100644
--- a/libfdisk/docs/libfdisk-sections.txt
+++ b/libfdisk/docs/libfdisk-sections.txt
@@ -162,6 +162,7 @@ fdisk_delete_partition
fdisk_get_partition
fdisk_is_partition_used
fdisk_set_partition
+fdisk_wipe_partition
<SUBSECTION>
fdisk_partition
fdisk_new_partition
diff --git a/libfdisk/src/Makemodule.am b/libfdisk/src/Makemodule.am
index bc7f1a378..d7e7f16d8 100644
--- a/libfdisk/src/Makemodule.am
+++ b/libfdisk/src/Makemodule.am
@@ -21,6 +21,7 @@ libfdisk_la_SOURCES = \
libfdisk/src/iter.c \
libfdisk/src/script.c \
libfdisk/src/version.c \
+ libfdisk/src/wipe.c \
\
libfdisk/src/sun.c \
libfdisk/src/sgi.c \
diff --git a/libfdisk/src/context.c b/libfdisk/src/context.c
index 88b9f8afb..26f526a78 100644
--- a/libfdisk/src/context.c
+++ b/libfdisk/src/context.c
@@ -47,6 +47,8 @@ struct fdisk_context *fdisk_new_context(void)
cxt->dev_fd = -1;
cxt->refcount = 1;
+ INIT_LIST_HEAD(&cxt->wipes);
+
/*
* Allocate label specific structs.
*
@@ -112,6 +114,8 @@ static int init_nested_from_parent(struct fdisk_context *cxt, int isnew)
return -ENOMEM;
}
+ INIT_LIST_HEAD(&cxt->wipes);
+
return 0;
}
@@ -339,9 +343,15 @@ int fdisk_enable_bootbits_protection(struct fdisk_context *cxt, int enable)
* @cxt: fdisk context
* @enable: 1 or 0
*
- * The library removes all filesystem/RAID signatures before write PT. This is
- * no-op if any collision has not been detected by fdisk_assign_device(). See
- * fdisk_has_collision(). The default is not wipe a device.
+ * The library removes all filesystem/RAID signatures before it writes
+ * partition table. The probing area where it looks for filesystem/RAID is from
+ * the begin of the disk. The device is wiped by libblkid.
+ *
+ * See also fdisk_wipe_partition().
+ *
+ * This is no-op if any collision has not been detected by
+ * fdisk_assign_device(). See fdisk_has_collision(). The default is not wipe a
+ * device.
*
* Returns: 0 on success, < 0 on error.
*/
@@ -349,7 +359,8 @@ int fdisk_enable_wipe(struct fdisk_context *cxt, int enable)
{
if (!cxt)
return -EINVAL;
- cxt->wipe_device = enable ? 1 : 0;
+
+ fdisk_set_wipe_area(cxt, 0, cxt->total_sectors * cxt->sector_size, enable);
return 0;
}
@@ -363,7 +374,10 @@ int fdisk_enable_wipe(struct fdisk_context *cxt, int enable)
*/
int fdisk_has_wipe(struct fdisk_context *cxt)
{
- return cxt && cxt->wipe_device;
+ if (!cxt)
+ return 0;
+
+ return fdisk_has_wipe_area(cxt, 0, cxt->total_sectors * cxt->sector_size);
}
@@ -484,6 +498,8 @@ static void reset_context(struct fdisk_context *cxt)
cxt->script = NULL;
cxt->label = NULL;
+
+ fdisk_free_wipe_areas(cxt);
}
/*
@@ -535,37 +551,6 @@ static int check_collisions(struct fdisk_context *cxt)
#endif
}
-int fdisk_wipe_collisions(struct fdisk_context *cxt)
-{
-#ifdef HAVE_LIBBLKID
- blkid_probe pr;
- int rc;
-
- assert(cxt);
- assert(cxt->dev_fd >= 0);
-
- DBG(CXT, ul_debugobj(cxt, "wipe: initialize libblkid prober"));
-
- pr = blkid_new_probe();
- if (!pr)
- return -ENOMEM;
- rc = blkid_probe_set_device(pr, cxt->dev_fd, 0, 0);
- if (rc)
- return rc;
-
- blkid_probe_enable_superblocks(pr, 1);
- blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
- blkid_probe_enable_partitions(pr, 1);
- blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
-
- while (blkid_do_probe(pr) == 0)
- blkid_do_wipe(pr, FALSE);
-
- blkid_free_probe(pr);
-#endif
- return 0;
-}
-
/**
* fdisk_assign_device:
* @cxt: context
diff --git a/libfdisk/src/fdiskP.h b/libfdisk/src/fdiskP.h
index 85c38492a..6444c3d3e 100644
--- a/libfdisk/src/fdiskP.h
+++ b/libfdisk/src/fdiskP.h
@@ -38,6 +38,7 @@
#define LIBFDISK_DEBUG_PARTTYPE (1 << 7)
#define LIBFDISK_DEBUG_TAB (1 << 8)
#define LIBFDISK_DEBUG_SCRIPT (1 << 9)
+#define LIBFDISK_DEBUG_WIPE (1 << 10)
#define LIBFDISK_DEBUG_ALL 0xFFFF
UL_DEBUG_DECLARE_MASK(libfdisk);
@@ -121,6 +122,10 @@ struct fdisk_partition {
char *attrs; /* partition flags/attributes converted to string */
struct fdisk_parttype *type; /* partition type */
+ char *fstype; /* filesystem type */
+ char *fsuuid; /* filesystem uuid */
+ char *fslabel; /* filesystem label */
+
struct list_head parts; /* list of partitions */
/* extra fields for partition_to_string() */
@@ -143,6 +148,7 @@ struct fdisk_partition {
partno_follow_default : 1, /* use default partno */
size_explicit : 1, /* don't align the size */
start_follow_default : 1, /* use default start */
+ fs_probed : 1, /* already probed by blkid */
used : 1, /* partition already used */
wholedisk : 1; /* special system partition */
};
@@ -355,10 +361,10 @@ struct fdisk_context {
display_in_cyl_units : 1, /* for obscure labels */
display_details : 1, /* expert display mode */
protect_bootbits : 1, /* don't zeroize fll irst sector */
- wipe_device : 1, /* wipe device before write */
listonly : 1; /* list partition, nothing else */
char *collision; /* name of already existing FS/PT */
+ struct list_head wipes; /* list of areas to wipe before write */
int sizeunit; /* SIZE fields, FDISK_SIZEUNIT_* */
@@ -389,8 +395,6 @@ struct fdisk_context {
struct fdisk_script *script; /* what we want to follow */
};
-int fdisk_wipe_collisions(struct fdisk_context *cxt);
-
/* context.c */
extern int __fdisk_switch_label(struct fdisk_context *cxt,
struct fdisk_label *lb);
@@ -455,4 +459,10 @@ extern struct dos_partition *fdisk_dos_get_partition(
struct fdisk_context *cxt,
size_t i);
+/* wipe.c */
+void fdisk_free_wipe_areas(struct fdisk_context *cxt);
+int fdisk_set_wipe_area(struct fdisk_context *cxt, uint64_t start, uint64_t size, int enable);
+int fdisk_do_wipe(struct fdisk_context *cxt);
+int fdisk_has_wipe_area(struct fdisk_context *cxt, uint64_t start, uint64_t size);
+
#endif /* _LIBFDISK_PRIVATE_H */
diff --git a/libfdisk/src/init.c b/libfdisk/src/init.c
index 61acb0a4f..b4de57cd0 100644
--- a/libfdisk/src/init.c
+++ b/libfdisk/src/init.c
@@ -21,6 +21,7 @@ UL_DEBUG_DEFINE_MASKNAMES(libfdisk) =
{ "parttype", LIBFDISK_DEBUG_PARTTYPE,"partition type utils" },
{ "script", LIBFDISK_DEBUG_SCRIPT, "sfdisk-like scripts" },
{ "tab", LIBFDISK_DEBUG_TAB, "table utils"},
+ { "wipe", LIBFDISK_DEBUG_WIPE, "wipe area utils" },
{ NULL, 0 }
};
diff --git a/libfdisk/src/label.c b/libfdisk/src/label.c
index f2580cf03..ee5ee3e4a 100644
--- a/libfdisk/src/label.c
+++ b/libfdisk/src/label.c
@@ -304,11 +304,7 @@ int fdisk_write_disklabel(struct fdisk_context *cxt)
if (!cxt->label->op->write)
return -ENOSYS;
- if (cxt->collision && cxt->wipe_device) {
- int rc = fdisk_wipe_collisions(cxt);
- if (rc)
- return rc;
- }
+ fdisk_do_wipe(cxt);
return cxt->label->op->write(cxt);
}
diff --git a/libfdisk/src/libfdisk.h.in b/libfdisk/src/libfdisk.h.in
index 7bcacd6da..6bd3a1e56 100644
--- a/libfdisk/src/libfdisk.h.in
+++ b/libfdisk/src/libfdisk.h.in
@@ -285,6 +285,10 @@ enum fdisk_fieldtype {
FDISK_FIELD_SADDR, /* Start-C/H/S (MBR) */
FDISK_FIELD_UUID, /* partition UUID (GPT) */
+ FDISK_FIELD_FSUUID,
+ FDISK_FIELD_FSLABEL,
+ FDISK_FIELD_FSTYPE,
+
FDISK_NFIELDS /* must be last */
};
@@ -321,9 +325,10 @@ extern int fdisk_get_partition(struct fdisk_context *cxt, size_t partno, struct
extern int fdisk_set_partition(struct fdisk_context *cxt, size_t partno, struct fdisk_partition *pa);
extern int fdisk_add_partition(struct fdisk_context *cxt, struct fdisk_partition *pa, size_t *partno);
extern int fdisk_delete_partition(struct fdisk_context *cxt, size_t partno);
-
extern int fdisk_delete_all_partitions(struct fdisk_context *cxt);
+extern int fdisk_wipe_partition(struct fdisk_context *cxt, size_t partno, int enable);
+
extern int fdisk_set_partition_type(struct fdisk_context *cxt, size_t partnum,
struct fdisk_parttype *t);
@@ -389,6 +394,7 @@ size_t fdisk_partition_get_partno(struct fdisk_partition *pa);
int fdisk_partition_has_partno(struct fdisk_partition *pa);
int fdisk_partition_cmp_partno(struct fdisk_partition *a,
struct fdisk_partition *b);
+
int fdisk_partition_partno_follow_default(struct fdisk_partition *pa, int enable);
extern int fdisk_partition_set_type(struct fdisk_partition *pa, struct fdisk_parttype *type);
diff --git a/libfdisk/src/libfdisk.sym b/libfdisk/src/libfdisk.sym
index 6a412bc20..c5aeac68e 100644
--- a/libfdisk/src/libfdisk.sym
+++ b/libfdisk/src/libfdisk.sym
@@ -259,3 +259,7 @@ FDISK_2.28 {
fdisk_get_collision;
fdisk_has_wipe;
} FDISK_2.27;
+
+FDISK_2.29 {
+ fdisk_wipe_partition;
+} FDISK_2.28;
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);
diff --git a/libfdisk/src/wipe.c b/libfdisk/src/wipe.c
new file mode 100644
index 000000000..2c91da57f
--- /dev/null
+++ b/libfdisk/src/wipe.c
@@ -0,0 +1,143 @@
+#include "c.h"
+#include "strutils.h"
+
+#ifdef HAVE_LIBBLKID
+# include <blkid.h>
+#endif
+
+#include "fdiskP.h"
+
+struct fdisk_wipe {
+ struct list_head wipes;
+ uint64_t start; /* sectors */
+ uint64_t size; /* sectors */
+};
+
+static struct fdisk_wipe *fdisk_get_wipe_area(
+ struct fdisk_context *cxt,
+ uint64_t start,
+ uint64_t size)
+{
+ struct list_head *p;
+
+ if (cxt == NULL || list_empty(&cxt->wipes))
+ return NULL;
+
+ list_for_each(p, &cxt->wipes) {
+ struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
+ if (wp->start == start && wp->size == size)
+ return wp;
+ }
+ return NULL;
+}
+
+void fdisk_free_wipe_areas(struct fdisk_context *cxt)
+{
+ while (!list_empty(&cxt->wipes)) {
+ struct fdisk_wipe *wp = list_entry(cxt->wipes.next,
+ struct fdisk_wipe, wipes);
+ DBG(WIPE, ul_debugobj(wp, "free [start=%ju, size=%ju]",
+ (uintmax_t) wp->start, (uintmax_t) wp->size));
+ list_del(&wp->wipes);
+ free(wp);
+ }
+}
+
+int fdisk_has_wipe_area(struct fdisk_context *cxt,
+ uint64_t start,
+ uint64_t size)
+{
+ return fdisk_get_wipe_area(cxt, start, size) != NULL;
+}
+
+/* Add/remove new wiping area
+ *
+ * Returns: <0 on error, or old area setting (1: enabled, 0: disabled)
+ */
+int fdisk_set_wipe_area(struct fdisk_context *cxt,
+ uint64_t start,
+ uint64_t size,
+ int enable)
+{
+ struct fdisk_wipe *wp;
+
+ if (FDISK_IS_UNDEF(start) || FDISK_IS_UNDEF(size))
+ return -EINVAL;
+
+ wp = fdisk_get_wipe_area(cxt, start, size);
+
+ /* disable */
+ if (!enable) {
+ if (wp) {
+ DBG(WIPE, ul_debugobj(wp, "disable [start=%ju, size=%ju]",
+ (uintmax_t) start, (uintmax_t) size));
+ list_del(&wp->wipes);
+ free(wp);
+ return 1;
+ }
+ return 0;
+ }
+
+ /* enable */
+ if (wp)
+ return 1; /* already enabled */
+
+ wp = calloc(1, sizeof(*wp));
+ if (!wp)
+ return -ENOMEM;
+
+ DBG(WIPE, ul_debugobj(wp, "enable [start=%ju, size=%ju]",
+ (uintmax_t) start, (uintmax_t) size));
+
+ INIT_LIST_HEAD(&wp->wipes);
+ wp->start = start;
+ wp->size = size;
+ list_add_tail(&wp->wipes, &cxt->wipes);
+
+ return 0;
+}
+
+int fdisk_do_wipe(struct fdisk_context *cxt)
+{
+#ifdef HAVE_LIBBLKID
+ struct list_head *p;
+ blkid_probe pr;
+ int rc;
+
+ assert(cxt);
+ assert(cxt->dev_fd >= 0);
+
+ if (list_empty(&cxt->wipes))
+ return 0;
+
+ pr = blkid_new_probe();
+ if (!pr)
+ return -ENOMEM;
+
+ list_for_each(p, &cxt->wipes) {
+ struct fdisk_wipe *wp = list_entry(p, struct fdisk_wipe, wipes);
+ blkid_loff_t start = (blkid_loff_t) wp->start * cxt->sector_size,
+ size = (blkid_loff_t) wp->size * cxt->sector_size;
+
+ DBG(WIPE, ul_debugobj(wp, "initialize libblkid prober [start=%ju, size=%ju]",
+ (uintmax_t) start, (uintmax_t) size));
+
+ rc = blkid_probe_set_device(pr, cxt->dev_fd, start, size);
+ if (rc)
+ return rc;
+
+ blkid_probe_enable_superblocks(pr, 1);
+ blkid_probe_set_superblocks_flags(pr, BLKID_SUBLKS_MAGIC);
+ blkid_probe_enable_partitions(pr, 1);
+ blkid_probe_set_partitions_flags(pr, BLKID_PARTS_MAGIC);
+
+ while (blkid_do_probe(pr) == 0) {
+ DBG(WIPE, ul_debugobj(wp, " wiping..."));
+ blkid_do_wipe(pr, FALSE);
+ }
+ }
+
+ blkid_free_probe(pr);
+#endif
+ return 0;
+}