]> git.wh0rd.org - home.git/blob - ddnuke.c
faster dd helper for erasing drivers
[home.git] / ddnuke.c
1 /*
2 * released into the public domain
3 * written by Mike Frysinger <vapier>
4 */
5
6 #define _FILE_OFFSET_BITS 64
7 #define _LARGEFILE_SOURCE
8 #define _LARGEFILE64_SOURCE
9 #define _GNU_SOURCE
10
11 #include <fcntl.h>
12 #include <inttypes.h>
13 #include <locale.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <time.h>
18 #include <unistd.h>
19
20 static const char zero[1024 * 1024];
21
22 #define errp(msg, args...) \
23 do { \
24 printf("%s: " msg ": %m\n", argv[0], ## args); \
25 return 1; \
26 } while (0)
27
28 static unsigned long long mbps(struct timespec *stime, struct timespec *etime, off_t len)
29 {
30 uint64_t dtime;
31 clock_gettime(CLOCK_MONOTONIC, etime);
32 dtime = ((etime->tv_sec - stime->tv_sec) * 1000 * 1000 * 1000) +
33 (etime->tv_nsec - stime->tv_nsec);
34 *stime = *etime;
35 return 1000 * len / dtime;
36 }
37
38 int main(int argc, char *argv[])
39 {
40 off_t offset = 0;
41 const char *file;
42
43 setlocale(LC_NUMERIC, "en_US");
44
45 switch (argc) {
46 case 3:
47 offset = atoll(argv[2]);
48 case 2:
49 file = argv[1];
50 break;
51 default:
52 puts("Usage: ddnuke <dev> [offset in bytes]");
53 return 1;
54 }
55
56 int fd = open(file, O_WRONLY);
57 if (fd == -1)
58 errp("open(%s) failed", file);
59
60 if (lseek(fd, offset, SEEK_SET) != offset)
61 errp("lseek(%"PRIu64"u) failed", offset);
62
63 unsigned long long speed = 0;
64 struct timespec stime, etime, itime;
65 clock_gettime(CLOCK_MONOTONIC, &stime);
66 itime = stime;
67
68 off_t pos = 0, last_pos = 0;
69 ssize_t ret;
70 int fsync_pos = 0;
71 while (1) {
72 ret = write(fd, zero, sizeof(zero));
73 pos += ret;
74 if (ret != sizeof(zero)) {
75 printf("\ngot back %zi (wanted %zu)\n%'llu MB/s over entire run\n",
76 ret, sizeof(zero), mbps(&itime, &etime, pos));
77 return 0;
78 }
79
80 printf("%'llu bytes (%'llu MB/s)%20s\r", (unsigned long long)pos, speed, "");
81
82 if ((++fsync_pos % 16) == 0) {
83 speed = mbps(&stime, &etime, pos - last_pos);
84 last_pos = pos;
85 fflush(stdout);
86 fsync(fd);
87 }
88 }
89
90 return 0;
91 }