]>
git.wh0rd.org - home.git/blob - ddnuke.c
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
28 #include <sys/ioctl.h>
30 #include <sys/types.h>
34 static unsigned long long mbps(struct timespec
*stime
, struct timespec
*etime
, off_t len
)
37 clock_gettime(CLOCK_MONOTONIC
, etime
);
38 dtime
= ((etime
->tv_sec
- stime
->tv_sec
) * 1000 * 1000 * 1000) +
39 (etime
->tv_nsec
- stime
->tv_nsec
);
41 return 1000 * len
/ dtime
;
44 static off_t
get_blk_size(int fd
)
47 if (ioctl(fd
, BLKGETSIZE64
, &size
))
48 err(EX_DATAERR
, "ioctl(BLKGETSIZE64) failed");
52 static off_t
get_size(int fd
)
57 err(EX_DATAERR
, "could not stat %i", fd
);
59 if (S_ISREG(st
.st_mode
))
61 else if (S_ISBLK(st
.st_mode
))
62 return get_blk_size(fd
);
65 err(EX_DATAERR
, "unknown type of file");
68 static void nuke(int fd
, off_t block_size
, off_t offset
, off_t max_size
, off_t flush_count
, unsigned char pattern
)
71 memset(mem
, pattern
, sizeof(mem
));
73 printf("Writing 0x%X to the output\n", pattern
);
75 if (lseek(fd
, offset
, SEEK_SET
) != offset
)
76 err(EX_DATAERR
, "lseek(%"PRIu64
"u) failed", offset
);
78 unsigned long long speed
= 0;
79 struct timespec stime
, etime
, itime
;
80 clock_gettime(CLOCK_MONOTONIC
, &stime
);
83 off_t pos
= offset
, last_pos
= 0;
86 while (pos
< max_size
) {
87 /* This will round up to sizeof(mem) ... */
88 ret
= write(fd
, mem
, sizeof(mem
));
90 if (ret
!= block_size
) {
92 printf("\nread() returned %zi (wanted %zu)\n%'llu MB/s over entire run\n",
93 ret
, sizeof(mem
), mbps(&itime
, &etime
, pos
));
97 unsigned long long eta
= speed
? (max_size
- pos
) / (speed
* 1000 * 1000) : 0;
98 printf("\r%'llu bytes %u%% (%'llu MB/s) (ETA ~%llum%llus)\e[K",
99 (unsigned long long)pos
, (unsigned)((pos
* 100) / max_size
), speed
,
102 if ((++fsync_pos
% flush_count
) == 0) {
103 speed
= mbps(&stime
, &etime
, pos
- last_pos
);
113 static void usage(int status
)
116 status
? stderr
: stdout
,
117 "Usage: ddnuke [options] <dev>\n"
121 " -y Assume yes to all prompts\n"
122 " -b <size> How many bytes to write at once. (default: 1Mib)\n"
123 " -f <count> How many blocks to write before flush (stdout & disk). (default: 32)\n"
124 " -o <offset> Position to start writing\n"
125 " -r Write three times: 0x00, then 0xaa, then 0x55\n"
130 int main(int argc
, char *argv
[])
132 off_t block_size
= 1024 * 1024;
133 off_t flush_count
= 32;
141 setlocale(LC_NUMERIC
, "en_US");
143 while ((o
= getopt(argc
, argv
, "hb:f:o:qry")) != -1) {
146 block_size
= atoll(optarg
);
149 flush_count
= atoll(optarg
);
152 offset
= atoll(optarg
);
171 if (argc
!= optind
+ 1)
175 int fd
= open(file
, O_WRONLY
|O_CLOEXEC
);
177 err(EX_NOINPUT
, "open(%s) failed", file
);
181 const char *argv
[] = {"fdisk", "-l", file
, NULL
};
182 if (posix_spawnp(&pid
, argv
[0], NULL
, NULL
, (char *const *)argv
, NULL
))
183 err(EX_OSERR
, "spawn(%s %s) failed", argv
[0], file
);
184 waitpid(pid
, NULL
, 0);
189 printf("Do you want to wipe '%s'? (y/N) ", file
);
192 if (fread(&c
, 1, 1, stdin
)) {/* don't care */}
193 if (tolower(c
) != 'y')
194 errx(EX_UNAVAILABLE
, "User decided not to wipe");
197 off_t max_size
= get_size(fd
);
199 nuke(fd
, block_size
, offset
, max_size
, flush_count
, 0x00);
201 nuke(fd
, block_size
, offset
, max_size
, flush_count
, 0xaa);
202 nuke(fd
, block_size
, offset
, max_size
, flush_count
, 0x55);