#include <fcntl.h>
#include <inttypes.h>
#include <locale.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sysexits.h>
#include <time.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <linux/fs.h>
-static const char zero[1024 * 1024];
-
#define errp(msg, args...) \
do { \
printf("%s: " msg ": %m\n", program_invocation_short_name, ## args); \
errp("unknown type of file");
}
-int main(int argc, char *argv[])
+static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
{
- off_t offset = 0;
- const char *file;
-
- setlocale(LC_NUMERIC, "en_US");
-
- switch (argc) {
- case 3:
- offset = atoll(argv[2]);
- case 2:
- file = argv[1];
- break;
- default:
- puts("Usage: ddnuke <dev> [offset in bytes]");
- return 1;
- }
-
- int fd = open(file, O_WRONLY);
- if (fd == -1)
- errp("open(%s) failed", file);
-
- off_t max_size = get_size(fd);
-
- if (lseek(fd, offset, SEEK_SET) != offset)
- errp("lseek(%"PRIu64"u) failed", offset);
+ static char mem[1024 * 1024];
+ memset(mem, pattern, sizeof(mem));
+ if (pattern)
+ printf("Writing 0x%X to the output\n", pattern);
unsigned long long speed = 0;
struct timespec stime, etime, itime;
ssize_t ret;
int fsync_pos = 0;
while (pos < max_size) {
- ret = write(fd, zero, sizeof(zero));
+ /* This will round up to sizeof(mem) ... */
+ ret = write(fd, mem, sizeof(mem));
pos += ret;
- if (ret != sizeof(zero)) {
+ if (ret != sizeof(mem)) {
printf("\nread() returned %zi (wanted %zu)\n%'llu MB/s over entire run\n",
- ret, sizeof(zero), mbps(&itime, &etime, pos));
- return 0;
+ ret, sizeof(mem), mbps(&itime, &etime, pos));
+ return;
}
printf("%'llu bytes %u%% (%'llu MB/s)%20s\r", (unsigned long long)pos,
}
printf("\n");
- return 0;
+}
+
+static void usage(int status)
+{
+ fprintf(
+ status ? stderr : stdout,
+ "Usage: ddnuke [options] <dev>\n"
+ "\n"
+ "Options:"
+ " -o <offset> Position to start writing\n"
+ " -r Write random garbage to the device\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);
+
+ if (lseek(fd, offset, SEEK_SET) != offset)
+ errp("lseek(%"PRIu64"u) failed", offset);
+
+ nuke(fd, offset, max_size, 0x00);
+ if (random) {
+ nuke(fd, offset, max_size, 0xaa);
+ nuke(fd, offset, max_size, 0x55);
+ }
+
+ return EX_OK;
}