fdisk_get_partition
fdisk_is_partition_used
fdisk_set_partition
+fdisk_wipe_partition
<SUBSECTION>
fdisk_partition
fdisk_new_partition
libfdisk/src/iter.c \
libfdisk/src/script.c \
libfdisk/src/version.c \
+ libfdisk/src/wipe.c \
\
libfdisk/src/sun.c \
libfdisk/src/sgi.c \
cxt->dev_fd = -1;
cxt->refcount = 1;
+ INIT_LIST_HEAD(&cxt->wipes);
+
/*
* Allocate label specific structs.
*
return -ENOMEM;
}
+ INIT_LIST_HEAD(&cxt->wipes);
+
return 0;
}
* @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.
*/
{
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;
}
*/
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);
}
cxt->script = NULL;
cxt->label = NULL;
+
+ fdisk_free_wipe_areas(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
#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);
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() */
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 */
};
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_* */
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);
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 */
{ "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 }
};
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);
}
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 */
};
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);
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);
fdisk_get_collision;
fdisk_has_wipe;
} FDISK_2.27;
+
+FDISK_2.29 {
+ fdisk_wipe_partition;
+} FDISK_2.28;
#include "c.h"
#include "strutils.h"
+#ifdef HAVE_LIBBLKID
+# include <blkid.h>
+#endif
+
#include "fdiskP.h"
/**
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;
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;
}
* @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.
*/
if (FDISK_IS_UNDEF(off))
return -ERANGE;
pa->start = off;
+ pa->fs_probed = 0;
return 0;
}
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->start);
+ pa->fs_probed = 0;
return 0;
}
if (FDISK_IS_UNDEF(sz))
return -ERANGE;
pa->size = sz;
+ pa->fs_probed = 0;
return 0;
}
if (!pa)
return -EINVAL;
FDISK_INIT_UNDEF(pa->size);
+ pa->fs_probed = 0;
return 0;
}
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
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;
}
return rc;
}
+
/**
* fdisk_get_partition:
* @cxt: context
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;
(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)
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:
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,
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);
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);
--- /dev/null
+#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;
+}