]> git.wh0rd.org - home.git/blame - ddnuke.c
gdbinit: split up & migrate some to python
[home.git] / ddnuke.c
CommitLineData
d777d1fb
MF
1/*
2 * released into the public domain
3 * written by Mike Frysinger <vapier>
4 */
5
e5e72e45
MF
6#pragma GCC diagnostic warning "-Wall"
7#pragma GCC diagnostic warning "-Wextra"
8
d777d1fb
MF
9#define _FILE_OFFSET_BITS 64
10#define _LARGEFILE_SOURCE
11#define _LARGEFILE64_SOURCE
12#define _GNU_SOURCE
13
d3bb7a4d 14#include <err.h>
e5e72e45 15#include <errno.h>
d777d1fb
MF
16#include <fcntl.h>
17#include <inttypes.h>
18#include <locale.h>
d8ceb2d6 19#include <stdbool.h>
d777d1fb
MF
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
d8ceb2d6 23#include <sysexits.h>
d777d1fb
MF
24#include <time.h>
25#include <unistd.h>
e5e72e45
MF
26#include <sys/ioctl.h>
27#include <sys/stat.h>
28#include <linux/fs.h>
d777d1fb 29
d777d1fb
MF
30static unsigned long long mbps(struct timespec *stime, struct timespec *etime, off_t len)
31{
32 uint64_t dtime;
33 clock_gettime(CLOCK_MONOTONIC, etime);
34 dtime = ((etime->tv_sec - stime->tv_sec) * 1000 * 1000 * 1000) +
35 (etime->tv_nsec - stime->tv_nsec);
36 *stime = *etime;
37 return 1000 * len / dtime;
38}
39
e5e72e45
MF
40static off_t get_blk_size(int fd)
41{
42 uint64_t size;
43 if (ioctl(fd, BLKGETSIZE64, &size))
d3bb7a4d 44 err(1, "ioctl(BLKGETSIZE64) failed");
e5e72e45
MF
45 return size;
46}
47
48static off_t get_size(int fd)
49{
50 struct stat st;
51
52 if (fstat(fd, &st))
d3bb7a4d 53 err(1, "could not stat %i", fd);
e5e72e45
MF
54
55 if (S_ISREG(st.st_mode))
56 return st.st_size;
57 else if (S_ISBLK(st.st_mode))
58 return get_blk_size(fd);
59
60 errno = EINVAL;
d3bb7a4d 61 err(1, "unknown type of file");
e5e72e45
MF
62}
63
d8ceb2d6 64static void nuke(int fd, off_t offset, off_t max_size, unsigned char pattern)
d777d1fb 65{
d8ceb2d6
MF
66 static char mem[1024 * 1024];
67 memset(mem, pattern, sizeof(mem));
68 if (pattern)
69 printf("Writing 0x%X to the output\n", pattern);
d777d1fb 70
64f2ae36 71 if (lseek(fd, offset, SEEK_SET) != offset)
d3bb7a4d 72 err(1, "lseek(%"PRIu64"u) failed", offset);
64f2ae36 73
d777d1fb
MF
74 unsigned long long speed = 0;
75 struct timespec stime, etime, itime;
76 clock_gettime(CLOCK_MONOTONIC, &stime);
77 itime = stime;
78
e5e72e45 79 off_t pos = offset, last_pos = 0;
d777d1fb
MF
80 ssize_t ret;
81 int fsync_pos = 0;
e5e72e45 82 while (pos < max_size) {
d8ceb2d6
MF
83 /* This will round up to sizeof(mem) ... */
84 ret = write(fd, mem, sizeof(mem));
d777d1fb 85 pos += ret;
d8ceb2d6 86 if (ret != sizeof(mem)) {
64f2ae36
MF
87 if (pos != max_size)
88 printf("\nread() returned %zi (wanted %zu)\n%'llu MB/s over entire run\n",
89 ret, sizeof(mem), mbps(&itime, &etime, pos));
d8ceb2d6 90 return;
d777d1fb
MF
91 }
92
d3bb7a4d
MF
93 printf("\r\e[2K%'llu bytes %u%% (%'llu MB/s)", (unsigned long long)pos,
94 (unsigned)((pos * 100) / max_size), speed);
d777d1fb 95
64f2ae36 96 if ((++fsync_pos % 32) == 0) {
d777d1fb
MF
97 speed = mbps(&stime, &etime, pos - last_pos);
98 last_pos = pos;
99 fflush(stdout);
100 fsync(fd);
101 }
102 }
103
e5e72e45 104 printf("\n");
d8ceb2d6
MF
105}
106
107static void usage(int status)
108{
109 fprintf(
110 status ? stderr : stdout,
111 "Usage: ddnuke [options] <dev>\n"
112 "\n"
64f2ae36 113 "Options:\n"
d8ceb2d6 114 " -o <offset> Position to start writing\n"
64f2ae36 115 " -r Write three times: 0x00, then 0xaa, then 0x55\n"
d8ceb2d6
MF
116 );
117 exit(status);
118}
119
120int main(int argc, char *argv[])
121{
122 off_t offset = 0;
123 const char *file;
124 bool random = false;
125 int o;
126
127 setlocale(LC_NUMERIC, "en_US");
128
129 while ((o = getopt(argc, argv, "ho:r")) != -1) {
130 switch (o) {
131 case 'o':
132 offset = atoll(optarg);
133 break;
134 case 'r':
135 random = true;
136 break;
d3bb7a4d
MF
137 case 'h':
138 usage(EX_OK);
139 break;
140 default:
141 usage(EX_USAGE);
142 break;
d8ceb2d6
MF
143 }
144 }
145 if (argc != optind + 1)
146 usage(EX_USAGE);
147 file = argv[optind];
148
149 int fd = open(file, O_WRONLY|O_CLOEXEC);
150 if (fd == -1)
d3bb7a4d 151 err(1, "open(%s) failed", file);
d8ceb2d6
MF
152
153 off_t max_size = get_size(fd);
154
d8ceb2d6
MF
155 nuke(fd, offset, max_size, 0x00);
156 if (random) {
157 nuke(fd, offset, max_size, 0xaa);
158 nuke(fd, offset, max_size, 0x55);
159 }
160
161 return EX_OK;
d777d1fb 162}