I bring more love to everybody's favorite rm option.

So I'm wiping a file from a fairly slow USB stick and it's taking
forever.  I don't really give a shit about some guy with a quantum
tachyon microscope taking it apart, I just want the files to be gone
enough that a simple undelete tool won't bring them back.  The three
wipes is the charm approach of rm -P is a little heavy handed.

What I propose is making -P wipe the file once each time it's
provided.  I get the simple whack the data for good option I want, the
paranoid weirdos get the rm `jot -b -P 4096` scrubber they want.

Index: rm.1
===================================================================
RCS file: /cvs/src/bin/rm/rm.1,v
retrieving revision 1.34
diff -u -p -r1.34 rm.1
--- rm.1        4 Oct 2010 07:17:30 -0000       1.34
+++ rm.1        24 Jul 2012 03:30:50 -0000
@@ -77,13 +77,13 @@ option overrides any previous
 options.
 .It Fl P
 Overwrite regular files before deleting them.
-Files are overwritten three times, first with the byte pattern
+Files are overwritten once for each time the option is given, first with the
+byte pattern
 .Li 0xff ,
 then
 .Li 0x00 ,
-and then
-.Li 0xff
-again, before they are deleted.
+and then alternating between the two patterns as required,
+before they are deleted.
 Files with multiple links will be unlinked but not overwritten.
 .It Fl R
 Attempt to remove the file hierarchy rooted in each file argument.
Index: rm.c
===================================================================
RCS file: /cvs/src/bin/rm/rm.c,v
retrieving revision 1.25
diff -u -p -r1.25 rm.c
--- rm.c        18 Jun 2012 01:03:05 -0000      1.25
+++ rm.c        24 Jul 2012 03:27:54 -0000
@@ -49,7 +49,7 @@
 
 extern char *__progname;
 
-int dflag, eval, fflag, iflag, Pflag, stdin_ok;
+int dflag, eval, fflag, iflag, Pcount, stdin_ok;
 
 int    check(char *, char *, struct stat *);
 void   checkdot(char **);
@@ -73,7 +73,7 @@ main(int argc, char *argv[])
 
        setlocale(LC_ALL, "");
 
-       Pflag = rflag = 0;
+       Pcount = rflag = 0;
        while ((ch = getopt(argc, argv, "dfiPRr")) != -1)
                switch(ch) {
                case 'd':
@@ -88,7 +88,7 @@ main(int argc, char *argv[])
                        iflag = 1;
                        break;
                case 'P':
-                       Pflag = 1;
+                       Pcount++;
                        break;
                case 'R':
                case 'r':                       /* Compatibility. */
@@ -200,7 +200,7 @@ rm_tree(char **argv)
 
                case FTS_F:
                case FTS_NSOK:
-                       if (Pflag)
+                       if (Pcount)
                                rm_overwrite(p->fts_accpath, p->fts_info ==
                                    FTS_NSOK ? NULL : p->fts_statp);
                        /* FALLTHROUGH */
@@ -248,7 +248,7 @@ rm_file(char **argv)
                else if (S_ISDIR(sb.st_mode))
                        rval = rmdir(f);
                else {
-                       if (Pflag)
+                       if (Pcount)
                                rm_overwrite(f, &sb);
                        rval = unlink(f);
                }
@@ -261,7 +261,7 @@ rm_file(char **argv)
 
 /*
  * rm_overwrite --
- *     Overwrite the file 3 times with varying bit patterns.
+ *     Overwrite the file Pcount times with varying bit patterns.
  *
  * XXX
  * This is a cheap way to *really* delete files.  Note that only regular
@@ -277,7 +277,7 @@ rm_overwrite(char *file, struct stat *sb
        struct stat sb, sb2;
        struct statfs fsb;
        size_t bsize;
-       int fd;
+       int fd, i;
        char *buf = NULL;
 
        fd = -1;
@@ -308,14 +308,11 @@ rm_overwrite(char *file, struct stat *sb
        if ((buf = malloc(bsize)) == NULL)
                err(1, "%s: malloc", file);
 
-       if (!pass(0xff, fd, sbp->st_size, buf, bsize) || fsync(fd) ||
-           lseek(fd, (off_t)0, SEEK_SET))
-               goto err;
-       if (!pass(0x00, fd, sbp->st_size, buf, bsize) || fsync(fd) ||
-           lseek(fd, (off_t)0, SEEK_SET))
-               goto err;
-       if (!pass(0xff, fd, sbp->st_size, buf, bsize) || fsync(fd))
-               goto err;
+       for (i = 0; i < Pcount; i++) {
+               if (!pass(i & 0x1 ? 0xff : 0x00, fd, sbp->st_size, buf, bsize) 
||
+                   fsync(fd) || lseek(fd, (off_t)0, SEEK_SET))
+                       goto err;
+       }
        close(fd);
        free(buf);
        return (1);

Reply via email to