diff options
-rw-r--r-- | misc-utils/wipefs.8 | 12 | ||||
-rw-r--r-- | misc-utils/wipefs.c | 47 | ||||
-rw-r--r-- | tests/commands.sh | 1 | ||||
-rw-r--r-- | tests/expected/wipefs/wipefs | 1 | ||||
-rwxr-xr-x | tests/ts/wipefs/wipefs | 30 |
5 files changed, 87 insertions, 4 deletions
diff --git a/misc-utils/wipefs.8 b/misc-utils/wipefs.8 index cdf449ec4..fee9aaf14 100644 --- a/misc-utils/wipefs.8 +++ b/misc-utils/wipefs.8 @@ -40,6 +40,10 @@ erased. Erase all available signatures. The set of erased signatures can be restricted with the \fB\-t\fP \fIlist\fP option. .TP +.BR \-b , " \-\-backup" +Create a signature backup to the file $HOME/wipefs-<devname>-<offset>.bak. +For more details see EXAMPLES section. +.TP .BR \-f , " \-\-force" Force erasure, even if the filesystem is mounted. This is required in order to erase the partition table on a block device. @@ -75,6 +79,14 @@ taken. For more details see mount(8). .TP .BR -V , " \-\-version" Output version information and exit. +.SH EXAMPLES +.TP +.BR "wipefs --all --backup /dev/sdb" +Erases all signatures from the device /dev/sdb and creates a signature backup +file ~/wipefs-sdb-<offset>.bak for each signature. +.TP +.BR "dd if=~/wipefs-sdb-0x00000438.bak of=/dev/sdb seek=$((0x00000438)) bs=1 conv=notrunc" +Restores ext2 signature from the backup file ~/wipefs-sdb-0x00000438.bak. .SH AUTHOR Karel Zak <kzak@redhat.com> .SH ENVIRONMENT diff --git a/misc-utils/wipefs.c b/misc-utils/wipefs.c index ce3d2b816..f10f498c7 100644 --- a/misc-utils/wipefs.c +++ b/misc-utils/wipefs.c @@ -309,13 +309,33 @@ static void do_wipe_real(blkid_probe pr, const char *devname, struct wipe_desc * putchar('\n'); } +static void do_backup(struct wipe_desc *wp, const char *base) +{ + char *fname = NULL; + int fd; + + xasprintf(&fname, "%s0x%08jx.bak", base, wp->offset); + + fd = open(fname, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR); + if (fd < 0) + goto err; + if (write_all(fd, wp->magic, wp->len) != 0) + goto err; + close(fd); + free(fname); + return; +err: + err(EXIT_FAILURE, _("%s: failed to create a signature backup"), fname); +} + static struct wipe_desc * -do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet, int force) +do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int bkp, int quiet, int force) { int flags; blkid_probe pr; struct wipe_desc *w, *wp0; int zap = all ? 1 : wp->zap; + char *fn_base = NULL; flags = O_RDWR; if (!force) @@ -324,6 +344,13 @@ do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet if (!pr) return NULL; + if (zap && bkp) { + const char *home = getenv ("HOME"); + if (!home) + errx(EXIT_FAILURE, _("failed to create a signature backup, $HOME undefined")); + xasprintf (&fn_base, "%s/wipefs-%s-", home, basename(devname)); + } + wp0 = clone_offset(wp); while (blkid_do_probe(pr) == 0) { @@ -345,8 +372,11 @@ do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet if (!wp->on_disk) continue; - if (zap) + if (zap) { + if (bkp) + do_backup(wp, fn_base); do_wipe_real(pr, devname, wp, noact, quiet); + } } for (w = wp0; w != NULL; w = w->next) { @@ -358,6 +388,7 @@ do_wipe(struct wipe_desc *wp, const char *devname, int noact, int all, int quiet close(blkid_probe_get_fd(pr)); blkid_free_probe(pr); free_wipe(wp0); + free(fn_base); return wp; } @@ -372,6 +403,7 @@ usage(FILE *out) fputs(_("\nOptions:\n"), out); fputs(_(" -a, --all wipe all magic strings (BE CAREFUL!)\n" + " -b, --backup create a signature backup in $HOME\n" " -f, --force force erasure\n" " -h, --help show this help text\n" " -n, --no-act do everything except the actual write() call\n" @@ -391,11 +423,12 @@ int main(int argc, char **argv) { struct wipe_desc *wp0 = NULL, *wp; - int c, all = 0, force = 0, has_offset = 0, noact = 0, quiet = 0; + int c, all = 0, bkp = 0, force = 0, has_offset = 0, noact = 0, quiet = 0; int mode = WP_MODE_PRETTY; static const struct option longopts[] = { { "all", 0, 0, 'a' }, + { "backup", 0, 0, 'b' }, { "force", 0, 0, 'f' }, { "help", 0, 0, 'h' }, { "no-act", 0, 0, 'n' }, @@ -426,6 +459,9 @@ main(int argc, char **argv) case 'a': all++; break; + case 'b': + bkp++; + break; case 'f': force++; break; @@ -461,6 +497,9 @@ main(int argc, char **argv) if (optind == argc) usage(stderr); + if (bkp && !(all || has_offset)) + warnx(_("The --backup option is meaningless in this context")); + if (!all && !has_offset) { /* * Print only @@ -477,7 +516,7 @@ main(int argc, char **argv) */ while (optind < argc) { wp = clone_offset(wp0); - wp = do_wipe(wp, argv[optind++], noact, all, quiet, + wp = do_wipe(wp, argv[optind++], noact, all, bkp, quiet, force); free_wipe(wp); } diff --git a/tests/commands.sh b/tests/commands.sh index 02ca6c3db..d12c0097c 100644 --- a/tests/commands.sh +++ b/tests/commands.sh @@ -66,3 +66,4 @@ TS_CMD_UL=${TS_CMD_UL-"$top_builddir/ul"} TS_CMD_UMOUNT=${TS_CMD_UMOUNT:-"$top_builddir/umount"} TS_CMD_UTMPDUMP=${TS_CMD_UTMPDUMP-"$top_builddir/utmpdump"} TS_CMD_WHEREIS=${TS_CMD_WHEREIS-"$top_builddir/whereis"} +TS_CMD_WIPEFS=${TS_CMD_WIPEFS-"$top_builddir/wipefs"} diff --git a/tests/expected/wipefs/wipefs b/tests/expected/wipefs/wipefs new file mode 100644 index 000000000..d86bac9de --- /dev/null +++ b/tests/expected/wipefs/wipefs @@ -0,0 +1 @@ +OK diff --git a/tests/ts/wipefs/wipefs b/tests/ts/wipefs/wipefs new file mode 100755 index 000000000..38dbedbb1 --- /dev/null +++ b/tests/ts/wipefs/wipefs @@ -0,0 +1,30 @@ +#!/bin/bash + +TS_TOPDIR="$(dirname $0)/../.." +TS_DESC="wipefs" + +. $TS_TOPDIR/functions.sh +ts_skip_nonroot +ts_init "$*" + +DEVICE=$(ts_scsi_debug_init dev_size_mb=50 num_parts=2) + +# remove old backups +rm -rf $HOME/wipefs-$(basename ${DEVICE})-*.bak + +#remove the magic byte, back it up +$TS_CMD_WIPEFS --all --backup ${DEVICE} &>/dev/null || ts_die "wipefs failed" + +#there should be just one magic string/backup file in this case +INFILE=$(ls $HOME/wipefs-$(basename ${DEVICE})-*.bak) +OFFT=$(echo $INFILE | sed -E 's/^.*-(.*).bak$/\1/') +dd if=$INFILE of=$DEVICE bs=1 conv=notrunc seek=$(($OFFT)) &>/dev/null + +#the bytes should be copied back, check if wipefs can recognize it +$TS_CMD_WIPEFS -a ${DEVICE} > $TS_OUTDIR/out 2>/dev/null + +# check for output +[ -s $TS_OUTDIR/out ] && echo "OK" &> $TS_OUTPUT || exit 1 + +rmmod scsi_debug &>/dev/null +ts_finalize |