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:
parent
2b89be6c80
commit
6611a3dd78
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue