]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
wipefs: improve -a, use blkid_do_wipe()
authorKarel Zak <kzak@redhat.com>
Fri, 11 Nov 2011 11:48:38 +0000 (12:48 +0100)
committerKarel Zak <kzak@redhat.com>
Fri, 11 Nov 2011 11:48:38 +0000 (12:48 +0100)
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>
misc-utils/wipefs.c

index 58fc03d00d89c87aec13fd92e8e6529f59d0c9c3..1cd3159d1d8f17e96b4d8945259fa0225b675c51 100644 (file)
@@ -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;
 }