diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/shred.c | 49 |
1 files changed, 39 insertions, 10 deletions
diff --git a/src/shred.c b/src/shred.c index 95a255a5b..6f5b4da65 100644 --- a/src/shred.c +++ b/src/shred.c @@ -82,6 +82,7 @@ #include <sys/types.h> #include "system.h" +#include "argmatch.h" #include "xstrtol.h" #include "error.h" #include "fcntl--.h" @@ -104,12 +105,30 @@ enum { SECTOR_SIZE = 512 }; enum { SECTOR_MASK = SECTOR_SIZE - 1 }; verify (0 < SECTOR_SIZE && (SECTOR_SIZE & SECTOR_MASK) == 0); +enum remove_method +{ + remove_none = 0, /* the default: only wipe data. */ + remove_unlink, /* don't obfuscate name, just unlink. */ + remove_wipe, /* obfuscate name before unlink. */ + remove_wipesync /* obfuscate name, syncing each byte, before unlink. */ +}; + +static char const *const remove_args[] = +{ + "unlink", "wipe", "wipesync", NULL +}; + +static enum remove_method const remove_methods[] = +{ + remove_unlink, remove_wipe, remove_wipesync +}; + struct Options { bool force; /* -f flag: chmod files if necessary */ size_t n_iterations; /* -n flag: Number of iterations */ off_t size; /* -s flag: size of file */ - bool remove_file; /* -u flag: remove file after shredding */ + enum remove_method remove_file; /* -u flag: remove file after shredding */ bool verbose; /* -v flag: Print progress */ bool exact; /* -x flag: Do not round up file size */ bool zero_fill; /* -z flag: Add a final zero pass */ @@ -129,7 +148,7 @@ static struct option const long_opts[] = {"iterations", required_argument, NULL, 'n'}, {"size", required_argument, NULL, 's'}, {"random-source", required_argument, NULL, RANDOM_SOURCE_OPTION}, - {"remove", no_argument, NULL, 'u'}, + {"remove", optional_argument, NULL, 'u'}, {"verbose", no_argument, NULL, 'v'}, {"zero", no_argument, NULL, 'z'}, {GETOPT_HELP_OPTION_DECL}, @@ -159,7 +178,7 @@ for even very expensive hardware probing to recover the data.\n\ -s, --size=N shred this many bytes (suffixes like K, M, G accepted)\n\ "), DEFAULT_PASSES); fputs (_("\ - -u, --remove truncate and remove file after overwriting\n\ + -u, --remove[=HOW] truncate and remove file after overwriting; See below\n\ -v, --verbose show progress\n\ -x, --exact do not round file sizes up to the next full block;\n\ this is the default for non-regular files\n\ @@ -173,8 +192,12 @@ If FILE is -, shred standard output.\n\ \n\ Delete FILE(s) if --remove (-u) is specified. The default is not to remove\n\ the files because it is common to operate on device files like /dev/hda,\n\ -and those files usually should not be removed. When operating on regular\n\ -files, most people use the --remove option.\n\ +and those files usually should not be removed.\n\ +The optional HOW parameter indicates how to remove a directory entry:\n\ +'unlink' => use a standard unlink call.\n\ +'wipe' => also first obfuscate bytes in the name.\n\ +'wipesync' => also sync each obfuscated byte to disk.\n\ +The default mode is 'wipesync', but note it can be expensive.\n\ \n\ "), stdout); fputs (_("\ @@ -965,8 +988,8 @@ incname (char *name, size_t len) /* * Repeatedly rename a file with shorter and shorter names, - * to obliterate all traces of the file name on any system that - * adds a trailing delimiter to on-disk file names and reuses + * to obliterate all traces of the file name (and length) on any system + * that adds a trailing delimiter to on-disk file names and reuses * the same directory slot. Finally, unlink it. * The passed-in filename is modified in place to the new filename. * (Which is unlinked if this function succeeds, but is still present if @@ -999,13 +1022,15 @@ wipename (char *oldname, char const *qoldname, struct Options const *flags) char *qdir = xstrdup (quotearg_colon (dir)); bool first = true; bool ok = true; + int dir_fd = -1; - int dir_fd = open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); + if (flags->remove_file == remove_wipesync) + dir_fd = open (dir, O_RDONLY | O_DIRECTORY | O_NOCTTY | O_NONBLOCK); if (flags->verbose) error (0, 0, _("%s: removing"), qoldname); - while (len) + while ((flags->remove_file != remove_unlink) && len) { memset (base, nameset[0], len); base[len] = 0; @@ -1175,7 +1200,11 @@ main (int argc, char **argv) break; case 'u': - flags.remove_file = true; + if (optarg == NULL) + flags.remove_file = remove_wipesync; + else + flags.remove_file = XARGMATCH ("--remove", optarg, + remove_args, remove_methods); break; case 's': |