X-Git-Url: https://git.wh0rd.org/?a=blobdiff_plain;f=ddnuke.c;h=8e0abdbaaa5c371e1aab3a15eb0e41a738351310;hb=6f3ed6f832f53a6ee07c774333ee8301cdcb1e49;hp=3d01d36f6a142052491f1fe05d3bd33286573db0;hpb=d777d1fb803a4adf084869a526eda1e6f282abc0;p=home.git diff --git a/ddnuke.c b/ddnuke.c index 3d01d36..8e0abdb 100644 --- a/ddnuke.c +++ b/ddnuke.c @@ -3,26 +3,33 @@ * written by Mike Frysinger */ +#pragma GCC diagnostic warning "-Wall" +#pragma GCC diagnostic warning "-Wextra" + #define _FILE_OFFSET_BITS 64 #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE #define _GNU_SOURCE +#include #include #include #include +#include #include #include #include +#include #include #include - -static const char zero[1024 * 1024]; +#include +#include +#include #define errp(msg, args...) \ do { \ - printf("%s: " msg ": %m\n", argv[0], ## args); \ - return 1; \ + printf("%s: " msg ": %m\n", program_invocation_short_name, ## args); \ + exit(1); \ } while (0) static unsigned long long mbps(struct timespec *stime, struct timespec *etime, off_t len) @@ -35,27 +42,36 @@ static unsigned long long mbps(struct timespec *stime, struct timespec *etime, o return 1000 * len / dtime; } -int main(int argc, char *argv[]) +static off_t get_blk_size(int fd) { - off_t offset = 0; - const char *file; + uint64_t size; + if (ioctl(fd, BLKGETSIZE64, &size)) + errp("ioctl(BLKGETSIZE64) failed"); + return size; +} - setlocale(LC_NUMERIC, "en_US"); +static off_t get_size(int fd) +{ + struct stat st; - switch (argc) { - case 3: - offset = atoll(argv[2]); - case 2: - file = argv[1]; - break; - default: - puts("Usage: ddnuke [offset in bytes]"); - return 1; - } + if (fstat(fd, &st)) + errp("could not stat %i", fd); - int fd = open(file, O_WRONLY); - if (fd == -1) - errp("open(%s) failed", file); + if (S_ISREG(st.st_mode)) + return st.st_size; + else if (S_ISBLK(st.st_mode)) + return get_blk_size(fd); + + errno = EINVAL; + errp("unknown type of file"); +} + +static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern) +{ + static char mem[1024 * 1024]; + memset(mem, pattern, sizeof(mem)); + if (pattern) + printf("Writing 0x%X to the output\n", pattern); if (lseek(fd, offset, SEEK_SET) != offset) errp("lseek(%"PRIu64"u) failed", offset); @@ -65,21 +81,24 @@ int main(int argc, char *argv[]) clock_gettime(CLOCK_MONOTONIC, &stime); itime = stime; - off_t pos = 0, last_pos = 0; + off_t pos = offset, last_pos = 0; ssize_t ret; int fsync_pos = 0; - while (1) { - ret = write(fd, zero, sizeof(zero)); + while (pos < max_size) { + /* This will round up to sizeof(mem) ... */ + ret = write(fd, mem, sizeof(mem)); pos += ret; - if (ret != sizeof(zero)) { - printf("\ngot back %zi (wanted %zu)\n%'llu MB/s over entire run\n", - ret, sizeof(zero), mbps(&itime, &etime, pos)); - return 0; + if (ret != sizeof(mem)) { + if (pos != max_size) + printf("\nread() returned %zi (wanted %zu)\n%'llu MB/s over entire run\n", + ret, sizeof(mem), mbps(&itime, &etime, pos)); + return; } - printf("%'llu bytes (%'llu MB/s)%20s\r", (unsigned long long)pos, speed, ""); + printf("%'llu bytes %u%% (%'llu MB/s)%20s\r", (unsigned long long)pos, + (unsigned)((pos * 100) / max_size), speed, ""); - if ((++fsync_pos % 16) == 0) { + if ((++fsync_pos % 32) == 0) { speed = mbps(&stime, &etime, pos - last_pos); last_pos = pos; fflush(stdout); @@ -87,5 +106,58 @@ int main(int argc, char *argv[]) } } - return 0; + printf("\n"); +} + +static void usage(int status) +{ + fprintf( + status ? stderr : stdout, + "Usage: ddnuke [options] \n" + "\n" + "Options:\n" + " -o Position to start writing\n" + " -r Write three times: 0x00, then 0xaa, then 0x55\n" + ); + exit(status); +} + +int main(int argc, char *argv[]) +{ + off_t offset = 0; + const char *file; + bool random = false; + int o; + + setlocale(LC_NUMERIC, "en_US"); + + while ((o = getopt(argc, argv, "ho:r")) != -1) { + switch (o) { + case 'o': + offset = atoll(optarg); + break; + case 'r': + random = true; + break; + case 'h': usage(EX_OK); + default: usage(EX_USAGE); + } + } + if (argc != optind + 1) + usage(EX_USAGE); + file = argv[optind]; + + int fd = open(file, O_WRONLY|O_CLOEXEC); + if (fd == -1) + errp("open(%s) failed", file); + + off_t max_size = get_size(fd); + + nuke(fd, offset, max_size, 0x00); + if (random) { + nuke(fd, offset, max_size, 0xaa); + nuke(fd, offset, max_size, 0x55); + } + + return EX_OK; }