-
Notifications
You must be signed in to change notification settings - Fork 45
/
rm
246 lines (214 loc) · 6.01 KB
/
rm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
#!/usr/bin/perl -w
#############################################################################
# A simple compatible version of rm( 1 ) written in Perl.
#############################################################################
#
# Copyright (c) Steve Kemp 1999, [email protected]
#
# To do:-
# Currently the interactive and force options are not handled
# totally correctly. According to the man pages for RM the
# option placement matters, so a -f will override an _earlier_
# -i, etc.
#
# This program 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 2
# of the License, or (at your option) any later version.
#
# This program 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 this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
##############################################################################
# Packages we use.
use strict;
use Getopt::Std;
# Command line arguments, and other variables.
use vars qw( $opt_i $opt_f $opt_r $opt_R $opt_P );
my $arg = 0;
# Get the options.
&getOptions();
#
# Process each file named on the command line.
foreach $arg ( @ARGV )
{
&processFile( $arg );
}
#
# Attempt to process each file / directory named on the command line.
sub processFile()
{
my ( $fileName )= @_;
# See if the file is a directory.
if ( ( -d $fileName ) && ( $opt_r || $opt_R ))
{
# Remove a directory recursively.
removeDirectory( $fileName );
}
elsif ( ( -d $fileName ) && !( $opt_r || $opt_R ) && (!$opt_i ))
{
rmdir( $fileName );
}
elsif( -f $fileName )
{
removeFile( $fileName );
}
}
#
# Recursively remove a directory
sub removeDirectory( )
{
my ( $dirName ) = @_;
my ( $path );
unless (opendir(DIR, $dirName))
{
warn "Can't open $dirName\n";
closedir(DIR);
return;
}
foreach (readdir(DIR))
{
next if $_ eq '.' || $_ eq '..';
$path = "$dirName/$_";
if (-d $path)
{
&removeDirectory($path);
}
elsif (-f _)
{
removeFile( $path );
}
}
closedir(DIR);
rmdir( $dirName );
}
#
# Remove a file, asking for confirmation, etc, as
# necessary
sub removeFile( )
{
my ( $fileName ) = @_;
my $reply;
# If its read only, and we're not forcing, and interactive prompt for deletion
#
if ( ( ! -w $fileName ) && ( !$opt_f ) && ( $opt_i ))
{
print "$fileName: Read-only ? ";
$reply = <STDIN>;
if ( $reply =~ /^[Nn]/ )
{
return;
}
}
elsif ( $opt_i )
{
print "$fileName: ? ";
$reply = <STDIN>;
if ( $reply =~ /^[Nn]/ )
{
return;
}
}
# If we are forcing the delete first change the files mode to allow writes.
if ( $opt_f )
{
my ( $mode ) = "0777";
chmod $mode, $fileName;
}
# Overwrite the file with rubbish before deleting.
if ( $opt_P )
{
overWriteFile( $fileName );
}
# Delete the file.
unlink( $fileName );
}
#
# Overwrite the file specified, first with x00, the xFF, then x00
sub overWriteFile( )
{
my ( $fileName ) = @_;
# Info returned from stat
my ( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size );
# Text we print to the file to overwrite its contents
my ( $text, $FILEHANDLE, $ff );
# We only want the size
( $dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size ) = stat $fileName;
$ff = "\0xFF";
# Change mode if the file is readonly.
if ( !-w $fileName )
{
my ( $mode ) = "0777";
chmod $mode, $fileName;
}
## First pass at overwrite
if ( open (FILEHANDLE, ">$fileName" ) )
{
$text = $ff x $size;
print FILEHANDLE $text;
close ( FILEHANDLE );
}
## Second pass at overwrite
if ( open (FILEHANDLE, ">$fileName" ) )
{
$text = "\0" x $size;
print $text;
print FILEHANDLE $text;
close ( FILEHANDLE );
}
## Third pass at overwrite
if ( open (FILEHANDLE, ">$fileName" ) )
{
$text = $ff x $size;
print FILEHANDLE $text;
close ( FILEHANDLE );
}
}
#
# Read the options from the command line.
sub getOptions()
{
# Process options, if any.
# Make sure defaults are set before returning!
return unless @ARGV > 0;
if ( !getopts( 'ifPrR' ) )
{
showUsage();
}
}
#
# Show the useage
sub showUsage()
{
print << "E-O-F";
Usage: rm [-fiPrR] file ...
The options are as follows:
-f Attempt to remove the files without prompting for confirmation, re-
gardless of the file's permissions. If the file does not exist, do
not display a diagnostic message or modify the exit status to re-
flect an error. The -f option overrides any previous -i options.
-i Request confirmation before attempting to remove each file, regard-
less of the file's permissions, or whether or not the standard in-
put device is a terminal. The -i option overrides any previous -f
options.
-P Overwrite regular files before deleting them. Files are overwrit-
ten three times, first with the byte pattern 0xff, then 0x00, and
then 0xff again, before they are deleted.
-R Attempt to remove the file hierarchy rooted in each file argument.
The -R option implies the -d option. If the -i option is speci-
fied, the user is prompted for confirmation before each directory's
contents are processed (as well as before the attempt is made to
remove the directory). If the user does not respond affirmatively,
the file hierarchy rooted in that directory is skipped.
The rm utility removes symbolic links, not the files referenced by the
links.
It is an error to attempt to remove the files ``.'' or ``..''.
E-O-F
exit;
}