2 * released into the public domain
3 * written by Mike Frysinger <vapier>
6 #pragma GCC diagnostic warning "-Wall"
7 #pragma GCC diagnostic warning "-Wextra"
9 #define _FILE_OFFSET_BITS 64
10 #define _LARGEFILE_SOURCE
11 #define _LARGEFILE64_SOURCE
25 #include <sys/ioctl.h>
29 #define errp(msg, args...) \
31 printf("%s: " msg ": %m\n", program_invocation_short_name, ## args); \
35 static unsigned long long mbps(struct timespec *stime, struct timespec *etime, off_t len)
38 clock_gettime(CLOCK_MONOTONIC, etime);
39 dtime = ((etime->tv_sec - stime->tv_sec) * 1000 * 1000 * 1000) +
40 (etime->tv_nsec - stime->tv_nsec);
42 return 1000 * len / dtime;
45 static off_t get_blk_size(int fd)
48 if (ioctl(fd, BLKGETSIZE64, &size))
49 errp("ioctl(BLKGETSIZE64) failed");
53 static off_t get_size(int fd)
58 errp("could not stat %i", fd);
60 if (S_ISREG(st.st_mode))
62 else if (S_ISBLK(st.st_mode))
63 return get_blk_size(fd);
66 errp("unknown type of file");
69 static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
71 static char mem[1024 * 1024];
72 memset(mem, pattern, sizeof(mem));
74 printf("Writing 0x%X to the output\n", pattern);
76 if (lseek(fd, offset, SEEK_SET) != offset)
77 errp("lseek(%"PRIu64"u) failed", offset);
79 unsigned long long speed = 0;
80 struct timespec stime, etime, itime;
81 clock_gettime(CLOCK_MONOTONIC, &stime);
84 off_t pos = offset, last_pos = 0;
87 while (pos < max_size) {
88 /* This will round up to sizeof(mem) ... */
89 ret = write(fd, mem, sizeof(mem));
91 if (ret != sizeof(mem)) {
93 printf("\nread() returned %zi (wanted %zu)\n%'llu MB/s over entire run\n",
94 ret, sizeof(mem), mbps(&itime, &etime, pos));
98 printf("%'llu bytes %u%% (%'llu MB/s)%20s\r", (unsigned long long)pos,
99 (unsigned)((pos * 100) / max_size), speed, "");
101 if ((++fsync_pos % 32) == 0) {
102 speed = mbps(&stime, &etime, pos - last_pos);
112 static void usage(int status)
115 status ? stderr : stdout,
116 "Usage: ddnuke [options] <dev>\n"
119 " -o <offset> Position to start writing\n"
120 " -r Write three times: 0x00, then 0xaa, then 0x55\n"
125 int main(int argc, char *argv[])
132 setlocale(LC_NUMERIC, "en_US");
134 while ((o = getopt(argc, argv, "ho:r")) != -1) {
137 offset = atoll(optarg);
142 case 'h': usage(EX_OK);
143 default: usage(EX_USAGE);
146 if (argc != optind + 1)
150 int fd = open(file, O_WRONLY|O_CLOEXEC);
152 errp("open(%s) failed", file);
154 off_t max_size = get_size(fd);
156 nuke(fd, offset, max_size, 0x00);
158 nuke(fd, offset, max_size, 0xaa);
159 nuke(fd, offset, max_size, 0x55);