diff options
author | Karel Zak | 2011-11-11 12:48:38 +0100 |
---|---|---|
committer | Karel Zak | 2011-11-11 12:48:38 +0100 |
commit | 6611a3dd783006fd8c6b924a76c4820287278d36 (patch) | |
tree | fe1f6251302b89650e272c7c4800334a923d1e06 /misc-utils | |
parent | libblkid: add blkid_do_wipe() (diff) | |
download | kernel-qcow2-util-linux-6611a3dd783006fd8c6b924a76c4820287278d36.tar.gz kernel-qcow2-util-linux-6611a3dd783006fd8c6b924a76c4820287278d36.tar.xz kernel-qcow2-util-linux-6611a3dd783006fd8c6b924a76c4820287278d36.zip |
wipefs: improve -a, use blkid_do_wipe()
Some filesystems (e.g. FAT) is possible to detect in many ways -- for
example if a magic string is stored on more places on the device. The
current implementation always removes from the device only the firstly
detected possibility.
# wipefs /dev/sdb1
offset type
----------------------------------------------------------------
0x36 vfat [filesystem]
UUID: D203-A7F4
# wipefs -a /dev/sdb1
8 bytes [46 41 54 31 36 20 20 20] erased at offset 0x36 (vfat)
# wipefs /dev/sdb1
offset type
----------------------------------------------------------------
0x0 vfat [filesystem]
UUID: D203-A7F4
This patch fixes this issue:
# wipefs -a /dev/sdb1
8 bytes were erased at offset 0x00000036 (vfat): 46 41 54 31 36 20 20 20
1 bytes were erased at offset 0x00000000 (vfat): eb
2 bytes were erased at offset 0x000001fe (vfat): 55 aa
Signed-off-by: Karel Zak <kzak@redhat.com>
Diffstat (limited to 'misc-utils')
-rw-r--r-- | misc-utils/wipefs.c | 158 |
1 files changed, 92 insertions, 66 deletions
diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c index 58fc03d00..1cd3159d1 100644 --- a/misc-utils/wipefs.c +++ b/misc-utils/wipefs.c @@ -49,6 +49,8 @@ struct wipe_desc { char *label; /* FS label */ char *uuid; /* FS uuid */ + int on_disk; + struct wipe_desc *next; }; @@ -138,7 +140,7 @@ add_offset(struct wipe_desc *wp0, loff_t offset, int zap) } static struct wipe_desc * -get_offset_from_probe(struct wipe_desc *wp, blkid_probe pr, int zap) +get_desc_for_probe(struct wipe_desc *wp, blkid_probe pr) { const char *off, *type, *usage, *mag; size_t len; @@ -151,12 +153,13 @@ get_offset_from_probe(struct wipe_desc *wp, blkid_probe pr, int zap) loff_t offset = strtoll(off, NULL, 10); const char *p; - wp = add_offset(wp, offset, zap); + wp = add_offset(wp, offset, 0); if (!wp) return NULL; wp->usage = xstrdup(usage); wp->type = xstrdup(type); + wp->on_disk = 1; wp->magic = xmalloc(len); memcpy(wp->magic, mag, len); @@ -172,18 +175,28 @@ get_offset_from_probe(struct wipe_desc *wp, blkid_probe pr, int zap) return wp; } -static struct wipe_desc * -read_offsets(struct wipe_desc *wp, const char *fname, int zap) +static blkid_probe +new_probe(const char *devname, int mode) { blkid_probe pr; int rc; - if (!fname) + if (!devname) return NULL; - pr = blkid_new_probe_from_filename(fname); + if (mode) { + int fd = open(devname, mode); + if (fd < 0) + goto error; + + pr = blkid_new_probe(); + if (pr && blkid_probe_set_device(pr, fd, 0, 0)) + goto error; + } else + pr = blkid_new_probe_from_filename(devname); + if (!pr) - errx(EXIT_FAILURE, _("error: %s: probing initialization failed"), fname); + goto error; blkid_probe_enable_superblocks(pr, 0); /* enabled by default ;-( */ @@ -195,7 +208,7 @@ read_offsets(struct wipe_desc *wp, const char *fname, int zap) const char *type = NULL; blkid_probe_lookup_value(pr, "PTTYPE", &type, NULL); warnx(_("WARNING: %s: appears to contain '%s' " - "partition table"), fname, type); + "partition table"), devname, type); } blkid_probe_enable_superblocks(pr, 1); @@ -203,8 +216,22 @@ read_offsets(struct wipe_desc *wp, const char *fname, int zap) BLKID_SUBLKS_TYPE | BLKID_SUBLKS_USAGE | BLKID_SUBLKS_LABEL | BLKID_SUBLKS_UUID); + return pr; +error: + err(EXIT_FAILURE, _("error: %s: probing initialization failed"), devname); + return NULL; +} + +static struct wipe_desc * +read_offsets(struct wipe_desc *wp, const char *devname) +{ + blkid_probe pr = new_probe(devname, 0); + + if (!pr) + return NULL; + while (blkid_do_probe(pr) == 0) { - wp = get_offset_from_probe(wp, pr, zap); + wp = get_desc_for_probe(wp, pr); if (!wp) break; } @@ -213,60 +240,54 @@ read_offsets(struct wipe_desc *wp, const char *fname, int zap) return wp; } -static int -do_wipe_offset(int fd, struct wipe_desc *wp, const char *fname, int noact) +static struct wipe_desc * +do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all) { - char buf[BUFSIZ]; - off_t l; - size_t i, len; - - if (!wp->type) { - warnx(_("no magic string found at offset " - "0x%jx -- ignored"), wp->offset); - return 0; - } - - l = lseek(fd, wp->offset, SEEK_SET); - if (l == (off_t) -1) - err(EXIT_FAILURE, _("%s: failed to seek to offset 0x%jx"), - fname, wp->offset); - - len = wp->len > sizeof(buf) ? sizeof(buf) : wp->len; - - memset(buf, 0, len); - if (noact == 0 && write_all(fd, buf, len)) - err(EXIT_FAILURE, _("%s: write failed"), fname); + blkid_probe pr = new_probe(devname, O_RDWR); + struct wipe_desc *w; - printf(_("%zd bytes were erased at offset 0x%jx (%s)\nthey were: "), - wp->len, wp->offset, wp->type); + if (!pr) + return NULL; - for (i = 0; i < len; i++) { - printf("%02x", wp->magic[i]); - if (i + 1 < len) - fputc(' ', stdout); + while (blkid_do_probe(pr) == 0) { + w = get_desc_for_probe(wp, pr); + if (!w) + break; + wp = w; + if (!wp->on_disk) + continue; + wp->zap = all ? 1 : wp->zap; + if (!wp->zap) + continue; + + if (blkid_do_wipe(pr, noact)) + warn(_("failed to erase %s magic string at offset 0x%08jx"), + wp->type, wp->offset); + else { + size_t i; + + printf(_("%zd bytes were erased at offset 0x%08jx (%s): "), + wp->len, wp->offset, wp->type); + + for (i = 0; i < wp->len; i++) { + printf("%02x", wp->magic[i]); + if (i + 1 < wp->len) + fputc(' ', stdout); + } + putchar('\n'); + } } - printf("\n"); - return 0; -} - -static int -do_wipe(struct wipe_desc *wp, const char *fname, int noact) -{ - int fd; - - fd = open(fname, O_WRONLY); - if (fd < 0) - err(EXIT_FAILURE, _("%s: open failed"), fname); - - while (wp) { - if (wp->zap) - do_wipe_offset(fd, wp, fname, noact); - wp = wp->next; + for (w = wp; w != NULL; w = w->next) { + if (!w->on_disk) + warnx(_("offset 0x%jx not found"), w->offset); } - close(fd); - return 0; + fsync(blkid_probe_get_fd(pr)); + close(blkid_probe_get_fd(pr)); + blkid_free_probe(pr); + + return wp; } static void @@ -323,7 +344,7 @@ main(int argc, char **argv) { struct wipe_desc *wp = NULL; int c, all = 0, has_offset = 0, noact = 0, mode = 0; - const char *fname; + const char *devname; static const struct option longopts[] = { { "all", 0, 0, 'a' }, @@ -372,20 +393,25 @@ main(int argc, char **argv) if (optind == argc) usage(stderr); - fname = argv[optind++]; + devname = argv[optind++]; if (optind != argc) errx(EXIT_FAILURE, _("only one device as argument is currently supported.")); - wp = read_offsets(wp, fname, all); - - if (wp) { - if (has_offset || all) - do_wipe(wp, fname, noact); - else + if (!all && !has_offset) { + /* + * Print only + */ + wp = read_offsets(wp, devname); + if (wp) print_all(wp, mode); - - free_wipe(wp); + } else { + /* + * Erase + */ + wp = do_wipe(wp, devname, noact, all); } + + free_wipe(wp); return EXIT_SUCCESS; } |