]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
wipefs: add --backup
authorOndrej Oprala <ooprala@redhat.com>
Wed, 10 Apr 2013 16:21:27 +0000 (18:21 +0200)
committerKarel Zak <kzak@redhat.com>
Fri, 26 Apr 2013 10:27:37 +0000 (12:27 +0200)
[kzak@redhat.com: - don't wipe if failed to create a backup file
                  - use ts_scsi_debug_init in the regression tests]

Signed-off-by: Ondrej Oprala <ooprala@redhat.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
misc-utils/wipefs.8
misc-utils/wipefs.c
tests/commands.sh
tests/expected/wipefs/wipefs [new file with mode: 0644]
tests/ts/wipefs/wipefs [new file with mode: 0755]

index cdf449ec4360d5abe96ac3a1a8714caa2ee23b41..fee9aaf1411a1fdb8ca199d0d1955bbaf86127aa 100644 (file)
@@ -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
index ce3d2b816b38be3f6e0beece0bbbec6ab1f16eb0..f10f498c7d6ee1b039a30e523227541951c1a012 100644 (file)
@@ -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);
                }
index 02ca6c3dba217fd07e072fcaf0214113b6dbc03f..d12c0097ca3b1d755754aba1e559f68bdf1f4a9c 100644 (file)
@@ -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 (file)
index 0000000..d86bac9
--- /dev/null
@@ -0,0 +1 @@
+OK
diff --git a/tests/ts/wipefs/wipefs b/tests/ts/wipefs/wipefs
new file mode 100755 (executable)
index 0000000..38dbedb
--- /dev/null
@@ -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