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);