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