summaryrefslogtreecommitdiffstats
path: root/libfdisk
diff options
context:
space:
mode:
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;
+}