5 safe-rm - wrapper around the rm command to prevent accidental deletions
10 (same arguments as rm)
14 safe-rm prevents the accidental deletion of important files by
15 replacing rm with a wrapper which checks the given arguments against a
16 configurable blacklist of files and directories which should never be
19 Users who attempt to delete one of these protected files or
20 directories will not be able to do so and will be shown a warning
23 safe-rm is meant to replace the rm command so you can achieve this by
24 putting a symbolic link with the name "rm" in a directory which sits
25 at the front of your path. For example, given this path:
27 PATH=/usr/local/bin:/bin:/usr/bin
29 You could create the following symlink:
31 ln -s /usr/local/bin/safe-rm /usr/local/bin/rm
33 =head1 CONFIGURATION FILES
35 Protected paths can be set both at the site and user levels.
37 Both of these configuation files can contain a list of important files
38 or directories (one per line):
43 If both of these are empty, a default list of important paths will be
48 Francois Marier <francois@safe-rm.org.nz>
56 Copyright (C) 2008-2009 Francois Marier
58 This program is free software: you can redistribute it and/or modify
59 it under the terms of the GNU General Public License as published by
60 the Free Software Foundation, either version 3 of the License, or
61 (at your option) any later version.
63 This program is distributed in the hope that it will be useful,
64 but WITHOUT ANY WARRANTY; without even the implied warranty of
65 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
66 GNU General Public License for more details.
68 You should have received a copy of the GNU General Public License
69 along with this program. If not, see <http://www.gnu.org/licenses/>.
77 my %default_protected_dirs = ( '/bin' => 1,
93 '/usr/local/bin' => 1,
94 '/usr/local/include' => 1,
95 '/usr/local/sbin' => 1,
96 '/usr/local/share' => 1,
103 my %protected_dirs = ();
105 # Read in system-wide configuration file
106 if (open my $systemwide_cfg, '<', '/etc/safe-rm.conf') {
107 while (<$systemwide_cfg>) {
109 $protected_dirs{$_} = 1;
111 close($systemwide_cfg);
114 # Read in user configuration file
115 my $homedir = $ENV{HOME
} || '';
116 if (open my $user_cfg, '<', "$homedir/.safe-rm") {
117 while (<$user_cfg>) {
119 $protected_dirs{$_} = 1;
124 if (0 == scalar keys %protected_dirs) {
125 %protected_dirs = %default_protected_dirs;
128 my @allowed_args = ();
132 # Normalize the pathname
133 my $normalized_pathname = $pathname;
134 if ($normalized_pathname =~ m
|/| or -e
"$normalized_pathname") {
135 # Convert to an absolute path (e.g. remove "..")
136 $normalized_pathname = realpath
($normalized_pathname);
137 if (!$normalized_pathname) {
138 $normalized_pathname = $pathname;
141 if ($normalized_pathname =~ m
|^(.+?
)/+$|ms
) {
142 # Trim trailing slashes
143 $normalized_pathname = $1;
146 # Check against the blacklist
147 if (exists($protected_dirs{$normalized_pathname})) {
148 print STDERR
"Skipping $pathname\n";
150 push @allowed_args, $pathname;
156 my $real_rm = '/bin/rm';
157 if (realpath
($real_rm) eq realpath
($0)) {
158 die 'Cannot find the real "rm" binary'."\n";
160 my $status = system($real_rm, @allowed_args);
161 $errcode = $status >> 8;