line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package File::System::Table; |
2
|
|
|
|
|
|
|
|
3
|
3
|
|
|
3
|
|
19
|
use strict; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
119
|
|
4
|
3
|
|
|
3
|
|
19
|
use warnings; |
|
3
|
|
|
|
|
4
|
|
|
3
|
|
|
|
|
99
|
|
5
|
|
|
|
|
|
|
|
6
|
3
|
|
|
3
|
|
22
|
use base 'File::System::Object'; |
|
3
|
|
|
|
|
5
|
|
|
3
|
|
|
|
|
4130
|
|
7
|
|
|
|
|
|
|
|
8
|
3
|
|
|
3
|
|
21
|
use Carp; |
|
3
|
|
|
|
|
7
|
|
|
3
|
|
|
|
|
227
|
|
9
|
3
|
|
|
3
|
|
17
|
use File::System; |
|
3
|
|
|
|
|
6
|
|
|
3
|
|
|
|
|
5197
|
|
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '1.15'; |
12
|
|
|
|
|
|
|
|
13
|
|
|
|
|
|
|
=head1 NAME |
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
File::System::Table - A file system implementation for mounting other modules |
16
|
|
|
|
|
|
|
|
17
|
|
|
|
|
|
|
=head1 SYNOPSIS |
18
|
|
|
|
|
|
|
|
19
|
|
|
|
|
|
|
use File::System; |
20
|
|
|
|
|
|
|
|
21
|
|
|
|
|
|
|
my $root = File::System->new('Table', |
22
|
|
|
|
|
|
|
'/' => [ 'Real', root => '/home/foo' ], |
23
|
|
|
|
|
|
|
'/tmp' => [ 'Real', root => '/tmp' ], |
24
|
|
|
|
|
|
|
'/bin' => [ 'Real', root => '/bin' ], |
25
|
|
|
|
|
|
|
); |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
my $file = $root->create('/tmp/dude', 'f'); |
28
|
|
|
|
|
|
|
my $fh = $file->open('w'); |
29
|
|
|
|
|
|
|
print $fh "Party on! Excellent!\n"; |
30
|
|
|
|
|
|
|
close $fh; |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
=head1 DESCRIPTION |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
This file system module allows for the creation of a tabular virtual file system. Each L is created with a root file system (at least) and then can have zero or more mounts to allow for more complicated file system handling. All mount points can be changed after the initial file system creation (except for the root, which is static). |
35
|
|
|
|
|
|
|
|
36
|
|
|
|
|
|
|
=head2 MOUNT POINTS |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
There are a few rules regarding mount points that this system requires. This should be familiar to anyone familiar with Unix file system mounting: |
39
|
|
|
|
|
|
|
|
40
|
|
|
|
|
|
|
=over |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
=item 1. |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
The root mount point (F>) is special and static. It cannot be unmounted except by deleting the file system object altogether. |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
=item 2. |
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
A specific mount point cannot be mounted more than once. I.e., the following code would fail: |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
$root = File::System->new('Table', '/' => [ 'Real' ]); |
51
|
|
|
|
|
|
|
$root->mount('/tmp' => [ 'Real', root => '/tmp' ]); |
52
|
|
|
|
|
|
|
$root->mount('/tmp' => [ 'Real', root => '/var/tmp' ]); |
53
|
|
|
|
|
|
|
# ^^^ ERROR! Mount point already in use! |
54
|
|
|
|
|
|
|
|
55
|
|
|
|
|
|
|
=item 3. |
56
|
|
|
|
|
|
|
|
57
|
|
|
|
|
|
|
A file system may only be mounted onto existing containers. When mounting a path, the path must exist as per the already present mount table and that path must represent a container. Otherwise, an error will occur. I.e., the following code would fail: |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
$root = File::System->new('Table', '/' => [ 'Real' ]); |
60
|
|
|
|
|
|
|
$obj = $root->lookup('/foo'); |
61
|
|
|
|
|
|
|
$obj->remove('force') if defined $obj; |
62
|
|
|
|
|
|
|
$root->mount('/foo' => [ 'Real', root => '/tmp' ]); |
63
|
|
|
|
|
|
|
# ^^^ ERROR! Mount point does not exist! |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
$root->mkfile('/foo'); |
66
|
|
|
|
|
|
|
$root->mount('/foo' => [ 'Real', root => '/tmp' ]); |
67
|
|
|
|
|
|
|
# ^^^ ERROR! Mount point is not a container! |
68
|
|
|
|
|
|
|
|
69
|
|
|
|
|
|
|
=item 4. |
70
|
|
|
|
|
|
|
|
71
|
|
|
|
|
|
|
Any content or containers within a container that is mounted to within the parent is immediately invisible. These objects are hidden by the child mount until the file system is unmounted. |
72
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
=item 5. |
74
|
|
|
|
|
|
|
|
75
|
|
|
|
|
|
|
A mount point cannot be set above an existing mount point so that it would hide an existing mount. I.e., the following code would fail: |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
$root = File::System->new('Table', '/' => [ 'Real' ]); |
78
|
|
|
|
|
|
|
$obj = $root->mkdir('/foo/bar'); |
79
|
|
|
|
|
|
|
$obj->mount('/foo/bar' => [ 'Real', root => '/tmp' ]); |
80
|
|
|
|
|
|
|
$obj->mount('/foo' => [ 'Real', root => '/var/tmp' ]); |
81
|
|
|
|
|
|
|
# ^^^ ERROR! Mount point hides an already mounted file system! |
82
|
|
|
|
|
|
|
|
83
|
|
|
|
|
|
|
=item 6. |
84
|
|
|
|
|
|
|
|
85
|
|
|
|
|
|
|
As a corollary to the fifth principle, a mount point cannot be removed above another mount point below. If you mount one file system within another, the inner file system must be unmounted prior to unmounting the outer. |
86
|
|
|
|
|
|
|
|
87
|
|
|
|
|
|
|
=back |
88
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
Because of these rules it is obvious that the order in which mounting takes place is significant and will affect the outcome. As such, the root mount must always be specified first in the constructor. |
90
|
|
|
|
|
|
|
|
91
|
|
|
|
|
|
|
=head2 MOUNT TABLE API |
92
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
This file system module provides a constructor (duh) and a few extra methods. All other methods are given in the documentation of L. |
94
|
|
|
|
|
|
|
|
95
|
|
|
|
|
|
|
=over |
96
|
|
|
|
|
|
|
|
97
|
|
|
|
|
|
|
=item $root = File::System-Enew('Table', '/' =E $fs, ...) |
98
|
|
|
|
|
|
|
|
99
|
|
|
|
|
|
|
The constructor establishes the initial mount table for the file system. The mount table must always contain at least one entry for the root directory (F>). The root directory entry must always be the first entry given as well. |
100
|
|
|
|
|
|
|
|
101
|
|
|
|
|
|
|
Each entry is made of two elements, the path to mount to and then a reference to either a reference to the file system object responsible for files under that mount point, or an array reference that can be passed to L to create a file system object. |
102
|
|
|
|
|
|
|
|
103
|
|
|
|
|
|
|
=cut |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
sub new { |
106
|
3
|
|
|
3
|
1
|
8
|
my $class = shift; |
107
|
|
|
|
|
|
|
|
108
|
3
|
50
|
|
|
|
11
|
$_[0] eq '/' |
109
|
|
|
|
|
|
|
or croak "The first mount point given must always be the root (/), but found '$_[0]' instead."; |
110
|
|
|
|
|
|
|
|
111
|
3
|
|
|
|
|
14
|
my $self = bless { cwd => '/' }, $class; |
112
|
|
|
|
|
|
|
|
113
|
3
|
|
|
|
|
16
|
while (my ($mp, $fs) = splice @_, 0, 2) { |
114
|
4
|
|
|
|
|
15
|
$self->mount($mp, $fs); |
115
|
|
|
|
|
|
|
} |
116
|
|
|
|
|
|
|
|
117
|
3
|
|
|
|
|
16
|
return $self; |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
=item $obj-Emount($path, $fs) |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
Each entry is made of two elements, the path to mount to and then a reference to either a reference to the file system object responsible for files under that mount point, or an array reference that can be passed to L to create a file system object. |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
=cut |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub mount { |
127
|
8
|
|
|
8
|
1
|
3590
|
my $self = shift; |
128
|
8
|
|
|
|
|
45
|
my $path = $self->normalize_path(shift); |
129
|
8
|
|
|
|
|
33
|
my $fs = $self->_init_fs(shift); |
130
|
|
|
|
|
|
|
|
131
|
8
|
100
|
|
|
|
36
|
if ($path eq '/') { |
132
|
3
|
50
|
|
|
|
273
|
if (defined $self->{mounts}) { |
133
|
0
|
|
|
|
|
0
|
croak "The root mount point cannot be overridden."; |
134
|
|
|
|
|
|
|
} else { |
135
|
3
|
|
|
|
|
40
|
$self->{cwd_fs} = $self->{mounts}{$path} = $fs; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
} else { |
138
|
5
|
|
|
|
|
26
|
my $dir = $self->lookup($path); |
139
|
|
|
|
|
|
|
|
140
|
5
|
50
|
|
|
|
20
|
defined $dir |
141
|
|
|
|
|
|
|
or croak "The mount point '$path' does not exist."; |
142
|
|
|
|
|
|
|
|
143
|
5
|
50
|
|
|
|
412
|
$dir->is_container |
144
|
|
|
|
|
|
|
or croak "The mount point '$path' is not a container."; |
145
|
|
|
|
|
|
|
|
146
|
5
|
|
|
|
|
14
|
my @inner = grep /^$path/, keys %{ $self->{mounts} }; |
|
5
|
|
|
|
|
107
|
|
147
|
5
|
50
|
|
|
|
22
|
croak "The mount point '$inner[0]' must be unmounted before mount point '$path' may be used." |
148
|
|
|
|
|
|
|
if @inner; |
149
|
|
|
|
|
|
|
|
150
|
5
|
100
|
|
|
|
247
|
$dir->has_children |
151
|
|
|
|
|
|
|
and carp "Mounting on mount point '$path' will hide some files."; |
152
|
|
|
|
|
|
|
|
153
|
5
|
|
|
|
|
722
|
$self->{mounts}{$path} = $fs; |
154
|
|
|
|
|
|
|
} |
155
|
|
|
|
|
|
|
} |
156
|
|
|
|
|
|
|
|
157
|
|
|
|
|
|
|
=item $unmounted_fs = $fs-Eunmount($path) |
158
|
|
|
|
|
|
|
|
159
|
|
|
|
|
|
|
Unmounts the file system mounted to the given path. This method will raise an exception if the user attempts to unmount a path that has no file system mounted. |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
This method returns the file system that was mounted at the given path. |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
=cut |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub unmount { |
166
|
4
|
|
|
4
|
1
|
7387
|
my $self = shift; |
167
|
4
|
|
|
|
|
27
|
my $path = $self->normalize_path(shift); |
168
|
|
|
|
|
|
|
|
169
|
4
|
50
|
|
|
|
19
|
$path eq '/' |
170
|
|
|
|
|
|
|
and croak "The root mount point cannot be unmounted."; |
171
|
|
|
|
|
|
|
|
172
|
4
|
50
|
|
|
|
25
|
defined $self->{mounts}{$path} |
173
|
|
|
|
|
|
|
or croak "No file system is mounted at '$path'. Therefore it cannot be unmounted."; |
174
|
|
|
|
|
|
|
|
175
|
4
|
|
|
|
|
9
|
my @inner = grep /^$path./, keys %{ $self->{mounts} }; |
|
4
|
|
|
|
|
101
|
|
176
|
4
|
50
|
|
|
|
20
|
croak "Mount point '$inner[0]' must be unmounted before '$path'" |
177
|
|
|
|
|
|
|
if @inner; |
178
|
|
|
|
|
|
|
|
179
|
4
|
|
|
|
|
44
|
delete $self->{mounts}{$path}; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
=item @paths = $fs-Emounts |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
Returns the list of all paths that have been mounted to. |
185
|
|
|
|
|
|
|
|
186
|
|
|
|
|
|
|
=cut |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
sub mounts { |
189
|
225
|
|
|
225
|
1
|
8244
|
my $self = shift; |
190
|
225
|
|
|
|
|
500
|
return keys %{ $self->{mounts} }; |
|
225
|
|
|
|
|
1227
|
|
191
|
|
|
|
|
|
|
} |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
=back |
194
|
|
|
|
|
|
|
|
195
|
|
|
|
|
|
|
=cut |
196
|
|
|
|
|
|
|
|
197
|
|
|
|
|
|
|
sub _init_fs { |
198
|
8
|
|
|
8
|
|
14
|
my $self = shift; |
199
|
8
|
|
|
|
|
10
|
my $fs = shift; |
200
|
|
|
|
|
|
|
|
201
|
8
|
50
|
|
|
|
65
|
if (UNIVERSAL::isa($fs, 'File::System::Object')) { |
|
|
50
|
|
|
|
|
|
202
|
0
|
|
|
|
|
0
|
return $fs; |
203
|
|
|
|
|
|
|
} elsif (ref $fs eq 'ARRAY') { |
204
|
8
|
|
|
|
|
71
|
return File::System->new(@$fs); |
205
|
|
|
|
|
|
|
} else { |
206
|
0
|
|
|
|
|
0
|
croak "File system must be an array reference or an actual File::System::Object. '$fs' is neither of these. See the documentation of File::System::Table for details."; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
} |
209
|
|
|
|
|
|
|
|
210
|
|
|
|
|
|
|
sub _resolve_fs { |
211
|
27334
|
|
|
27334
|
|
43094
|
my $self = shift; |
212
|
27334
|
|
|
|
|
73286
|
my $path = $self->normalize_path(shift); |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
# The mount point we want should be the longest one which matches our |
215
|
|
|
|
|
|
|
# given path name. |
216
|
5044
|
|
|
|
|
31168
|
my ($mp) = |
217
|
69253
|
|
|
|
|
3474854
|
sort { -(length($a) <=> length($b)) } |
218
|
27334
|
|
|
|
|
87432
|
grep { $path =~ /^$_/ } |
219
|
27334
|
|
|
|
|
49454
|
keys %{ $self->{mounts} }; |
220
|
|
|
|
|
|
|
|
221
|
27334
|
|
|
|
|
70128
|
my $rel_path = substr $path, length($mp); |
222
|
27334
|
100
|
|
|
|
86900
|
$rel_path = '/'.$rel_path unless $rel_path =~ /^\//; |
223
|
|
|
|
|
|
|
|
224
|
27334
|
|
|
|
|
120586
|
return ($self->{mounts}{$mp}, $rel_path); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub root { |
228
|
1686
|
|
|
1686
|
1
|
2617
|
my $self = shift; |
229
|
|
|
|
|
|
|
|
230
|
1686
|
|
|
|
|
14219
|
return bless { |
231
|
|
|
|
|
|
|
cwd => '/', |
232
|
|
|
|
|
|
|
cwd_fs => $self->{mounts}{'/'}, |
233
|
|
|
|
|
|
|
mounts => $self->{mounts}, |
234
|
|
|
|
|
|
|
}, ref $self; |
235
|
|
|
|
|
|
|
} |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
sub exists { |
238
|
492
|
|
|
492
|
1
|
163676
|
my $self = shift; |
239
|
492
|
|
66
|
|
|
2126
|
my ($fs, $path) = $self->_resolve_fs(shift || $self->path); |
240
|
492
|
|
|
|
|
2006
|
return $fs->exists($path); |
241
|
|
|
|
|
|
|
} |
242
|
|
|
|
|
|
|
|
243
|
|
|
|
|
|
|
sub lookup { |
244
|
26387
|
|
|
26387
|
1
|
439111
|
my $self = shift; |
245
|
26387
|
|
|
|
|
116420
|
my $cwd = $self->normalize_path($_[0]); |
246
|
26387
|
|
|
|
|
75858
|
my ($fs, $path) = $self->_resolve_fs(shift); |
247
|
|
|
|
|
|
|
|
248
|
26387
|
|
|
|
|
104621
|
my $cwd_fs = $fs->lookup($path); |
249
|
|
|
|
|
|
|
|
250
|
26387
|
100
|
|
|
|
63169
|
return undef unless defined $cwd_fs; |
251
|
|
|
|
|
|
|
|
252
|
26376
|
|
|
|
|
310059
|
return bless { |
253
|
|
|
|
|
|
|
cwd => $cwd, |
254
|
|
|
|
|
|
|
cwd_fs => $cwd_fs, |
255
|
|
|
|
|
|
|
mounts => $self->{mounts}, |
256
|
|
|
|
|
|
|
}, ref $self; |
257
|
|
|
|
|
|
|
} |
258
|
|
|
|
|
|
|
|
259
|
|
|
|
|
|
|
my @delegates = qw/ |
260
|
|
|
|
|
|
|
is_valid |
261
|
|
|
|
|
|
|
properties |
262
|
|
|
|
|
|
|
settable_properties |
263
|
|
|
|
|
|
|
set_property |
264
|
|
|
|
|
|
|
remove |
265
|
|
|
|
|
|
|
has_content |
266
|
|
|
|
|
|
|
is_container |
267
|
|
|
|
|
|
|
is_readable |
268
|
|
|
|
|
|
|
is_seekable |
269
|
|
|
|
|
|
|
is_writable |
270
|
|
|
|
|
|
|
is_appendable |
271
|
|
|
|
|
|
|
open |
272
|
|
|
|
|
|
|
content |
273
|
|
|
|
|
|
|
has_children |
274
|
|
|
|
|
|
|
children_paths |
275
|
|
|
|
|
|
|
/; |
276
|
|
|
|
|
|
|
|
277
|
|
|
|
|
|
|
for my $name (@delegates) { |
278
|
|
|
|
|
|
|
eval qq( |
279
|
|
|
|
|
|
|
#line 287 "File::Sytem::Table ($name)" |
280
|
|
|
|
|
|
|
sub $name { |
281
|
|
|
|
|
|
|
my \$self = shift; |
282
|
|
|
|
|
|
|
return \$self->{cwd_fs}->$name(\@_); |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
); |
285
|
|
|
|
|
|
|
die $@ if $@; |
286
|
|
|
|
|
|
|
} |
287
|
|
|
|
|
|
|
|
288
|
|
|
|
|
|
|
sub get_property { |
289
|
108874
|
|
|
108874
|
1
|
161108
|
my $self = shift; |
290
|
108874
|
|
|
|
|
177104
|
local $_ = shift; |
291
|
|
|
|
|
|
|
|
292
|
|
|
|
|
|
|
SWITCH: { |
293
|
108874
|
100
|
|
|
|
165983
|
/^path$/ && do { |
|
108874
|
|
|
|
|
370138
|
|
294
|
100761
|
|
|
|
|
588988
|
return $self->{cwd}; |
295
|
|
|
|
|
|
|
}; |
296
|
8113
|
100
|
|
|
|
25760
|
/^dirname$/ && do { |
297
|
5495
|
|
|
|
|
20853
|
return $self->dirname_of_path($self->{cwd}); |
298
|
|
|
|
|
|
|
}; |
299
|
2618
|
100
|
|
|
|
7651
|
/^basename$/ && do { |
300
|
1826
|
|
|
|
|
20289
|
return $self->basename_of_path($self->{cwd}); |
301
|
|
|
|
|
|
|
}; |
302
|
792
|
|
|
|
|
2845
|
DEFAULT: { |
303
|
792
|
|
|
|
|
921
|
return $self->{cwd_fs}->get_property($_); |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub rename { |
309
|
382
|
|
|
382
|
1
|
548
|
my $self = shift; |
310
|
382
|
|
|
|
|
756
|
my $name = shift; |
311
|
|
|
|
|
|
|
|
312
|
382
|
50
|
|
|
|
459
|
grep { $self->{cwd} eq $_ } keys %{ $self->{mounts} } |
|
940
|
|
|
|
|
2688
|
|
|
382
|
|
|
|
|
1521
|
|
313
|
|
|
|
|
|
|
and croak "Cannot rename the mount point '$self'"; |
314
|
|
|
|
|
|
|
|
315
|
382
|
|
|
|
|
1793
|
$self->{cwd_fs}->rename($name); |
316
|
|
|
|
|
|
|
|
317
|
382
|
|
|
|
|
2269
|
$self->{cwd} =~ s#[^/]+$ #$name#x; |
318
|
|
|
|
|
|
|
|
319
|
382
|
|
|
|
|
1642
|
return $self; |
320
|
|
|
|
|
|
|
} |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
sub move { |
323
|
382
|
|
|
382
|
1
|
597
|
my $self = shift; |
324
|
382
|
|
|
|
|
534
|
my $path = shift; |
325
|
382
|
|
|
|
|
541
|
my $force = shift; |
326
|
|
|
|
|
|
|
|
327
|
382
|
50
|
|
|
|
1694
|
UNIVERSAL::isa($path, 'File::System::Table') |
328
|
|
|
|
|
|
|
or croak "Move failed; the '$path' object is not a 'File::System::Table'"; |
329
|
|
|
|
|
|
|
|
330
|
382
|
|
|
|
|
1857
|
$self->{cwd_fs}->move($path->{cwd_fs}, $force); |
331
|
382
|
|
|
|
|
1202
|
$self->{cwd} = $self->normalize_path($path->path.'/'.$self->basename); |
332
|
|
|
|
|
|
|
|
333
|
382
|
|
|
|
|
1659
|
return $self; |
334
|
|
|
|
|
|
|
} |
335
|
|
|
|
|
|
|
|
336
|
|
|
|
|
|
|
sub copy { |
337
|
191
|
|
|
191
|
1
|
294
|
my $self = shift; |
338
|
191
|
|
|
|
|
322
|
my $path = shift; |
339
|
191
|
|
|
|
|
411
|
my $force = shift; |
340
|
|
|
|
|
|
|
|
341
|
191
|
50
|
|
|
|
822
|
UNIVERSAL::isa($path, 'File::System::Table') |
342
|
|
|
|
|
|
|
or croak "Copy failed; the '$path' object is not a 'File::System::Table'"; |
343
|
|
|
|
|
|
|
|
344
|
191
|
|
|
|
|
1095
|
my $copy = $self->{cwd_fs}->copy($path->{cwd_fs}, $force); |
345
|
191
|
|
|
|
|
872
|
my $copy_cwd = $self->normalize_path($path->path.'/'.$self->basename); |
346
|
|
|
|
|
|
|
|
347
|
191
|
|
|
|
|
1761
|
return bless { |
348
|
|
|
|
|
|
|
cwd_fs => $copy, |
349
|
|
|
|
|
|
|
cwd => $copy_cwd, |
350
|
|
|
|
|
|
|
mounts => $self->{mounts}, |
351
|
|
|
|
|
|
|
}, ref $self; |
352
|
|
|
|
|
|
|
} |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
sub children { |
355
|
2137
|
|
|
2137
|
1
|
3774
|
my $self = shift; |
356
|
|
|
|
|
|
|
return |
357
|
2137
|
|
|
|
|
9560
|
map { $self->lookup($_) } |
|
3098
|
|
|
|
|
16161
|
|
358
|
|
|
|
|
|
|
grep !/^\.\.?$/, $self->{cwd_fs}->children_paths; |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub child { |
362
|
242
|
|
|
242
|
1
|
16215
|
my $self = shift; |
363
|
242
|
|
|
|
|
390
|
my $name = shift; |
364
|
|
|
|
|
|
|
|
365
|
242
|
50
|
|
|
|
764
|
$self->is_container |
366
|
|
|
|
|
|
|
or croak "The child method called on non-container."; |
367
|
|
|
|
|
|
|
|
368
|
242
|
50
|
|
|
|
742
|
$name !~ /\// |
369
|
|
|
|
|
|
|
or croak "Argument to child must not be a path."; |
370
|
|
|
|
|
|
|
|
371
|
242
|
|
|
|
|
607
|
return $self->lookup($name); |
372
|
|
|
|
|
|
|
} |
373
|
|
|
|
|
|
|
|
374
|
|
|
|
|
|
|
sub is_createable { |
375
|
0
|
|
|
0
|
0
|
0
|
my $self = shift; |
376
|
0
|
|
|
|
|
0
|
my $path = $self->normalize_path($_[0]); |
377
|
0
|
|
|
|
|
0
|
my ($fs, $rel_path) = $self->_resolve_fs(shift); |
378
|
0
|
|
|
|
|
0
|
my $type = shift; |
379
|
|
|
|
|
|
|
|
380
|
0
|
|
|
|
|
0
|
return $fs->is_creatable($rel_path, $type); |
381
|
|
|
|
|
|
|
} |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
sub create { |
384
|
455
|
|
|
455
|
1
|
6961731
|
my $self = shift; |
385
|
455
|
|
|
|
|
2325
|
my $path = $self->normalize_path($_[0]); |
386
|
455
|
|
|
|
|
1746
|
my ($fs, $rel_path) = $self->_resolve_fs(shift); |
387
|
455
|
|
|
|
|
1008
|
my $type = shift; |
388
|
|
|
|
|
|
|
|
389
|
455
|
|
|
|
|
2122
|
my $obj = $fs->create($rel_path, $type); |
390
|
|
|
|
|
|
|
|
391
|
455
|
50
|
|
|
|
2296
|
return undef unless defined $obj; |
392
|
|
|
|
|
|
|
|
393
|
455
|
|
|
|
|
3877
|
return bless { |
394
|
|
|
|
|
|
|
cwd => $path, |
395
|
|
|
|
|
|
|
cwd_fs => $obj, |
396
|
|
|
|
|
|
|
mounts => $self->{mounts}, |
397
|
|
|
|
|
|
|
}, ref $self; |
398
|
|
|
|
|
|
|
} |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
=head1 BUGS |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
The C and C methods will fail if used between file systems. This can be remedied, but it will require some delicate planning that hasn't yet been done. |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
=head1 SEE ALSO |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
L, L, L, L |
407
|
|
|
|
|
|
|
|
408
|
|
|
|
|
|
|
=head1 AUTHOR |
409
|
|
|
|
|
|
|
|
410
|
|
|
|
|
|
|
Andrew Sterling Hanenkamp, Ehanenkamp@cpan.orgE |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
413
|
|
|
|
|
|
|
|
414
|
|
|
|
|
|
|
Copyright 2005 Andrew Sterling Hanenkamp. All Rights Reserved. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
This library is distributed and licensed under the same terms as Perl itself. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
=cut |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
1 |