]> git.wh0rd.org - home.git/commitdiff
ddnuke: add fdisk+prompt to startup, and rough ETA
authorMike Frysinger <vapier@gentoo.org>
Sat, 15 Aug 2020 07:20:11 +0000 (03:20 -0400)
committerMike Frysinger <vapier@gentoo.org>
Sat, 15 Aug 2020 07:20:11 +0000 (03:20 -0400)
ddnuke.c

index 1712d16b6f0e0c4ab49a3cf59aef9d9d0f12d1b2..388a1441e224010992c8758f16ecfce155b8a935 100644 (file)
--- a/ddnuke.c
+++ b/ddnuke.c
 #define _LARGEFILE64_SOURCE
 #define _GNU_SOURCE
 
+#include <ctype.h>
 #include <err.h>
 #include <errno.h>
 #include <fcntl.h>
 #include <inttypes.h>
 #include <locale.h>
+#include <spawn.h>
 #include <stdbool.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -25,6 +27,8 @@
 #include <unistd.h>
 #include <sys/ioctl.h>
 #include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
 #include <linux/fs.h>
 
 static unsigned long long mbps(struct timespec *stime, struct timespec *etime, off_t len)
@@ -41,7 +45,7 @@ static off_t get_blk_size(int fd)
 {
        uint64_t size;
        if (ioctl(fd, BLKGETSIZE64, &size))
-               err(1, "ioctl(BLKGETSIZE64) failed");
+               err(EX_DATAERR, "ioctl(BLKGETSIZE64) failed");
        return size;
 }
 
@@ -50,7 +54,7 @@ static off_t get_size(int fd)
        struct stat st;
 
        if (fstat(fd, &st))
-               err(1, "could not stat %i", fd);
+               err(EX_DATAERR, "could not stat %i", fd);
 
        if (S_ISREG(st.st_mode))
                return st.st_size;
@@ -58,7 +62,7 @@ static off_t get_size(int fd)
                return get_blk_size(fd);
 
        errno = EINVAL;
-       err(1, "unknown type of file");
+       err(EX_DATAERR, "unknown type of file");
 }
 
 static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
@@ -69,7 +73,7 @@ static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
                printf("Writing 0x%X to the output\n", pattern);
 
        if (lseek(fd, offset, SEEK_SET) != offset)
-               err(1, "lseek(%"PRIu64"u) failed", offset);
+               err(EX_DATAERR, "lseek(%"PRIu64"u) failed", offset);
 
        unsigned long long speed = 0;
        struct timespec stime, etime, itime;
@@ -90,8 +94,10 @@ static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
                        return;
                }
 
-               printf("\r\e[2K%'llu bytes %u%% (%'llu MB/s)", (unsigned long long)pos,
-                       (unsigned)((pos * 100) / max_size), speed);
+               unsigned long long eta = speed ? (max_size - pos) / (speed * 1000 * 1000) : 0;
+               printf("\r\e[2K%'llu bytes %u%% (%'llu MB/s) (ETA ~%llum%llus)",
+                       (unsigned long long)pos, (unsigned)((pos * 100) / max_size), speed,
+                       eta / 60, eta % 60);
 
                if ((++fsync_pos % 32) == 0) {
                        speed = mbps(&stime, &etime, pos - last_pos);
@@ -111,6 +117,8 @@ static void usage(int status)
                "Usage: ddnuke [options] <dev>\n"
                "\n"
                "Options:\n"
+               " -q            Run quietly\n"
+               " -y            Assume yes to all prompts\n"
                " -o <offset>   Position to start writing\n"
                " -r            Write three times: 0x00, then 0xaa, then 0x55\n"
        );
@@ -121,19 +129,27 @@ int main(int argc, char *argv[])
 {
        off_t offset = 0;
        const char *file;
+       bool quiet = false;
        bool random = false;
+       bool yes = false;
        int o;
 
        setlocale(LC_NUMERIC, "en_US");
 
-       while ((o = getopt(argc, argv, "ho:r")) != -1) {
+       while ((o = getopt(argc, argv, "ho:qry")) != -1) {
                switch (o) {
                case 'o':
                        offset = atoll(optarg);
                        break;
+               case 'q':
+                       quiet = true;
+                       break;
                case 'r':
                        random = true;
                        break;
+               case 'y':
+                       yes = true;
+                       break;
                case 'h':
                        usage(EX_OK);
                        break;
@@ -148,7 +164,25 @@ int main(int argc, char *argv[])
 
        int fd = open(file, O_WRONLY|O_CLOEXEC);
        if (fd == -1)
-               err(1, "open(%s) failed", file);
+               err(EX_NOINPUT, "open(%s) failed", file);
+
+       if (!quiet) {
+               pid_t pid;
+               const char *argv[] = {"fdisk", "-l", file, NULL};
+               if (posix_spawnp(&pid, argv[0], NULL, NULL, (char *const *)argv, NULL))
+                       err(EX_OSERR, "spawn(%s %s) failed", argv[0], file);
+               waitpid(pid, NULL, 0);
+               printf("\n");
+       }
+
+       if (!yes) {
+               printf("Do you want to wipe '%s'? (y/N) ", file);
+               fflush(stdout);
+               char c = 0;
+               if (fread(&c, 1, 1, stdin)) {/* don't care */}
+               if (tolower(c) != 'y')
+                       errx(EX_UNAVAILABLE, "User decided not to wipe");
+       }
 
        off_t max_size = get_size(fd);