(Please CC me on your reply) Having recently deleted my /usr/lib by mistake (and gone through the pain of reinstalling all of my packages), I wrote a little Perl script which I have now aliased to "rm" in my .bashrc.
Basically, the wrapper (see attached file) has a blacklist which contains directories like /usr/lib, /home, /etc and removes those before passing its arguments to the real 'rm' command. I'm probably not the only person to have made this mistake and who wants to avoid doing it again. So I'm thinking of turning it into something that's useful to other people (probably packaging it in some form). If you have some ideas regarding things like: - how to get this script to be picked up before 'rm' in the PATH (including when using sudo) or whether it should be an alias in all of the shell global config files (like /etc/bash.bashrc) - where to find a good list of directories which should never be deleted - how to effectively disable it if one really wants to delete a system dir (for an alias, '\rm' does the trick, for a command in the path, maybe an environment variable?) - ways to detect directories expressed like "../../../usr/lib/../../usr/bin" - any other comments/suggestions you may have about the idea or the script Francois P.S. I realize that 'rm' is a low-level command which should do what it's told, but the reality is that a lot of people use it directly on a daily basis and can accidently hose their system. I don't want to implement a "command-line trashcan", but I'm looking for a way to prevent me from doing things I should never ask for (like 'rm -rf /usr/lib/').
#!/usr/bin/perl =head1 NAME safe-rm - safety wrapper around the rm command =head1 SYNOPSIS safe-rm [ ... ] (same arguments as rm =head1 DESCRIPTION safe-rm is a wrapper around 'rm' that checks the given arguments against a blacklist of directories which should never be removed. It is meant to be used instead of rm by aliasing rm to it. For example, in bash: alias rm='safe-rm' =head1 AUTHOR Francois Marier <[EMAIL PROTECTED]> =head1 SEE ALSO rm(1) =head1 COPYRIGHT Copyright (C) 2007 Francois Marier <[EMAIL PROTECTED]> safe-rm is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. safe-rm is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Email-Reminder; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. =cut use warnings; use strict; my %protected_dirs = ( '/bin' => 1, '/boot' => 1, '/dev' => 1, '/etc' => 1, '/home' => 1, '/initrd' => 1, '/lib' => 1, '/proc' => 1, '/root' => 1, '/sbin' => 1, '/sys' => 1, '/usr' => 1, '/usr/bin' => 1, '/usr/include' => 1, '/usr/lib' => 1, '/usr/local' => 1, '/usr/local/bin' => 1, '/usr/local/include' => 1, '/usr/local/sbin' => 1, '/usr/local/share' => 1, '/usr/sbin' => 1, '/usr/share' => 1, '/usr/src' => 1, '/var' => 1, ); my @allowed_args = (); for (my $i = 0; $i <= $#ARGV; $i++) { my $pathname = $ARGV[$i]; # Normalize the pathname my $normalized_pathname = $pathname; if ($pathname =~ m|^(.*?)/+$|) { # Trim leading slashes $normalized_pathname = $1; } # TODO: Get the absolute name (to catch things like ../../usr/lib/ from /usr/lib/ or ./etc from /) # Check against the blacklist if (exists($protected_dirs{$normalized_pathname})) { print STDERR "Skipping $pathname\n"; } else { push @allowed_args, $pathname; } } # Run rm if there is at least one argument left my $errcode = 0; if (@allowed_args > 0) { my $status = system('rm', @allowed_args); $errcode = $status >> 8; } exit $errcode;