#define _SHRED_C #include #include #include #include #include #include #include #include #include "config.h" static char f_flag; static char u_flag; static char z_flag; static int n_loops = 3; static int shred(int rand_fd, int fd) { /* Get size */ off_t size = lseek(fd, 0, SEEK_END); if (size <= 0) return 1; void *buf = mmap(NULL, size, PROT_WRITE, MAP_SHARED, fd, 0); if (buf == MAP_FAILED) { fprintf(stderr, "shred: mmap: %s\n", strerror(errno)); return 1; } for (char n = 0; n < n_loops; n++) { if (read(rand_fd, buf, size) == 0) fprintf(stderr, "shred: %s", strerror(errno)); fsync(fd); } if (z_flag) memset(buf, 0, size); if (munmap(buf, size)) { fprintf(stderr, "shred: munmap: %s\n", strerror(errno)); return 1; } return 0; } int main(int argc, char **argv) { int opt; while ((opt = getopt(argc, argv, "fuzn:")) != -1) { switch (opt) { case 'f': f_flag = 1; break; case 'u': u_flag = 1; break; case 'z': z_flag = 1; break; case 'n': n_loops = atoi(optarg); break; default: puts("shred [fuzn] [file1 file2...]\n\t-n N Overwrite N times, default 3\n\t-z Final overwrite with zeros\n\t-u Remove file\n\t-f Chmod to ensure writability"); return 0; } } argv += optind; argc -= optind; if (argc == 0) { fprintf(stderr, "shred: missing operand\n"); return 1; } int rand_fd = open(RAND_SOURCE, O_RDONLY); if (rand_fd < 0) { fprintf(stderr, "shred: %s: %s\n", RAND_SOURCE, strerror(errno)); return 1; } for (int i = 0; i < argc; i++) { int fd = open(argv[i], O_RDWR); if (fd < 0) { fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno)); continue; } shred(rand_fd, fd); fsync(fd); close(fd); if (f_flag) { if (chmod(argv[i], 0) < 0) fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno)); } if (u_flag) { if (unlink(argv[i]) < 0) fprintf(stderr, "shred: %s is %s\n", argv[i], strerror(errno)); } } close(rand_fd); return 0; }