changeset 1598:50daa0da1530 draft

Add shred.
author Rob Landley <rob@landley.net>
date Thu, 04 Dec 2014 16:42:01 -0600
parents 5de199de14ba
children cd97856ca52c
files toys/other/shred.c
diffstat 1 files changed, 104 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/toys/other/shred.c	Thu Dec 04 16:42:01 2014 -0600
@@ -0,0 +1,104 @@
+/* shred.c - Overwrite a file to securely delete
+ *
+ * Copyright 2014 Rob Landley <rob@landley.net>
+ *
+ * No standard
+
+USE_SHRED(NEWTOY(shred, "<1zxus#<1n#<1o#<0f", TOYFLAG_USR|TOYFLAG_BIN))
+
+config SHRED
+  bool "shred"
+  default n
+  help
+    usage: shred [-fuz] [-n COUNT] [-s SIZE] FILE...
+
+    Securely delete a file by overwriting its contents with random data.
+
+    -f        Force (chmod if necessary)
+    -n COUNT  Random overwrite iterations (default 1)
+    -o OFFSET Start at OFFSET
+    -s SIZE   Use SIZE instead of detecting file size
+    -u        unlink (actually delete file when done)
+    -x        Use exact size (default without -s rounds up to next 4k)
+    -z        zero at end
+
+    Note: data journaling filesystems render this command useless, you must
+    overwrite all free space (fill up disk) to erase old data on those.
+*/
+
+#define FOR_shred
+#include "toys.h"
+
+GLOBALS(
+  long offset;
+  long iterations;
+  long size;
+
+  int ufd;
+)
+
+void shred_main(void)
+{
+  char **try;
+
+  if (!(toys.optflags & FLAG_n)) TT.iterations++;
+  TT.ufd = xopen("/dev/urandom", O_RDONLY);
+
+  // We don't use loopfiles() here because "-" isn't stdin, and want to
+  // respond to files we can't open via chmod.
+
+  for (try = toys.optargs; *try; try++) {
+    off_t pos = 0, len = TT.size;
+    int fd = open(*try, O_RDWR), iter = 0, throw;
+
+    // do -f chmod if necessary
+    if (fd == -1 && (toys.optflags & FLAG_f)) {
+      chmod(*try, 0600);
+      fd = open(*try, O_RDWR);
+    }
+    if (fd == -1) {
+      perror_msg("%s", *try);
+      continue;
+    }
+
+    // determine length
+    if (!len) len = fdlength(fd);
+    if (len<1) {
+      error_msg("%s: needs -s", *try);
+      close(fd);
+      continue;
+    }
+
+    // Loop through, writing to this file
+    for (;;) {
+      // Advance to next -n or -z?
+
+      if (pos >= len) {
+        pos = -1;
+        if (++iter == TT.iterations && (toys.optargs && FLAG_z)) {
+          memset(toybuf, 0, sizeof(toybuf));
+          continue;
+        }
+        if (iter >= TT.iterations) break;
+      }
+
+      if (pos < TT.offset) {
+        if (TT.offset != lseek(fd, TT.offset, SEEK_SET)) {
+          perror_msg("%s", *try);
+          break;
+        }
+        pos = TT.offset;
+      }
+
+      // Determine length, read random data if not zeroing, write.
+
+      throw = sizeof(toybuf);
+      if (toys.optflags & FLAG_x)
+        if (len-pos < throw) throw = len-pos;
+
+      if (iter != TT.iterations) xread(TT.ufd, toybuf, throw);
+      if (throw != writeall(fd, toybuf, throw)) perror_msg("%s");
+      pos += throw;
+    }
+  }
+}