line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package File::System::Real; |
2
|
|
|
|
|
|
|
|
3
|
7
|
|
|
7
|
|
38
|
use strict; |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
286
|
|
4
|
7
|
|
|
7
|
|
39
|
use warnings; |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
355
|
|
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
our $VERSION = '1.15'; |
7
|
|
|
|
|
|
|
|
8
|
7
|
|
|
7
|
|
35
|
use Carp; |
|
7
|
|
|
|
|
10
|
|
|
7
|
|
|
|
|
533
|
|
9
|
7
|
|
|
7
|
|
7434
|
use File::Copy (); |
|
7
|
|
|
|
|
31413
|
|
|
7
|
|
|
|
|
177
|
|
10
|
7
|
|
|
7
|
|
10944
|
use File::Copy::Recursive; |
|
7
|
|
|
|
|
28107
|
|
|
7
|
|
|
|
|
410
|
|
11
|
7
|
|
|
7
|
|
68
|
use File::Glob (); |
|
7
|
|
|
|
|
16
|
|
|
7
|
|
|
|
|
117
|
|
12
|
7
|
|
|
7
|
|
38
|
use File::Path (); |
|
7
|
|
|
|
|
13
|
|
|
7
|
|
|
|
|
119
|
|
13
|
7
|
|
|
7
|
|
38
|
use File::Spec; |
|
7
|
|
|
|
|
59
|
|
|
7
|
|
|
|
|
388
|
|
14
|
7
|
|
|
7
|
|
7395
|
use FileHandle; |
|
7
|
|
|
|
|
62210
|
|
|
7
|
|
|
|
|
79
|
|
15
|
|
|
|
|
|
|
|
16
|
7
|
|
|
7
|
|
3927
|
use base 'File::System::Object'; |
|
7
|
|
|
|
|
77
|
|
|
7
|
|
|
|
|
19243
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
=head1 NAME |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
File::System::Real - A file system module based on the real file system |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
=head1 SYNOPSIS |
23
|
|
|
|
|
|
|
|
24
|
|
|
|
|
|
|
use File::System; |
25
|
|
|
|
|
|
|
$root = File::System->new('Real', root => '/usr/local'); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
=head1 DESCRIPTION |
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
This is the most basic file system implementation. It is purely implemented within terms of a real file system. |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
=head1 OPTIONS |
32
|
|
|
|
|
|
|
|
33
|
|
|
|
|
|
|
This file system module accepts only a single object, C. If not given, the current working directory is assumed for the value C. All files returned by the file system will be rooted at the given (or assumed) point. |
34
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
=cut |
36
|
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
sub new { |
38
|
13
|
|
|
13
|
0
|
137
|
my $class = shift; |
39
|
13
|
|
|
|
|
56
|
my %args = @_; |
40
|
|
|
|
|
|
|
|
41
|
13
|
|
50
|
|
|
57
|
$args{root} ||= '.'; |
42
|
13
|
|
|
|
|
594
|
$args{root} = File::Spec->rel2abs($args{root}); |
43
|
13
|
|
|
|
|
157
|
$args{root} = $class->normalize_path($args{root}); |
44
|
13
|
|
|
|
|
70
|
my $root = File::Spec->canonpath($args{root}); |
45
|
|
|
|
|
|
|
|
46
|
13
|
50
|
|
|
|
561
|
-e $root or croak "Sorry, root $root does not exist!"; |
47
|
13
|
50
|
|
|
|
336
|
-d $root or croak "Sorry, root $root is not a directory!"; |
48
|
|
|
|
|
|
|
|
49
|
13
|
|
|
|
|
124
|
return bless { |
50
|
|
|
|
|
|
|
fs_root => $root, |
51
|
|
|
|
|
|
|
path => '/', |
52
|
|
|
|
|
|
|
fullpath => $root, |
53
|
|
|
|
|
|
|
}, $class; |
54
|
|
|
|
|
|
|
} |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
sub is_valid { |
57
|
983
|
|
|
983
|
1
|
2703
|
my $self = shift; |
58
|
983
|
|
|
|
|
29201
|
return -e $self->{fullpath}; |
59
|
|
|
|
|
|
|
} |
60
|
|
|
|
|
|
|
|
61
|
|
|
|
|
|
|
sub root { |
62
|
20
|
|
|
20
|
1
|
41
|
my $self = shift; |
63
|
|
|
|
|
|
|
|
64
|
20
|
|
|
|
|
579
|
return bless { |
65
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
66
|
|
|
|
|
|
|
path => '/', |
67
|
|
|
|
|
|
|
fullpath => $self->{fs_root}, |
68
|
|
|
|
|
|
|
}, ref $self; |
69
|
|
|
|
|
|
|
} |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
sub exists { |
72
|
865
|
|
|
865
|
1
|
17238
|
my $self = shift; |
73
|
865
|
|
66
|
|
|
2134
|
my $path = shift || $self->path; |
74
|
|
|
|
|
|
|
|
75
|
865
|
|
|
|
|
3016
|
return -e $self->normalize_real_path($path); |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
|
78
|
|
|
|
|
|
|
sub lookup { |
79
|
28236
|
|
|
28236
|
1
|
95861
|
my $self = shift; |
80
|
28236
|
|
|
|
|
49746
|
my $path = shift; |
81
|
|
|
|
|
|
|
|
82
|
28236
|
|
|
|
|
81583
|
my $abspath = $self->normalize_path($path); |
83
|
28236
|
|
|
|
|
85256
|
my $fullpath = $self->normalize_real_path($path); |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
return undef |
86
|
28236
|
100
|
|
|
|
846246
|
unless -e $fullpath; |
87
|
|
|
|
|
|
|
|
88
|
28067
|
|
|
|
|
252006
|
return bless { |
89
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
90
|
|
|
|
|
|
|
path => $abspath, |
91
|
|
|
|
|
|
|
fullpath => $fullpath, |
92
|
|
|
|
|
|
|
}, ref $self; |
93
|
|
|
|
|
|
|
} |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
sub glob { |
96
|
320
|
|
|
320
|
1
|
433
|
my $self = shift; |
97
|
320
|
|
|
|
|
396
|
my $glob = shift; |
98
|
|
|
|
|
|
|
|
99
|
320
|
|
|
|
|
850
|
my $absglob = $self->normalize_path($glob); |
100
|
|
|
|
|
|
|
|
101
|
320
|
|
|
|
|
1113
|
my $fullglob = $self->normalize_real_path($absglob); |
102
|
|
|
|
|
|
|
|
103
|
228
|
|
|
|
|
7673
|
return sort map { |
104
|
320
|
|
|
|
|
29779
|
s/^$self->{fs_root}//; |
105
|
228
|
|
|
|
|
1071
|
bless { |
106
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
107
|
|
|
|
|
|
|
path => $self->normalize_path($_), |
108
|
|
|
|
|
|
|
fullpath => $self->normalize_real_path($_), |
109
|
|
|
|
|
|
|
}, ref $self |
110
|
|
|
|
|
|
|
} File::Glob::bsd_glob($fullglob); |
111
|
|
|
|
|
|
|
} |
112
|
|
|
|
|
|
|
|
113
|
|
|
|
|
|
|
sub properties { |
114
|
2569
|
|
|
2569
|
1
|
190324
|
my $self = shift; |
115
|
|
|
|
|
|
|
|
116
|
2569
|
|
|
|
|
28655
|
return qw/ |
117
|
|
|
|
|
|
|
basename |
118
|
|
|
|
|
|
|
dirname |
119
|
|
|
|
|
|
|
path |
120
|
|
|
|
|
|
|
object_type |
121
|
|
|
|
|
|
|
dev |
122
|
|
|
|
|
|
|
ino |
123
|
|
|
|
|
|
|
mode |
124
|
|
|
|
|
|
|
nlink |
125
|
|
|
|
|
|
|
uid |
126
|
|
|
|
|
|
|
gid |
127
|
|
|
|
|
|
|
rdev |
128
|
|
|
|
|
|
|
size |
129
|
|
|
|
|
|
|
atime |
130
|
|
|
|
|
|
|
mtime |
131
|
|
|
|
|
|
|
ctime |
132
|
|
|
|
|
|
|
blksize |
133
|
|
|
|
|
|
|
blocks |
134
|
|
|
|
|
|
|
/; |
135
|
|
|
|
|
|
|
} |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub settable_properties { |
138
|
364
|
|
|
364
|
1
|
2021
|
my $self = shift; |
139
|
|
|
|
|
|
|
|
140
|
364
|
|
|
|
|
2482
|
return qw/ |
141
|
|
|
|
|
|
|
mode |
142
|
|
|
|
|
|
|
uid |
143
|
|
|
|
|
|
|
gid |
144
|
|
|
|
|
|
|
atime |
145
|
|
|
|
|
|
|
mtime |
146
|
|
|
|
|
|
|
/; |
147
|
|
|
|
|
|
|
} |
148
|
|
|
|
|
|
|
|
149
|
|
|
|
|
|
|
sub _stat { |
150
|
1690
|
|
|
1690
|
|
2196
|
my $self = shift; |
151
|
|
|
|
|
|
|
|
152
|
1690
|
|
|
|
|
56432
|
my @stat = stat $self->{fullpath}; |
153
|
1690
|
|
|
|
|
31030
|
return \@stat; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
sub get_property { |
157
|
92490
|
|
|
92490
|
1
|
143648
|
my $self = shift; |
158
|
92490
|
|
|
|
|
155101
|
local $_ = shift; |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
SWITCH: { |
161
|
92490
|
100
|
|
|
|
127588
|
/^basename$/ && do { |
|
92490
|
|
|
|
|
222724
|
|
162
|
2281
|
|
|
|
|
9326
|
return $self->basename_of_path($self->{path}); |
163
|
|
|
|
|
|
|
}; |
164
|
90209
|
100
|
|
|
|
221216
|
/^dirname$/ && do { |
165
|
2647
|
|
|
|
|
9284
|
return $self->dirname_of_path($self->{path}); |
166
|
|
|
|
|
|
|
}; |
167
|
87562
|
100
|
|
|
|
205921
|
/^path$/ && do { |
168
|
23201
|
|
|
|
|
175071
|
return $self->{path}; |
169
|
|
|
|
|
|
|
}; |
170
|
64361
|
100
|
|
|
|
211908
|
/^object_type$/ && do { |
171
|
62671
|
|
|
|
|
86414
|
my $result = ''; |
172
|
62671
|
100
|
|
|
|
1752761
|
$result .= 'd' if -d $self->{fullpath}; |
173
|
62671
|
100
|
|
|
|
1409442
|
$result .= 'f' if -f $self->{fullpath}; |
174
|
62671
|
|
|
|
|
524498
|
return $result; |
175
|
|
|
|
|
|
|
}; |
176
|
1690
|
50
|
|
|
|
3517
|
/^dev$/ && do { |
177
|
0
|
|
|
|
|
0
|
return $self->_stat->[0]; |
178
|
|
|
|
|
|
|
}; |
179
|
1690
|
50
|
|
|
|
3363
|
/^ino$/ && do { |
180
|
0
|
|
|
|
|
0
|
return $self->_stat->[1]; |
181
|
|
|
|
|
|
|
}; |
182
|
1690
|
100
|
|
|
|
4135
|
/^mode$/ && do { |
183
|
338
|
|
|
|
|
1186
|
return $self->_stat->[2]; |
184
|
|
|
|
|
|
|
}; |
185
|
1352
|
50
|
|
|
|
2793
|
/^nlink$/ && do { |
186
|
0
|
|
|
|
|
0
|
return $self->_stat->[3]; |
187
|
|
|
|
|
|
|
}; |
188
|
1352
|
50
|
|
|
|
17347
|
/^uid$/ && do { |
189
|
0
|
|
|
|
|
0
|
return $self->_stat->[4]; |
190
|
|
|
|
|
|
|
}; |
191
|
1352
|
50
|
|
|
|
3340
|
/^gid$/ && do { |
192
|
0
|
|
|
|
|
0
|
return $self->_stat->[5]; |
193
|
|
|
|
|
|
|
}; |
194
|
1352
|
50
|
|
|
|
2943
|
/^rdev$/ && do { |
195
|
0
|
|
|
|
|
0
|
return $self->_stat->[6]; |
196
|
|
|
|
|
|
|
}; |
197
|
1352
|
50
|
|
|
|
3181
|
/^size$/ && do { |
198
|
0
|
|
|
|
|
0
|
return $self->_stat->[7]; |
199
|
|
|
|
|
|
|
}; |
200
|
1352
|
100
|
|
|
|
3998
|
/^atime$/ && do { |
201
|
676
|
|
|
|
|
2395
|
return $self->_stat->[8]; |
202
|
|
|
|
|
|
|
}; |
203
|
676
|
50
|
|
|
|
2938
|
/^mtime$/ && do { |
204
|
676
|
|
|
|
|
2007
|
return $self->_stat->[9]; |
205
|
|
|
|
|
|
|
}; |
206
|
0
|
0
|
|
|
|
0
|
/^ctime$/ && do { |
207
|
0
|
|
|
|
|
0
|
return $self->_stat->[10]; |
208
|
|
|
|
|
|
|
}; |
209
|
0
|
0
|
|
|
|
0
|
/^blksize$/ && do { |
210
|
0
|
|
|
|
|
0
|
return $self->_stat->[11]; |
211
|
|
|
|
|
|
|
}; |
212
|
0
|
0
|
|
|
|
0
|
/^blocks$/ && do { |
213
|
0
|
|
|
|
|
0
|
return $self->_stat->[12]; |
214
|
|
|
|
|
|
|
}; |
215
|
0
|
|
|
|
|
0
|
DEFAULT: { |
216
|
0
|
|
|
|
|
0
|
return undef; |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
} |
219
|
|
|
|
|
|
|
} |
220
|
|
|
|
|
|
|
|
221
|
|
|
|
|
|
|
sub set_property { |
222
|
1014
|
|
|
1014
|
1
|
5265
|
my $self = shift; |
223
|
1014
|
|
|
|
|
1745
|
local $_ = shift; |
224
|
1014
|
|
|
|
|
1364
|
my $value = shift; |
225
|
|
|
|
|
|
|
|
226
|
|
|
|
|
|
|
SWITCH: { |
227
|
1014
|
100
|
|
|
|
1421
|
/^mode$/ && do { |
|
1014
|
|
|
|
|
4044
|
|
228
|
338
|
|
|
|
|
20881
|
chmod $value, $self->{fullpath}; |
229
|
338
|
|
|
|
|
1955
|
last SWITCH; |
230
|
|
|
|
|
|
|
}; |
231
|
676
|
50
|
|
|
|
1887
|
/^uid$/ && do { |
232
|
0
|
|
|
|
|
0
|
chown $value, $self->get_property('gid'), $self->{fullpath}; |
233
|
0
|
|
|
|
|
0
|
last SWITCH; |
234
|
|
|
|
|
|
|
}; |
235
|
676
|
50
|
|
|
|
1500
|
/^gid$/ && do { |
236
|
0
|
|
|
|
|
0
|
chown $self->get_property('uid'), $value, $self->{fullpath}; |
237
|
0
|
|
|
|
|
0
|
last SWITCH; |
238
|
|
|
|
|
|
|
}; |
239
|
676
|
100
|
|
|
|
2056
|
/^atime$/ && do { |
240
|
338
|
|
|
|
|
901
|
utime $value, $self->get_property('mtime'), $self->{fullpath}; |
241
|
338
|
|
|
|
|
1741
|
last SWITCH; |
242
|
|
|
|
|
|
|
}; |
243
|
338
|
50
|
|
|
|
1519
|
/^mtime$/ && do { |
244
|
338
|
|
|
|
|
910
|
utime $self->get_property('atime'), $value, $self->{fullpath}; |
245
|
338
|
|
|
|
|
1562
|
last SWITCH; |
246
|
|
|
|
|
|
|
}; |
247
|
0
|
|
|
|
|
0
|
DEFAULT: { |
248
|
0
|
|
|
|
|
0
|
croak "Cannot set unknown property '$_'"; |
249
|
|
|
|
|
|
|
} |
250
|
|
|
|
|
|
|
} |
251
|
|
|
|
|
|
|
} |
252
|
|
|
|
|
|
|
|
253
|
|
|
|
|
|
|
sub is_creatable { |
254
|
10
|
|
|
10
|
1
|
17
|
my $self = shift; |
255
|
10
|
|
|
|
|
18
|
my $path = shift; |
256
|
10
|
|
|
|
|
15
|
my $type = shift; |
257
|
|
|
|
|
|
|
|
258
|
10
|
50
|
|
|
|
26
|
defined $type |
259
|
|
|
|
|
|
|
or croak "No type argument given."; |
260
|
|
|
|
|
|
|
|
261
|
10
|
|
33
|
|
|
96
|
return ($type eq 'f' || $type eq 'd') && !$self->exists($path); |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
sub create { |
265
|
690
|
|
|
690
|
1
|
46389
|
my $self = shift; |
266
|
690
|
|
|
|
|
1024
|
my $path = shift; |
267
|
690
|
|
|
|
|
1005
|
my $type = shift; |
268
|
|
|
|
|
|
|
|
269
|
690
|
50
|
|
|
|
2063
|
defined $type |
270
|
|
|
|
|
|
|
or croak "Missing required argument 'type'."; |
271
|
|
|
|
|
|
|
|
272
|
690
|
100
|
|
|
|
2766
|
if ($type eq 'f') { |
|
|
50
|
|
|
|
|
|
273
|
230
|
|
|
|
|
558
|
my $fulldir = $self->dirname_of_path($self->normalize_real_path($path)); |
274
|
|
|
|
|
|
|
|
275
|
230
|
|
|
|
|
14036
|
File::Path::mkpath($fulldir, 0); |
276
|
|
|
|
|
|
|
|
277
|
230
|
|
|
|
|
890
|
my $abspath = $self->normalize_path($path); |
278
|
230
|
|
|
|
|
565
|
my $fullpath = $self->normalize_real_path($path); |
279
|
|
|
|
|
|
|
|
280
|
230
|
50
|
|
|
|
1582
|
my $fh = FileHandle->new(">$fullpath") |
281
|
|
|
|
|
|
|
or croak "Cannot create file $abspath: $!"; |
282
|
230
|
|
|
|
|
65493
|
close $fh; |
283
|
|
|
|
|
|
|
|
284
|
230
|
|
|
|
|
8937
|
return bless { |
285
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
286
|
|
|
|
|
|
|
path => $abspath, |
287
|
|
|
|
|
|
|
fullpath => $fullpath, |
288
|
|
|
|
|
|
|
}, ref $self; |
289
|
|
|
|
|
|
|
} elsif ($type eq 'd') { |
290
|
460
|
|
|
|
|
1527
|
my $abspath = $self->normalize_path($path); |
291
|
460
|
|
|
|
|
1995
|
my $fullpath = $self->normalize_real_path($path); |
292
|
|
|
|
|
|
|
|
293
|
460
|
|
|
|
|
130772
|
File::Path::mkpath($fullpath, 0); |
294
|
|
|
|
|
|
|
|
295
|
460
|
50
|
|
|
|
14503
|
-d $fullpath |
296
|
|
|
|
|
|
|
or croak "Failed to create directory '$abspath'"; |
297
|
|
|
|
|
|
|
|
298
|
460
|
|
|
|
|
6090
|
return bless { |
299
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
300
|
|
|
|
|
|
|
path => $abspath, |
301
|
|
|
|
|
|
|
fullpath => $fullpath, |
302
|
|
|
|
|
|
|
}, ref $self; |
303
|
|
|
|
|
|
|
} else { |
304
|
0
|
|
|
|
|
0
|
return undef; |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub rename { |
309
|
496
|
|
|
496
|
1
|
885
|
my $self = shift; |
310
|
496
|
|
|
|
|
1456
|
my $name = shift; |
311
|
|
|
|
|
|
|
|
312
|
496
|
50
|
|
|
|
1552
|
croak "The 'name' argument must be a plan name, not a path. However, the given value ($name) contains a slash." |
313
|
|
|
|
|
|
|
if $name =~ m#/#; |
314
|
|
|
|
|
|
|
|
315
|
496
|
|
|
|
|
1575
|
my $abspath = $self->normalize_path($self->dirname.'/'.$name); |
316
|
496
|
|
|
|
|
1726
|
my $fullpath = $self->normalize_real_path($self->dirname.'/'.$name); |
317
|
|
|
|
|
|
|
|
318
|
496
|
|
|
|
|
47660
|
rename $self->{fullpath}, $fullpath; |
319
|
|
|
|
|
|
|
|
320
|
496
|
|
|
|
|
1424
|
$self->{path} = $abspath; |
321
|
496
|
|
|
|
|
906
|
$self->{fullpath} = $fullpath; |
322
|
|
|
|
|
|
|
|
323
|
496
|
|
|
|
|
1615
|
return $self; |
324
|
|
|
|
|
|
|
} |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
sub move { |
327
|
496
|
|
|
496
|
1
|
1998
|
my $self = shift; |
328
|
496
|
|
|
|
|
738
|
my $to = shift; |
329
|
496
|
|
100
|
|
|
2009
|
my $force = shift || 0; |
330
|
|
|
|
|
|
|
|
331
|
496
|
50
|
|
|
|
2327
|
UNIVERSAL::isa($to, ref $self) |
332
|
|
|
|
|
|
|
or croak "Move failed; the '$to' object is not a '",ref $self,"'"; |
333
|
|
|
|
|
|
|
|
334
|
496
|
50
|
|
|
|
1869
|
$to->{fs_root} eq $self->{fs_root} |
335
|
|
|
|
|
|
|
or croak "Move failed; the '$to' object belongs to a different root."; |
336
|
|
|
|
|
|
|
|
337
|
496
|
50
|
|
|
|
1710
|
$to->is_valid |
338
|
|
|
|
|
|
|
or croak "Move failed; the '$to' object is not valid."; |
339
|
|
|
|
|
|
|
|
340
|
496
|
50
|
|
|
|
2086
|
$to->is_container |
341
|
|
|
|
|
|
|
or croak "Move failed; the '$to' object is not a directory."; |
342
|
|
|
|
|
|
|
|
343
|
496
|
50
|
|
|
|
2467
|
defined $to->child($self->basename) |
344
|
|
|
|
|
|
|
and croak "Move failed; the '$to/",$self->basename,"' object already exists."; |
345
|
|
|
|
|
|
|
|
346
|
496
|
100
|
|
|
|
2399
|
if ($self->is_container) { |
347
|
62
|
50
|
|
|
|
225
|
if ($force) { |
348
|
62
|
|
|
|
|
224
|
$to->create($self->basename, 'd'); |
349
|
62
|
50
|
|
|
|
462
|
File::Copy::Recursive::dircopy($self->{fullpath}, $to->{fullpath}.'/'.$self->basename) |
350
|
|
|
|
|
|
|
or croak "Move failed; dircopy failure to '$to'"; |
351
|
62
|
|
|
|
|
144764
|
File::Path::rmtree($self->{fullpath}); |
352
|
|
|
|
|
|
|
} else { |
353
|
0
|
|
|
|
|
0
|
croak "Move failed; cannot move a directory unless the 'force' argument is true."; |
354
|
|
|
|
|
|
|
} |
355
|
|
|
|
|
|
|
} else { |
356
|
434
|
|
|
|
|
2722
|
File::Copy::move($self->{fullpath}, $to->{fullpath}); |
357
|
|
|
|
|
|
|
} |
358
|
|
|
|
|
|
|
|
359
|
496
|
|
|
|
|
120362
|
my $name = $self->basename; |
360
|
|
|
|
|
|
|
|
361
|
496
|
|
|
|
|
4940
|
$self->{path} = $self->normalize_path($to->path.'/'.$name); |
362
|
496
|
|
|
|
|
1690
|
$self->{fullpath} = $self->normalize_real_path($to->path.'/'.$name); |
363
|
|
|
|
|
|
|
|
364
|
496
|
|
|
|
|
1697
|
return $self; |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub copy { |
368
|
248
|
|
|
248
|
1
|
389
|
my $self = shift; |
369
|
248
|
|
|
|
|
427
|
my $to = shift; |
370
|
248
|
|
100
|
|
|
1751
|
my $force = shift || 0; |
371
|
|
|
|
|
|
|
|
372
|
248
|
50
|
|
|
|
1122
|
UNIVERSAL::isa($to, ref $self) |
373
|
|
|
|
|
|
|
or croak "Copy failed; the '$to' object is not a '",ref $self,"'"; |
374
|
|
|
|
|
|
|
|
375
|
248
|
50
|
|
|
|
898
|
$to->{fs_root} eq $self->{fs_root} |
376
|
|
|
|
|
|
|
or croak "Copy failed; the '$to' object belongs to a different root."; |
377
|
|
|
|
|
|
|
|
378
|
248
|
50
|
|
|
|
734
|
$to->is_valid |
379
|
|
|
|
|
|
|
or croak "Copy failed; the '$to' object is not valid."; |
380
|
|
|
|
|
|
|
|
381
|
248
|
50
|
|
|
|
6115
|
$to->is_container |
382
|
|
|
|
|
|
|
or croak "Copy failed; the '$to' object is not a directory."; |
383
|
|
|
|
|
|
|
|
384
|
248
|
50
|
|
|
|
1035
|
defined $to->child($self->basename, 'd') |
385
|
|
|
|
|
|
|
and croak "Copy failed; the '$to/",$self->basename,"' object already exists."; |
386
|
|
|
|
|
|
|
|
387
|
248
|
100
|
|
|
|
1028
|
if ($self->is_container) { |
388
|
31
|
50
|
|
|
|
86
|
if ($force) { |
389
|
31
|
|
|
|
|
110
|
$to->create($self->basename, 'd'); |
390
|
31
|
50
|
|
|
|
377
|
File::Copy::Recursive::dircopy($self->{fullpath}, $to->{fullpath}.'/'.$self->basename) |
391
|
|
|
|
|
|
|
or croak "Copy failed; dircopy failure to '$to'"; |
392
|
|
|
|
|
|
|
} else { |
393
|
0
|
|
|
|
|
0
|
croak "Copy failed; cannot copy a directory unless the 'force' argument is true."; |
394
|
|
|
|
|
|
|
} |
395
|
|
|
|
|
|
|
} else { |
396
|
217
|
|
|
|
|
1218
|
File::Copy::copy($self->{fullpath}, $to->{fullpath}); |
397
|
|
|
|
|
|
|
} |
398
|
|
|
|
|
|
|
|
399
|
248
|
|
|
|
|
444570
|
return bless { |
400
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
401
|
|
|
|
|
|
|
path => $self->normalize_path($to->path.'/'.$self->basename), |
402
|
|
|
|
|
|
|
fullpath => $self->normalize_real_path($to->path.'/'.$self->basename), |
403
|
|
|
|
|
|
|
}, ref $self; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
sub remove { |
407
|
496
|
|
|
496
|
1
|
183391
|
my $self = shift; |
408
|
496
|
|
|
|
|
786
|
my $force = shift; |
409
|
|
|
|
|
|
|
|
410
|
496
|
100
|
66
|
|
|
32250
|
if (-d $self->{fullpath} && $force) { |
|
|
50
|
33
|
|
|
|
|
|
|
50
|
|
|
|
|
|
411
|
279
|
|
|
|
|
153762
|
File::Path::rmtree($self->{fullpath}); |
412
|
|
|
|
|
|
|
} elsif (-d $self->{fullpath} && $self->has_children) { |
413
|
0
|
|
|
|
|
0
|
croak "Cannot delete directory with children unless force is true."; |
414
|
|
|
|
|
|
|
} elsif (-d $self->{fullpath}) { |
415
|
0
|
|
|
|
|
0
|
rmdir $self->{fullpath}; |
416
|
|
|
|
|
|
|
} else { |
417
|
217
|
|
|
|
|
35591
|
unlink $self->{fullpath}; |
418
|
|
|
|
|
|
|
} |
419
|
|
|
|
|
|
|
} |
420
|
|
|
|
|
|
|
|
421
|
|
|
|
|
|
|
sub is_readable { |
422
|
224
|
|
|
224
|
1
|
1268
|
my $self = shift; |
423
|
224
|
|
|
|
|
770
|
return $self->has_content; |
424
|
|
|
|
|
|
|
} |
425
|
|
|
|
|
|
|
|
426
|
|
|
|
|
|
|
sub is_seekable { |
427
|
224
|
|
|
224
|
1
|
1269
|
my $self = shift; |
428
|
|
|
|
|
|
|
# TODO This is naive. Seekability is a little less available than this |
429
|
|
|
|
|
|
|
# would indicate. |
430
|
224
|
|
|
|
|
793
|
return $self->has_content; |
431
|
|
|
|
|
|
|
} |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
sub is_writable { |
434
|
224
|
|
|
224
|
1
|
1820
|
my $self = shift; |
435
|
224
|
|
|
|
|
1039
|
return $self->has_content; |
436
|
|
|
|
|
|
|
} |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
sub is_appendable { |
439
|
224
|
|
|
224
|
1
|
1104
|
my $self = shift; |
440
|
224
|
|
|
|
|
771
|
return $self->has_content; |
441
|
|
|
|
|
|
|
} |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
sub open { |
444
|
1568
|
|
|
1568
|
1
|
4389
|
my $self = shift; |
445
|
1568
|
|
|
|
|
2009
|
my $access = shift; |
446
|
1568
|
0
|
|
|
|
8895
|
return FileHandle->new($self->{fullpath}, $access) |
447
|
|
|
|
|
|
|
or croak "Cannot open $self with access mode '$access': $!"; |
448
|
|
|
|
|
|
|
} |
449
|
|
|
|
|
|
|
|
450
|
|
|
|
|
|
|
sub content { |
451
|
896
|
|
|
896
|
1
|
4386
|
my $self = shift; |
452
|
|
|
|
|
|
|
|
453
|
896
|
|
|
|
|
1873
|
my $fh = $self->open("r"); |
454
|
896
|
|
|
|
|
102611
|
my @lines = <$fh>; |
455
|
896
|
|
|
|
|
10400
|
close $fh; |
456
|
|
|
|
|
|
|
|
457
|
896
|
100
|
|
|
|
7763
|
return wantarray ? @lines : join '', @lines; |
458
|
|
|
|
|
|
|
} |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
sub has_children { |
461
|
119
|
|
|
119
|
1
|
947
|
my $self = shift; |
462
|
|
|
|
|
|
|
|
463
|
119
|
50
|
|
|
|
4646
|
opendir DH, $self->{fullpath} |
464
|
|
|
|
|
|
|
or croak "Cannot open directory $self for listing: $!"; |
465
|
119
|
|
|
|
|
2529
|
my @dirs = grep !/^\.\.?$/, readdir DH; |
466
|
119
|
|
|
|
|
1683
|
closedir DH; |
467
|
|
|
|
|
|
|
|
468
|
119
|
100
|
|
|
|
1390
|
return @dirs ? 1 : ''; |
469
|
|
|
|
|
|
|
} |
470
|
|
|
|
|
|
|
|
471
|
|
|
|
|
|
|
sub children_paths { |
472
|
4367
|
|
|
4367
|
1
|
22754
|
my $self = shift; |
473
|
|
|
|
|
|
|
|
474
|
4367
|
50
|
|
|
|
10333481
|
opendir DH, $self->{fullpath} |
475
|
|
|
|
|
|
|
or croak "Cannot open directory $self for listing: $!"; |
476
|
4367
|
|
|
|
|
1381109
|
my @paths = map { s/^$self->{fs_root}//; $_ } readdir DH; |
|
25938
|
|
|
|
|
105132
|
|
|
25938
|
|
|
|
|
78747
|
|
477
|
4367
|
|
|
|
|
344479
|
closedir DH; |
478
|
|
|
|
|
|
|
|
479
|
4367
|
|
|
|
|
41236
|
return @paths; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
|
482
|
|
|
|
|
|
|
sub children { |
483
|
746
|
|
|
746
|
1
|
1296
|
my $self = shift; |
484
|
|
|
|
|
|
|
|
485
|
746
|
50
|
|
|
|
36233
|
opendir DH, $self->{fullpath} |
486
|
|
|
|
|
|
|
or croak "Cannot open directory $self for listing: $!"; |
487
|
|
|
|
|
|
|
my @children = map { |
488
|
746
|
100
|
|
|
|
21829
|
if (/^\.\.?$/) { |
|
2482
|
|
|
|
|
7307
|
|
489
|
|
|
|
|
|
|
() |
490
|
1492
|
|
|
|
|
2688
|
} else { |
491
|
990
|
|
|
|
|
3615
|
bless { |
492
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
493
|
|
|
|
|
|
|
path => $self->normalize_path($_), |
494
|
|
|
|
|
|
|
fullpath => $self->normalize_real_path($_), |
495
|
|
|
|
|
|
|
}, ref $self; |
496
|
|
|
|
|
|
|
} |
497
|
|
|
|
|
|
|
} readdir DH; |
498
|
746
|
|
|
|
|
9676
|
closedir DH; |
499
|
|
|
|
|
|
|
|
500
|
746
|
|
|
|
|
5527
|
return @children; |
501
|
|
|
|
|
|
|
} |
502
|
|
|
|
|
|
|
|
503
|
|
|
|
|
|
|
sub child { |
504
|
788
|
|
|
788
|
1
|
1655
|
my $self = shift; |
505
|
788
|
|
|
|
|
2946
|
my $name = shift; |
506
|
|
|
|
|
|
|
|
507
|
788
|
50
|
|
|
|
2330
|
croak "Name given, '$name', is a path rather than a name (i.e., it contains a slash)." if $name =~ m#/#; |
508
|
|
|
|
|
|
|
|
509
|
788
|
|
|
|
|
2637
|
my $abspath = $self->normalize_path($name); |
510
|
788
|
|
|
|
|
2821
|
my $fullpath = $self->normalize_real_path($name); |
511
|
|
|
|
|
|
|
|
512
|
788
|
100
|
|
|
|
25460
|
if (-e $fullpath) { |
513
|
42
|
|
|
|
|
910
|
return bless { |
514
|
|
|
|
|
|
|
fs_root => $self->{fs_root}, |
515
|
|
|
|
|
|
|
path => $abspath, |
516
|
|
|
|
|
|
|
fullpath => $fullpath, |
517
|
|
|
|
|
|
|
}, ref $self; |
518
|
|
|
|
|
|
|
} else { |
519
|
746
|
|
|
|
|
2939
|
return undef; |
520
|
|
|
|
|
|
|
} |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
# =item $real_path = $obj->normalize_real_path($messy_path) |
524
|
|
|
|
|
|
|
# |
525
|
|
|
|
|
|
|
# Like C, except that it returns a real absolute path. |
526
|
|
|
|
|
|
|
# |
527
|
|
|
|
|
|
|
# =cut |
528
|
|
|
|
|
|
|
|
529
|
|
|
|
|
|
|
sub normalize_real_path { |
530
|
33609
|
|
|
33609
|
0
|
51430
|
my $self = shift; |
531
|
33609
|
|
|
|
|
48113
|
my $path = shift; |
532
|
|
|
|
|
|
|
|
533
|
33609
|
|
|
|
|
90260
|
my $abspath = $self->normalize_path($path); |
534
|
33609
|
|
|
|
|
476755
|
my $fullpath = File::Spec->canonpath( |
535
|
|
|
|
|
|
|
File::Spec->catfile($self->{fs_root}, $abspath) |
536
|
|
|
|
|
|
|
); |
537
|
|
|
|
|
|
|
|
538
|
33609
|
|
|
|
|
155368
|
return $fullpath; |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
|
541
|
|
|
|
|
|
|
=head1 SEE ALSO |
542
|
|
|
|
|
|
|
|
543
|
|
|
|
|
|
|
L, L |
544
|
|
|
|
|
|
|
|
545
|
|
|
|
|
|
|
=head1 AUTHOR |
546
|
|
|
|
|
|
|
|
547
|
|
|
|
|
|
|
Andrew Sterling Hanenkamp, Ehanenkamp@users.sourceforge.netE |
548
|
|
|
|
|
|
|
|
549
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
Copyright 2005 Andrew Sterling Hanenkamp. All Rights Reserved. |
552
|
|
|
|
|
|
|
|
553
|
|
|
|
|
|
|
This software is distributed and licensed under the same terms as Perl itself. |
554
|
|
|
|
|
|
|
|
555
|
|
|
|
|
|
|
=cut |
556
|
|
|
|
|
|
|
|
557
|
|
|
|
|
|
|
1 |