/* Reads a block device and wipe a block if non-zero. * Author: Peter Wu * Date: 2014-06-26 */ #include #include #include #include #include #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; }