summaryrefslogtreecommitdiffstats
path: root/misc-utils/wipefs.c
diff options
context:
space:
mode:
authorKarel Zak2017-08-31 14:47:14 +0200
committerKarel Zak2017-08-31 14:47:14 +0200
commit0e45b256ac41257e920e1bcf61ff1a1b30ba5b98 (patch)
treeafb922ea18413a97f698d7b061aef0bfc7c993ea /misc-utils/wipefs.c
parentlib/match: make match_fstype() case insensitive (diff)
downloadkernel-qcow2-util-linux-0e45b256ac41257e920e1bcf61ff1a1b30ba5b98.tar.gz
kernel-qcow2-util-linux-0e45b256ac41257e920e1bcf61ff1a1b30ba5b98.tar.xz
kernel-qcow2-util-linux-0e45b256ac41257e920e1bcf61ff1a1b30ba5b98.zip
wipefs: cleanup offsets list usage, fix -t filter
* move list with offsets specified by -o to the wipe_control struct * don't clone the list of offsets, just keep it simple and stupid * apply all filters (-o and -t) in get_desc_for_probe() * always return offset and len by get_desc_for_probe() and apply always use libblkid hide & step-back Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=1486777 Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils/wipefs.c')
-rw-r--r--misc-utils/wipefs.c209
1 files changed, 99 insertions, 110 deletions
diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c
index e01fa0c25..c211d5143 100644
--- a/misc-utils/wipefs.c
+++ b/misc-utils/wipefs.c
@@ -56,17 +56,17 @@ struct wipe_desc {
struct wipe_desc *next;
- unsigned int zap : 1,
- on_disk : 1,
+ unsigned int on_disk : 1,
is_parttable : 1;
};
struct wipe_control {
const char *devname;
- const char *type_pattern;
+ const char *type_pattern; /* -t <pattern> */
struct libscols_table *outtab;
+ struct wipe_desc *offsets; /* -o <offset> -o <offset> ... */
unsigned int noact : 1,
all : 1,
@@ -257,74 +257,90 @@ static void add_to_output(struct wipe_control *ctl, struct wipe_desc *wp)
fill_table_row(ctl, wp);
}
-static struct wipe_desc *
-add_offset(struct wipe_desc *wp0, loff_t offset, int zap)
+/* Allocates a new wipe_desc and add to the wp0 if not NULL */
+static struct wipe_desc *add_offset(struct wipe_desc **wp0, loff_t offset)
{
- struct wipe_desc *wp = wp0;
-
- while (wp) {
- if (wp->offset == offset)
- return wp;
- wp = wp->next;
+ struct wipe_desc *wp, *last = NULL;
+
+ if (wp0) {
+ /* check if already exists */
+ for (wp = *wp0; wp; wp = wp->next) {
+ if (wp->offset == offset)
+ return wp;
+ last = wp;
+ }
}
wp = xcalloc(1, sizeof(struct wipe_desc));
wp->offset = offset;
- wp->next = wp0;
- wp->zap = zap ? 1 : 0;
- return wp;
-}
-
-static struct wipe_desc *
-clone_offset(struct wipe_desc *wp0)
-{
- struct wipe_desc *wp = NULL;
-
- while(wp0) {
- wp = add_offset(wp, wp0->offset, wp0->zap);
- wp0 = wp0->next;
- }
+ wp->next = NULL;
+ if (last)
+ last->next = wp;
+ if (wp0 && !*wp0)
+ *wp0 = wp;
return wp;
}
-static struct wipe_desc *
-get_desc_for_probe(struct wipe_control *ctl, struct wipe_desc *wp, blkid_probe pr, int *found)
+/* Read data from libblkid and if detected type pass -t and -o filters than:
+ * - allocates a new wipe_desc
+ * - add the new wipe_desc to wp0 list (if not NULL)
+ *
+ * The function always returns offset and len if libblkid detected something.
+ */
+static struct wipe_desc *get_desc_for_probe(struct wipe_control *ctl,
+ struct wipe_desc **wp0,
+ blkid_probe pr,
+ loff_t *offset,
+ size_t *len)
{
const char *off, *type, *mag, *p, *usage = NULL;
- size_t len;
- loff_t offset;
+ struct wipe_desc *wp;
int rc, ispt = 0;
- if (found)
- *found = 0;
+ *len = 0;
/* superblocks */
if (blkid_probe_lookup_value(pr, "TYPE", &type, NULL) == 0) {
rc = blkid_probe_lookup_value(pr, "SBMAGIC_OFFSET", &off, NULL);
if (!rc)
- rc = blkid_probe_lookup_value(pr, "SBMAGIC", &mag, &len);
+ rc = blkid_probe_lookup_value(pr, "SBMAGIC", &mag, len);
if (rc)
- return wp;
+ return NULL;
/* partitions */
} else if (blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL) == 0) {
rc = blkid_probe_lookup_value(pr, "PTMAGIC_OFFSET", &off, NULL);
if (!rc)
- rc = blkid_probe_lookup_value(pr, "PTMAGIC", &mag, &len);
+ rc = blkid_probe_lookup_value(pr, "PTMAGIC", &mag, len);
if (rc)
- return wp;
+ return NULL;
usage = N_("partition-table");
ispt = 1;
} else
- return wp;
+ return NULL;
+
+ *offset = strtoll(off, NULL, 10);
+ /* Filter out by -t <type> */
if (ctl->type_pattern && !match_fstype(type, ctl->type_pattern))
- return wp;
+ return NULL;
+
+ /* Filter out by -o <offset> */
+ if (ctl->offsets) {
+ struct wipe_desc *w = NULL;
- offset = strtoll(off, NULL, 10);
+ for (w = ctl->offsets; w; w = w->next) {
+ if (w->offset == *offset)
+ break;
+ }
+ if (!w)
+ return NULL;
+
+ w->on_disk = 1; /* mark as "found" */
+ }
- wp = add_offset(wp, offset, 0);
+ wp = add_offset(wp0, *offset);
if (!wp)
return NULL;
@@ -335,9 +351,9 @@ get_desc_for_probe(struct wipe_control *ctl, struct wipe_desc *wp, blkid_probe p
wp->on_disk = 1;
wp->is_parttable = ispt ? 1 : 0;
- wp->magic = xmalloc(len);
- memcpy(wp->magic, mag, len);
- wp->len = len;
+ wp->magic = xmalloc(*len);
+ memcpy(wp->magic, mag, *len);
+ wp->len = *len;
if (blkid_probe_lookup_value(pr, "LABEL", &p, NULL) == 0)
wp->label = xstrdup(p);
@@ -345,8 +361,6 @@ get_desc_for_probe(struct wipe_control *ctl, struct wipe_desc *wp, blkid_probe p
if (blkid_probe_lookup_value(pr, "UUID", &p, NULL) == 0)
wp->uuid = xstrdup(p);
- if (found)
- *found = 1;
return wp;
}
@@ -392,34 +406,33 @@ error:
err(EXIT_FAILURE, _("error: %s: probing initialization failed"), devname);
}
-static struct wipe_desc *
-read_offsets(struct wipe_control *ctl, struct wipe_desc *wp)
+static struct wipe_desc *read_offsets(struct wipe_control *ctl)
{
blkid_probe pr = new_probe(ctl->devname, 0);
+ struct wipe_desc *wp0 = NULL;
if (!pr)
return NULL;
while (blkid_do_probe(pr) == 0) {
- int found = 0;
+ size_t len = 0;
+ loff_t offset = 0;
- wp = get_desc_for_probe(ctl, wp, pr, &found);
- if (!wp)
- break;
+ /* add a new offset to wp0 */
+ get_desc_for_probe(ctl, &wp0, pr, &offset, &len);
/* hide last detected signature and scan again */
- if (found) {
- blkid_probe_hide_range(pr, wp->offset, wp->len);
+ if (len) {
+ blkid_probe_hide_range(pr, offset, len);
blkid_probe_step_back(pr);
}
}
blkid_free_probe(pr);
- return wp;
+ return wp0;
}
-static void
-free_wipe(struct wipe_desc *wp)
+static void free_wipe(struct wipe_desc *wp)
{
while (wp) {
struct wipe_desc *next = wp->next;
@@ -493,23 +506,21 @@ static void rereadpt(int fd, const char *devname)
}
#endif
-static struct wipe_desc *
-do_wipe(struct wipe_control *ctl, struct wipe_desc *wp)
+static int do_wipe(struct wipe_control *ctl)
{
int mode = O_RDWR, reread = 0, need_force = 0;
blkid_probe pr;
- struct wipe_desc *w, *wp0;
- int zap = ctl->all ? 1 : wp->zap;
char *backup = NULL;
+ struct wipe_desc *w;
if (!ctl->force)
mode |= O_EXCL;
pr = new_probe(ctl->devname, mode);
if (!pr)
- return NULL;
+ return -errno;
- if (zap && ctl->backup) {
+ if (ctl->backup) {
const char *home = getenv ("HOME");
char *tmp = xstrdup(ctl->devname);
@@ -519,29 +530,14 @@ do_wipe(struct wipe_control *ctl, struct wipe_desc *wp)
free(tmp);
}
- /* wp0 is the list of wanted offsets */
- wp0 = clone_offset(wp);
-
while (blkid_do_probe(pr) == 0) {
int wiped = 0;
+ size_t len = 0;
+ loff_t offset = 0;
+ struct wipe_desc *wp;
- wp = get_desc_for_probe(ctl, wp, pr, NULL);
+ wp = get_desc_for_probe(ctl, NULL, pr, &offset, &len);
if (!wp)
- break;
-
- /* Check if offset is in provided list */
- w = wp0;
- while(w && w->offset != wp->offset)
- w = w->next;
-
- if (wp0 && !w)
- goto done;
-
- /* Mark done if found in provided list */
- if (w)
- w->on_disk = wp->on_disk;
-
- if (!wp->on_disk)
goto done;
if (!ctl->force
@@ -553,16 +549,14 @@ do_wipe(struct wipe_control *ctl, struct wipe_desc *wp)
goto done;
}
- if (zap) {
- if (backup)
- do_backup(wp, backup);
- do_wipe_real(ctl, pr, wp);
- if (wp->is_parttable)
- reread = 1;
- wiped = 1;
- }
+ if (backup)
+ do_backup(wp, backup);
+ do_wipe_real(ctl, pr, wp);
+ if (wp->is_parttable)
+ reread = 1;
+ wiped = 1;
done:
- if (!wiped) {
+ if (!wiped && len) {
/* if the offset has not been wiped (probably because
* filtered out by -t or -o) we need to hide it for
* libblkid to try another magic string for the same
@@ -570,13 +564,13 @@ do_wipe(struct wipe_control *ctl, struct wipe_desc *wp)
* another superblock. Don't forget that the same
* superblock could be detected by more magic strings
* */
- blkid_probe_hide_range(pr, wp->offset, wp->len);
+ blkid_probe_hide_range(pr, offset, len);
blkid_probe_step_back(pr);
}
-
+ free_wipe(wp);
}
- for (w = wp0; w != NULL; w = w->next) {
+ for (w = ctl->offsets; w; w = w->next) {
if (!w->on_disk && !ctl->quiet)
warnx(_("%s: offset 0x%jx not found"),
ctl->devname, (uintmax_t)w->offset);
@@ -594,10 +588,8 @@ do_wipe(struct wipe_control *ctl, struct wipe_desc *wp)
close(blkid_probe_get_fd(pr));
blkid_free_probe(pr);
- free_wipe(wp0);
free(backup);
-
- return wp;
+ return 0;
}
@@ -640,8 +632,7 @@ int
main(int argc, char **argv)
{
struct wipe_control ctl = { .devname = NULL };
- struct wipe_desc *wp0 = NULL;
- int c, noffsets = 0;
+ int c;
char *outarg = NULL;
static const struct option longopts[] = {
@@ -702,9 +693,8 @@ main(int argc, char **argv)
ctl.noact = 1;
break;
case 'o':
- wp0 = add_offset(wp0, strtosize_or_err(optarg,
- _("invalid offset argument")), 1);
- noffsets++;
+ add_offset(&ctl.offsets, strtosize_or_err(optarg,
+ _("invalid offset argument")));
break;
case 'p':
ctl.parsable = 1;
@@ -730,10 +720,10 @@ main(int argc, char **argv)
}
- if (ctl.backup && !(ctl.all || noffsets))
+ if (ctl.backup && !(ctl.all || ctl.offsets))
warnx(_("The --backup option is meaningless in this context"));
- if (!ctl.all && !noffsets) {
+ if (!ctl.all && !ctl.offsets) {
/*
* Print only
*/
@@ -760,11 +750,13 @@ main(int argc, char **argv)
init_output(&ctl);
while (optind < argc) {
+ struct wipe_desc *wp;
+
ctl.devname = argv[optind++];
- wp0 = read_offsets(&ctl, NULL);
- if (wp0)
- add_to_output(&ctl, wp0);
- free_wipe(wp0);
+ wp = read_offsets(&ctl);
+ if (wp)
+ add_to_output(&ctl, wp);
+ free_wipe(wp);
}
finalize_output(&ctl);
} else {
@@ -772,11 +764,8 @@ main(int argc, char **argv)
* Erase
*/
while (optind < argc) {
- struct wipe_desc *wp = clone_offset(wp0);
-
ctl.devname = argv[optind++];
- wp = do_wipe(&ctl, wp);
- free_wipe(wp);
+ do_wipe(&ctl);
}
}