summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--misc-utils/wipefs.812
-rw-r--r--misc-utils/wipefs.c47
-rw-r--r--tests/commands.sh1
-rw-r--r--tests/expected/wipefs/wipefs1
-rwxr-xr-xtests/ts/wipefs/wipefs30
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