bug-coreutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

RE: Shred recursive


From: Patterson, Shaun M Mr CTR USA AMC
Subject: RE: Shred recursive
Date: Mon, 29 Jun 2009 12:47:12 -0500

Well if anyone is interested the patch is below.

This is my first GNU submission...I tried to follow the GNU coding rules as 
best as possible.  I'm open to criticism.

--
Shaun

--- shred.c.orig        2009-06-29 13:36:11.485435000 -0400
+++ shred.c     2009-06-29 13:40:59.278678000 -0400
@@ -22,7 +22,6 @@
    - use consistent non-capitalization in error messages
    - add standard GNU copyleft comment
 
-  - Add -r/-R/--recursive
   - Add -i/--interactive
   - Reserve -d
   - Add -L
@@ -98,8 +97,14 @@
 #include "fcntl--.h"
 #include "human.h"
 #include "quotearg.h"          /* For quotearg_colon */
+#include "quote.h"
 #include "randint.h"
 #include "randread.h"
+#include "savedir.h"
+#include "filenamecat.h"
+
+
+
 
 /* Default number of times to overwrite.  */
 enum { DEFAULT_PASSES = 3 };
@@ -118,6 +123,7 @@
 {
   bool force;          /* -f flag: chmod files if necessary */
   size_t n_iterations; /* -n flag: Number of iterations */
+  bool recursive;       /* -R flag: Recursively shred directories */
   off_t size;          /* -s flag: size of file */
   bool remove_file;    /* -u flag: remove file after shredding */
   bool verbose;                /* -v flag: Print progress */
@@ -137,6 +143,7 @@
   {"exact", no_argument, NULL, 'x'},
   {"force", no_argument, NULL, 'f'},
   {"iterations", required_argument, NULL, 'n'},
+  {"recursive", no_argument, NULL, 'R'},
   {"size", required_argument, NULL, 's'},
   {"random-source", required_argument, NULL, RANDOM_SOURCE_OPTION},
   {"remove", no_argument, NULL, 'u'},
@@ -147,6 +154,24 @@
   {NULL, 0, NULL, 0}
 };
 
+
+/* For removing directories */
+extern int
+rmdir (char const *dir);
+
+static bool
+do_shred (char *cwd, const char *file_to_shred, 
+                 struct randint_source *randint_source, struct Options const 
*flags);
+
+static bool
+shred_internal (char *cwd, const char *file_to_shred, 
+                               struct randint_source *randint_source, struct 
Options const *flags);
+
+static bool
+wipefile (char *name, char const *qname,
+         struct randint_source *s, struct Options const *flags);
+
+
 void
 usage (int status)
 {
@@ -168,6 +193,7 @@
   -f, --force    change permissions to allow writing if necessary\n\
   -n, --iterations=N  overwrite N times instead of the default (%d)\n\
       --random-source=FILE  get random bytes from FILE\n\
+  -r, -R, --recursive    shred directories recursively\n\
   -s, --size=N   shred this many bytes (suffixes like K, M, G accepted)\n\
 "), DEFAULT_PASSES);
       fputs (_("\
@@ -1017,6 +1043,7 @@
       while (incname (base, len));
       len--;
     }
+
   if (unlink (oldname) != 0)
     {
       error (0, errno, _("%s: failed to remove"), qoldname);
@@ -1024,6 +1051,7 @@
     }
   else if (flags->verbose)
     error (0, 0, _("%s: removed"), qoldname);
+
   if (0 <= dir_fd)
     {
       if (dosync (dir_fd, qdir) != 0)
@@ -1040,6 +1068,122 @@
   return ok;
 }
 
+
+/*
+ * Workhorse of the shred operation. 
+ *
+ * Recursively shreds down directories if the recursive flag was passed
+ */
+static bool
+shred_internal (char *full_path_name, const char *file_to_shred,
+                               struct randint_source *randint_source, struct 
Options const *flags) 
+{
+  struct stat st;
+  bool ok = false;
+  
+  if (lstat (full_path_name, &st) < 0)
+    {
+         error (0, 0, _("failed to get attributes of %s"), quote 
(full_path_name));
+      return false;
+    }
+
+  /* If name is a directory, list all the files and recursively 
+   *  shred on them */
+  if (S_ISDIR (st.st_mode)) 
+       {
+         /* Shredding directory */
+
+         if (flags->recursive) 
+               {
+               /* Recursive flag set, grab all files/dirs in the directory
+                *  and shred */
+
+               /* For clarity */
+               char *cwd = full_path_name;
+
+               /* Get a list of files in this directory */
+               char *files_in_directory = savedir (cwd);
+
+               char *file_name = files_in_directory;
+               while (*file_name != '\0')
+                 {
+                   ok &= do_shred (cwd, file_name, randint_source, flags);
+
+
+                       file_name += strlen (file_name) + 1;
+                 }
+                       
+               
+               if (flags->remove_file) 
+                 {
+                       if (rmdir (cwd) != 0)
+                         {
+                               error (0, errno, _("%s: failed to remove 
directory"), cwd);
+                               ok = false;
+                         }
+                       else if (flags->verbose)
+                         error (0, 0, _("%s: removed"), cwd);
+                 }
+
+               free (files_in_directory);
+               
+               } 
+         else 
+               {
+                 /* Do not shred directory */
+                 error (0, 0, _("omitting directory %s"), quote 
(full_path_name));
+                 return false;
+               }
+
+
+       }
+   else
+       {
+         /* Shredding file */
+         char *qfull_path_name = xstrdup (quotearg_colon (full_path_name));
+
+         if (STREQ (file_to_shred, "-"))
+               {
+                 ok &= wipefd (STDOUT_FILENO, qfull_path_name, randint_source, 
flags);
+               }
+         else
+               {
+                 ok &= wipefile (full_path_name, qfull_path_name, 
randint_source, flags);
+               }
+
+         free (qfull_path_name);
+       }
+
+   return ok;
+}
+
+
+/*
+ * Shred file_to_shred
+ *
+ * If file_to_shred is a directory, the directory will be recursively shredded
+ *  if the recursive option is set
+ *
+ */
+static bool
+do_shred (char *cwd, const char *file_to_shred, 
+                 struct randint_source *randint_source, struct Options const 
*flags)
+{
+  /* current directory combined with the inputted file name */
+  char *full_path_name = file_name_concat (cwd, file_to_shred, NULL);
+
+  bool ok = false;
+  
+  ok = shred_internal (full_path_name, file_to_shred, randint_source, flags);
+
+  free (full_path_name);
+
+  return ok;
+}
+
+
+
+
 /*
  * Finally, the function that actually takes a filename and grinds
  * it into hamburger.
@@ -1114,10 +1258,17 @@
 
   atexit (close_stdout);
 
+  /* Init flags to defaults */
+  flags.force = false;
   flags.n_iterations = DEFAULT_PASSES;
+  flags.recursive = false;
   flags.size = -1;
+  flags.remove_file = false;
+  flags.verbose = false;
+  flags.exact = false;
+  flags.zero_fill = false;
 
-  while ((c = getopt_long (argc, argv, "fn:s:uvxz", long_opts, NULL)) != -1)
+  while ((c = getopt_long (argc, argv, "rRfn:s:uvxz", long_opts, NULL)) != -1)
     {
       switch (c)
        {
@@ -1144,6 +1295,11 @@
          random_source = optarg;
          break;
 
+       case 'r':
+       case 'R':
+         flags.recursive = true;
+         break;
+
        case 'u':
          flags.remove_file = true;
          break;
@@ -1198,17 +1354,9 @@
 
   for (i = 0; i < n_files; i++)
     {
-      char *qname = xstrdup (quotearg_colon (file[i]));
-      if (STREQ (file[i], "-"))
-       {
-         ok &= wipefd (STDOUT_FILENO, qname, randint_source, &flags);
-       }
-      else
-       {
-         /* Plain filename - Note that this overwrites *argv! */
-         ok &= wipefile (file[i], qname, randint_source, &flags);
-       }
-      free (qname);
+      /* Note that this overwrites *argv! */
+      ok &= do_shred ("", file [i], randint_source, &flags);
+
     }
 
   exit (ok ? EXIT_SUCCESS : EXIT_FAILURE);



 

-----Original Message-----
From: Pádraig Brady [mailto:address@hidden 
Sent: Monday, June 29, 2009 9:42 AM
To: Patterson, Shaun M Mr CTR USA AMC
Cc: address@hidden
Subject: Re: Shred recursive

Patterson, Shaun M Mr CTR USA AMC wrote:
> I have implemented a -r/-R/--recursive option in shred. Anyone 
> interested or is piping shred with a find command enough?

Hmm, it's one of those marginal ones.
You wouldn't gain much really over using find.
Though in saying that, rm has this option, so it might be worthwhile to add to 
allow one to: alias rm=shred Though I would never do that myself.

My vote is 60:40 against.

cheers,
Pádraig.




reply via email to

[Prev in Thread] Current Thread [Next in Thread]