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>
This commit is contained in:
Karel Zak 2011-11-11 12:48:38 +01:00
parent 2b89be6c80
commit 6611a3dd78
1 changed files with 92 additions and 66 deletions

View 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;
blkid_probe pr = new_probe(devname, O_RDWR);
struct wipe_desc *w;
if (!wp->type) {
warnx(_("no magic string found at offset "
"0x%jx -- ignored"), wp->offset);
return 0;
if (!pr)
return NULL;
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');
}
}
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);
printf(_("%zd bytes were erased at offset 0x%jx (%s)\nthey were: "),
wp->len, wp->offset, wp->type);
for (i = 0; i < len; i++) {
printf("%02x", wp->magic[i]);
if (i + 1 < len)
fputc(' ', stdout);
for (w = wp; w != NULL; w = w->next) {
if (!w->on_disk)
warnx(_("offset 0x%jx not found"), w->offset);
}
printf("\n");
return 0;
}
fsync(blkid_probe_get_fd(pr));
close(blkid_probe_get_fd(pr));
blkid_free_probe(pr);
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;
}
close(fd);
return 0;
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;
}