summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Wu <peter@lekensteyn.nl>2014-06-26 21:55:31 +0200
committerPeter Wu <peter@lekensteyn.nl>2014-06-26 21:55:31 +0200
commitc28bcc04f41f6b70e43fff87959ecf819388064c (patch)
tree809b5e947350eb667ddece5fcb7d3f661afad3cc
parent80172b86edfb4a46a26de13c741a8da97d1b7713 (diff)
downloadc-files-c28bcc04f41f6b70e43fff87959ecf819388064c.tar.gz
wipe-sectors: wipe sectors which are non-zero
-rw-r--r--wipe-sectors.c98
1 files changed, 98 insertions, 0 deletions
diff --git a/wipe-sectors.c b/wipe-sectors.c
new file mode 100644
index 0000000..cac0028
--- /dev/null
+++ b/wipe-sectors.c
@@ -0,0 +1,98 @@
+/* Reads a block device and wipe a block if non-zero.
+ * Author: Peter Wu <peter@lekensteyn.nl>
+ * Date: 2014-06-26
+ */
+#include <fcntl.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <err.h>
+#include <stdlib.h>
+
+#define BUFSIZE (1024 * 1024 * 2)
+
+static char zeroes[BUFSIZE];
+
+static void wipe(int fd, size_t len) {
+ off_t pos;
+ ssize_t r;
+
+ pos = lseek(fd, -len, SEEK_CUR);
+ if (pos == (off_t) -1)
+ err(1, "failed to seek before write");
+
+ r = write(fd, zeroes, len);
+ if (r < 0)
+ err(1, "failed to write zeroes");
+ if ((size_t) r != len)
+ errx(1, "could only write %zu instead of %zu bytes", r, len);
+}
+
+static void read_and_wipe(int fd) {
+ ssize_t r;
+ off_t endpos, pos;
+ char *buf = malloc(BUFSIZE);
+ unsigned iteration = 0, rounds;
+ if (buf == NULL)
+ err(1, "malloc");
+
+ endpos = lseek(fd, 0, SEEK_END);
+ if (endpos == (off_t) -1)
+ err(1, "failed to seek end");
+ if (endpos == 0) {
+ warnx("file is empty");
+ return;
+ }
+
+ pos = lseek(fd, 0, SEEK_SET);
+ if (pos == (off_t) -1)
+ err(1, "failed to seek to begin");
+
+ rounds = endpos / BUFSIZE;
+ if (rounds * BUFSIZE < endpos)
+ ++rounds;
+
+ do {
+ r = read(fd, buf, BUFSIZE);
+ printf("\r%u/%u -- %u%% (%llu/%llu)",
+ iteration, rounds,
+ (unsigned) (100 * pos / endpos),
+ (long long) pos, (long long) endpos);
+ if (r < 0) {
+ warn("read failed");
+ } else if (r > 0) {
+ char val = 0;
+ int i;
+ for (i = 0; i < r; i++) {
+ val |= buf[i];
+ }
+ pos += r;
+ /* if there are any non-zero bytes, act accordingly */
+ if (val != 0) {
+ printf(" WIPE ME!\n");
+ wipe(fd, r);
+ }
+ }
+ fflush(stdout);
+ ++iteration;
+ } while (r > 0);
+ putchar('\n');
+
+ free(buf);
+}
+
+int main(int argc, char **argv) {
+ int fd;
+
+ if (argc < 2)
+ errx(1, "Missing device argument");
+
+ fd = open(argv[1], O_RDWR);
+ if (fd < 0)
+ err(1, "failed to open file");
+
+ read_and_wipe(fd);
+
+ close(fd);
+
+ return 0;
+}