line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
# Declare our package |
2
|
|
|
|
|
|
|
package Filesys::Virtual::Async::Dispatcher; |
3
|
1
|
|
|
1
|
|
1150
|
use strict; use warnings; |
|
1
|
|
|
1
|
|
2
|
|
|
1
|
|
|
|
|
48
|
|
|
1
|
|
|
|
|
8
|
|
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
44
|
|
4
|
|
|
|
|
|
|
|
5
|
|
|
|
|
|
|
# Initialize our version |
6
|
1
|
|
|
1
|
|
17
|
use vars qw( $VERSION ); |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
83
|
|
7
|
|
|
|
|
|
|
$VERSION = '0.02'; |
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# set our superclass |
10
|
1
|
|
|
1
|
|
7
|
use base 'Filesys::Virtual::Async'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
1347
|
|
11
|
|
|
|
|
|
|
|
12
|
|
|
|
|
|
|
# get some handy stuff |
13
|
1
|
|
|
1
|
|
1772
|
use File::Spec; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
33
|
|
14
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
# get the refaddr of our FHs |
16
|
1
|
|
|
1
|
|
7
|
use Scalar::Util qw( refaddr openhandle ); |
|
1
|
|
|
|
|
1
|
|
|
1
|
|
|
|
|
98
|
|
17
|
|
|
|
|
|
|
|
18
|
|
|
|
|
|
|
# get some system constants |
19
|
1
|
|
|
1
|
|
6
|
use Errno qw( :POSIX ); # ENOENT EISDIR etc |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
582
|
|
20
|
1
|
|
|
1
|
|
6
|
use Fcntl qw( :DEFAULT :mode :seek ); # S_IFREG S_IFDIR, O_SYNC O_LARGEFILE etc |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
830
|
|
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Set some constants |
23
|
|
|
|
|
|
|
BEGIN { |
24
|
1
|
50
|
|
1
|
|
5
|
if ( ! defined &DEBUG ) { *DEBUG = sub () { 0 } } |
|
1
|
|
|
|
|
21338
|
|
25
|
|
|
|
|
|
|
} |
26
|
|
|
|
|
|
|
|
27
|
|
|
|
|
|
|
# creates a new instance |
28
|
|
|
|
|
|
|
sub new { |
29
|
0
|
|
|
0
|
1
|
|
my $class = shift; |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# The options hash |
32
|
0
|
|
|
|
|
|
my %opt; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Support passing in a hash ref or a regular hash |
35
|
0
|
0
|
0
|
|
|
|
if ( ( @_ & 1 ) and ref $_[0] and ref( $_[0] ) eq 'HASH' ) { |
|
|
|
0
|
|
|
|
|
36
|
0
|
|
|
|
|
|
%opt = %{ $_[0] }; |
|
0
|
|
|
|
|
|
|
37
|
|
|
|
|
|
|
} else { |
38
|
|
|
|
|
|
|
# Sanity checking |
39
|
0
|
0
|
|
|
|
|
if ( @_ & 1 ) { |
40
|
0
|
|
|
|
|
|
die __PACKAGE__ . ' requires an even number of options passed to new()'; |
41
|
|
|
|
|
|
|
} |
42
|
|
|
|
|
|
|
|
43
|
0
|
|
|
|
|
|
%opt = @_; |
44
|
|
|
|
|
|
|
} |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# lowercase keys |
47
|
0
|
|
|
|
|
|
%opt = map { lc($_) => $opt{$_} } keys %opt; |
|
0
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
|
49
|
|
|
|
|
|
|
# set the rootfs |
50
|
0
|
0
|
0
|
|
|
|
if ( ! exists $opt{'rootfs'} or ! defined $opt{'rootfs'} or ! ref $opt{'rootfs'} ) { |
51
|
0
|
|
|
|
|
|
die __PACKAGE__ . ' needs rootfs defined to bootstrap'; |
52
|
|
|
|
|
|
|
} else { |
53
|
|
|
|
|
|
|
# make sure it's the proper object |
54
|
0
|
0
|
|
|
|
|
if ( ! $opt{'rootfs'}->isa( 'Filesys::Virtual::Async' ) ) { |
55
|
0
|
|
|
|
|
|
die 'rootfs is not a valid ::Async subclass'; |
56
|
|
|
|
|
|
|
} |
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
# create our instance |
60
|
0
|
|
0
|
|
|
|
my $self = { |
61
|
|
|
|
|
|
|
'cwd' => $opt{'rootfs'}->cwd || File::Spec->rootdir(), |
62
|
|
|
|
|
|
|
'mounts' => {}, |
63
|
|
|
|
|
|
|
'mountstree' => {}, |
64
|
|
|
|
|
|
|
'fhmap' => {}, |
65
|
|
|
|
|
|
|
}; |
66
|
0
|
|
|
|
|
|
bless $self, $class; |
67
|
|
|
|
|
|
|
|
68
|
|
|
|
|
|
|
# initialize the first mount |
69
|
0
|
|
|
|
|
|
$self->mount( File::Spec->rootdir(), $opt{'rootfs'} ); |
70
|
|
|
|
|
|
|
|
71
|
0
|
|
|
|
|
|
return $self; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
sub mount { |
75
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $vfs ) = @_; |
76
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
# sanity |
78
|
0
|
0
|
|
|
|
|
if ( ! defined $path ) { |
79
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
80
|
|
|
|
|
|
|
warn 'invalid path'; |
81
|
|
|
|
|
|
|
} |
82
|
0
|
|
|
|
|
|
return 0; |
83
|
|
|
|
|
|
|
} else { |
84
|
|
|
|
|
|
|
# sanitize the path |
85
|
0
|
|
|
|
|
|
$path = File::Spec->canonpath( $path ); |
86
|
|
|
|
|
|
|
} |
87
|
|
|
|
|
|
|
|
88
|
|
|
|
|
|
|
# make sure it's a valid subclass |
89
|
0
|
0
|
0
|
|
|
|
if ( ! defined $vfs or ! ref $vfs or ! $vfs->isa( 'Filesys::Virtual::Async' ) ) { |
|
|
|
0
|
|
|
|
|
90
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
91
|
|
|
|
|
|
|
warn 'vfs is not a valid ::Async subclass'; |
92
|
|
|
|
|
|
|
} |
93
|
0
|
|
|
|
|
|
return 0; |
94
|
|
|
|
|
|
|
} |
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# FIXME Does the directory exist? |
97
|
|
|
|
|
|
|
# this is insane... we need a callback to stat() and see if it exists! |
98
|
|
|
|
|
|
|
# for now, we blindly mount, ha! |
99
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# Is that path taken? |
101
|
0
|
0
|
|
|
|
|
if ( exists $self->{'mounts'}->{ $path } ) { |
102
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
103
|
|
|
|
|
|
|
warn 'unable to mount over another mount'; |
104
|
|
|
|
|
|
|
} |
105
|
0
|
|
|
|
|
|
return 0; |
106
|
|
|
|
|
|
|
} |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
# Split up the path |
109
|
0
|
|
|
|
|
|
my @dirs; |
110
|
0
|
0
|
|
|
|
|
if ( $path eq File::Spec->rootdir() ) { |
111
|
0
|
|
|
|
|
|
push( @dirs, File::Spec->rootdir() ); |
112
|
|
|
|
|
|
|
} else { |
113
|
0
|
|
|
|
|
|
@dirs = File::Spec->splitdir( $path ); |
114
|
0
|
0
|
|
|
|
|
if ( @dirs ) { |
115
|
0
|
|
|
|
|
|
$dirs[0] = File::Spec->rootdir(); |
116
|
|
|
|
|
|
|
} else { |
117
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
118
|
|
|
|
|
|
|
warn 'path is not a valid directory name'; |
119
|
|
|
|
|
|
|
} |
120
|
0
|
|
|
|
|
|
return 0; |
121
|
|
|
|
|
|
|
} |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# store it! |
125
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
126
|
|
|
|
|
|
|
warn "mounting '$path' with $vfs"; |
127
|
|
|
|
|
|
|
} |
128
|
0
|
|
|
|
|
|
$self->{'mounts'}->{ $path } = $vfs; |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# build the tree |
131
|
0
|
|
|
|
|
|
my $curpos = $self->{'mountstree'}; |
132
|
0
|
|
|
|
|
|
foreach my $dir ( @dirs ) { |
133
|
|
|
|
|
|
|
## no critic ( ProhibitAccessOfPrivateData ) |
134
|
0
|
0
|
|
|
|
|
$curpos->{ $dir } = {} if not exists $curpos->{ $dir }; |
135
|
0
|
|
|
|
|
|
$curpos = $curpos->{ $dir }; |
136
|
|
|
|
|
|
|
} |
137
|
|
|
|
|
|
|
|
138
|
0
|
|
|
|
|
|
return 1; |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
|
141
|
|
|
|
|
|
|
sub umount { |
142
|
0
|
|
|
0
|
1
|
|
my( $self, $path ) = @_; |
143
|
|
|
|
|
|
|
|
144
|
|
|
|
|
|
|
# sanity |
145
|
0
|
0
|
|
|
|
|
if ( ! defined $path ) { |
146
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
147
|
|
|
|
|
|
|
warn 'invalid path'; |
148
|
|
|
|
|
|
|
} |
149
|
0
|
|
|
|
|
|
return 0; |
150
|
|
|
|
|
|
|
} else { |
151
|
|
|
|
|
|
|
# sanitize the path |
152
|
0
|
|
|
|
|
|
$path = File::Spec->canonpath( $path ); |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# unable to umount the rootfs, hah! |
156
|
0
|
0
|
|
|
|
|
if ( $path eq File::Spec->rootdir() ) { |
157
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
158
|
|
|
|
|
|
|
warn 'unable to umount the rootfs'; |
159
|
|
|
|
|
|
|
} |
160
|
0
|
|
|
|
|
|
return 0; |
161
|
|
|
|
|
|
|
} |
162
|
|
|
|
|
|
|
|
163
|
|
|
|
|
|
|
# is the path mounted? |
164
|
0
|
0
|
|
|
|
|
if ( ! exists $self->{'mounts'}->{ $path } ) { |
165
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
166
|
|
|
|
|
|
|
warn "directory '$path' is not mounted"; |
167
|
|
|
|
|
|
|
} |
168
|
0
|
|
|
|
|
|
return 0; |
169
|
|
|
|
|
|
|
} |
170
|
|
|
|
|
|
|
|
171
|
|
|
|
|
|
|
# are there any mounts under this one? |
172
|
0
|
|
|
|
|
|
my @matches = grep { $_ =~ /^$path/ } ( keys %{ $self->{'mounts'} } ); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
173
|
0
|
0
|
|
|
|
|
if ( @matches > 1 ) { |
174
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
175
|
|
|
|
|
|
|
warn "unable to umount '$path' as there are more mounts inside it"; |
176
|
|
|
|
|
|
|
} |
177
|
0
|
|
|
|
|
|
return 0; |
178
|
|
|
|
|
|
|
} |
179
|
|
|
|
|
|
|
|
180
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
181
|
|
|
|
|
|
|
warn "umounting '$path'"; |
182
|
|
|
|
|
|
|
} |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# unmount it! |
185
|
0
|
|
|
|
|
|
delete $self->{'mounts'}->{ $path }; |
186
|
|
|
|
|
|
|
|
187
|
|
|
|
|
|
|
# clean up the tree |
188
|
0
|
|
|
|
|
|
my @dirs = File::Spec->splitdir( $path ); |
189
|
0
|
|
|
|
|
|
shift( @dirs ); # get rid of the root entry which is always '' for me |
190
|
0
|
|
|
|
|
|
my $curpath = File::Spec->rootdir(); |
191
|
0
|
|
|
|
|
|
my $curpos = $self->{'mountstree'}->{ $curpath }; |
192
|
0
|
|
|
|
|
|
foreach my $dir ( @dirs ) { |
193
|
0
|
|
|
|
|
|
$curpath = File::Spec->catdir( $curpath, $dir ); |
194
|
0
|
0
|
|
|
|
|
if ( ! exists $self->{'mounts'}->{ $curpath } ) { |
195
|
|
|
|
|
|
|
# yay, reached end of tree |
196
|
0
|
|
|
|
|
|
delete $curpos->{ $dir }; ## no critic ( ProhibitAccessOfPrivateData ) |
197
|
0
|
|
|
|
|
|
last; |
198
|
|
|
|
|
|
|
} else { |
199
|
0
|
|
|
|
|
|
$curpos = $curpos->{ $dir }; ## no critic ( ProhibitAccessOfPrivateData ) |
200
|
|
|
|
|
|
|
} |
201
|
|
|
|
|
|
|
} |
202
|
|
|
|
|
|
|
|
203
|
0
|
|
|
|
|
|
return 1; |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub _findmount { |
207
|
0
|
|
|
0
|
|
|
my( $self, $path ) = @_; |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
# get an absolute path |
210
|
0
|
|
|
|
|
|
$path = File::Spec->rel2abs( $path, $self->{'cwd'} ); |
211
|
|
|
|
|
|
|
|
212
|
|
|
|
|
|
|
# traverse the tree, searching for the "deepest" hash we can find |
213
|
0
|
|
|
|
|
|
my @dirs = File::Spec->splitdir( $path ); |
214
|
0
|
|
|
|
|
|
shift( @dirs ); # get rid of the root entry which is always '' for me |
215
|
0
|
|
|
|
|
|
my $curpath = File::Spec->rootdir(); |
216
|
0
|
|
|
|
|
|
my $curpos = $self->{'mountstree'}->{ $curpath }; |
217
|
0
|
|
|
|
|
|
foreach my $dir ( @dirs ) { |
218
|
|
|
|
|
|
|
## no critic ( ProhibitAccessOfPrivateData ) |
219
|
0
|
0
|
|
|
|
|
if ( exists $curpos->{ $dir } ) { |
220
|
0
|
|
|
|
|
|
$curpath = File::Spec->catdir( $curpath, $dir ); |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
# is it the end? |
223
|
0
|
0
|
|
|
|
|
if ( ! defined $curpos->{ $dir } ) { |
224
|
|
|
|
|
|
|
# found our match! |
225
|
0
|
|
|
|
|
|
last; |
226
|
|
|
|
|
|
|
} else { |
227
|
|
|
|
|
|
|
# continue traversing |
228
|
0
|
|
|
|
|
|
$curpos = $curpos->{ $dir }; |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
} else { |
231
|
|
|
|
|
|
|
# found our match! |
232
|
0
|
|
|
|
|
|
last; |
233
|
|
|
|
|
|
|
} |
234
|
|
|
|
|
|
|
} |
235
|
|
|
|
|
|
|
|
236
|
|
|
|
|
|
|
# grab the mount object |
237
|
0
|
0
|
|
|
|
|
if ( ! exists $self->{'mounts'}->{ $curpath } ) { |
238
|
0
|
|
|
|
|
|
die "internal inconsistency - unable to find mount path($path) curpath($curpath)"; |
239
|
|
|
|
|
|
|
} |
240
|
|
|
|
|
|
|
|
241
|
|
|
|
|
|
|
# figure out the relative path |
242
|
0
|
|
|
|
|
|
my $relpath = File::Spec->catdir( File::Spec->rootdir(), File::Spec->abs2rel( $path, $curpath ) ); |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
# all done! |
245
|
0
|
|
|
|
|
|
return $self->{'mounts'}->{ $curpath }, $relpath; |
246
|
|
|
|
|
|
|
} |
247
|
|
|
|
|
|
|
|
248
|
|
|
|
|
|
|
sub cwd { |
249
|
0
|
|
|
0
|
1
|
|
my( $self, $cwd, $cb ) = @_; |
250
|
|
|
|
|
|
|
|
251
|
|
|
|
|
|
|
# sanitize the path |
252
|
0
|
|
|
|
|
|
$cwd = File::Spec->canonpath( $cwd ); |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
# Get or set? |
255
|
0
|
0
|
|
|
|
|
if ( ! defined $cwd ) { |
256
|
0
|
0
|
|
|
|
|
if ( defined $cb ) { |
257
|
0
|
|
|
|
|
|
$cb->( $self->{'cwd'} ); |
258
|
0
|
|
|
|
|
|
return; |
259
|
|
|
|
|
|
|
} else { |
260
|
0
|
|
|
|
|
|
return $self->{'cwd'}; |
261
|
|
|
|
|
|
|
} |
262
|
|
|
|
|
|
|
} |
263
|
|
|
|
|
|
|
|
264
|
|
|
|
|
|
|
# Is it the same cwd as we have? |
265
|
0
|
0
|
|
|
|
|
if ( $cwd eq $self->{'cwd'} ) { |
266
|
0
|
0
|
|
|
|
|
if ( defined $cb ) { |
267
|
0
|
|
|
|
|
|
$cb->( $cwd ); |
268
|
0
|
|
|
|
|
|
return; |
269
|
|
|
|
|
|
|
} else { |
270
|
0
|
|
|
|
|
|
return $cwd; |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
} |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# actually change our cwd! |
275
|
0
|
|
|
|
|
|
$self->{'cwd'} = $cwd; |
276
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $cwd ); |
277
|
0
|
0
|
|
|
|
|
if ( defined $cb ) { |
278
|
0
|
|
|
|
|
|
$mount->cwd( $where, $cb ); |
279
|
0
|
|
|
|
|
|
return; |
280
|
|
|
|
|
|
|
} else { |
281
|
0
|
|
|
|
|
|
return $mount->cwd( $where ); |
282
|
|
|
|
|
|
|
} |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub root { |
286
|
|
|
|
|
|
|
# we cannot sanely do this because we have no idea which mount to apply it to... |
287
|
0
|
|
|
0
|
1
|
|
if ( DEBUG ) { |
288
|
|
|
|
|
|
|
warn 'Setting root on the dispatcher has no meaning, please do it directly on the mount!'; |
289
|
|
|
|
|
|
|
} |
290
|
0
|
|
|
|
|
|
return; |
291
|
|
|
|
|
|
|
} |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
sub _resolve_fh { |
294
|
0
|
|
|
0
|
|
|
my $self = shift; |
295
|
0
|
|
|
|
|
|
my $fh = shift; |
296
|
0
|
|
|
|
|
|
my $ret = undef; |
297
|
0
|
0
|
|
|
|
|
if ( openhandle( $fh ) ) { |
298
|
0
|
|
|
|
|
|
$ret = refaddr( $fh ); |
299
|
0
|
0
|
|
|
|
|
if ( ! defined $ret ) { |
300
|
|
|
|
|
|
|
# try direct stringy eval |
301
|
0
|
|
|
|
|
|
$ret = "$fh"; |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
|
305
|
0
|
|
|
|
|
|
return $ret; |
306
|
|
|
|
|
|
|
} |
307
|
|
|
|
|
|
|
|
308
|
|
|
|
|
|
|
sub dirlist { |
309
|
0
|
|
|
0
|
0
|
|
my ( $self, $path, $withstat, $callback ) = @_; |
310
|
|
|
|
|
|
|
|
311
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
312
|
0
|
|
|
|
|
|
$mount->dirlist( $where, $withstat, $callback ); |
313
|
|
|
|
|
|
|
|
314
|
0
|
|
|
|
|
|
return; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
sub open { |
318
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $flags, $mode, $callback ) = @_; |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
# construct our custom callback |
321
|
|
|
|
|
|
|
my $cb = sub { |
322
|
0
|
|
|
0
|
|
|
my $fh = shift; |
323
|
0
|
0
|
|
|
|
|
if ( defined $fh ) { |
324
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
325
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
326
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
327
|
0
|
|
|
|
|
|
die "internal inconsistency - fh already exists in fhmap!"; |
328
|
|
|
|
|
|
|
} |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
# FIXME does $path need to be relative or absolute? |
331
|
0
|
|
|
|
|
|
$self->{'fhmap'}->{ $mapping } = $path; |
332
|
0
|
|
|
|
|
|
$callback->( $fh ); |
333
|
|
|
|
|
|
|
} else { |
334
|
|
|
|
|
|
|
# must be an error code |
335
|
0
|
|
|
|
|
|
$callback->( $fh ); |
336
|
|
|
|
|
|
|
} |
337
|
|
|
|
|
|
|
} else { |
338
|
0
|
|
|
|
|
|
$callback->( -EIO() ); |
339
|
|
|
|
|
|
|
} |
340
|
0
|
|
|
|
|
|
}; |
341
|
|
|
|
|
|
|
|
342
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
343
|
0
|
|
|
|
|
|
$mount->open( $where, $flags, $mode, $cb ); |
344
|
|
|
|
|
|
|
|
345
|
0
|
|
|
|
|
|
return; |
346
|
|
|
|
|
|
|
} |
347
|
|
|
|
|
|
|
|
348
|
|
|
|
|
|
|
sub close { |
349
|
0
|
|
|
0
|
1
|
|
my( $self, $fh, $callback ) = @_; |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
# get the proper mount |
352
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
353
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
354
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
355
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( delete $self->{'fhmap'}->{ $mapping } ); |
356
|
|
|
|
|
|
|
|
357
|
0
|
|
|
|
|
|
$mount->close( $fh, $callback ); |
358
|
|
|
|
|
|
|
} else { |
359
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
360
|
|
|
|
|
|
|
} |
361
|
|
|
|
|
|
|
} else { |
362
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
363
|
|
|
|
|
|
|
} |
364
|
|
|
|
|
|
|
|
365
|
0
|
|
|
|
|
|
return; |
366
|
|
|
|
|
|
|
} |
367
|
|
|
|
|
|
|
|
368
|
|
|
|
|
|
|
sub read { |
369
|
|
|
|
|
|
|
# have to leave @_ alone so aio_read will get proper $buffer reference :( |
370
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
371
|
0
|
|
|
|
|
|
my $fh = shift; |
372
|
|
|
|
|
|
|
|
373
|
|
|
|
|
|
|
# get the proper mount |
374
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
375
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
376
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
377
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
378
|
|
|
|
|
|
|
|
379
|
0
|
|
|
|
|
|
$mount->read( $fh, $_[0], $_[1], $_[2], $_[3], $_[4] ); |
380
|
|
|
|
|
|
|
} else { |
381
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
382
|
|
|
|
|
|
|
} |
383
|
|
|
|
|
|
|
} else { |
384
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
385
|
|
|
|
|
|
|
} |
386
|
|
|
|
|
|
|
|
387
|
0
|
|
|
|
|
|
return; |
388
|
|
|
|
|
|
|
} |
389
|
|
|
|
|
|
|
|
390
|
|
|
|
|
|
|
sub write { |
391
|
|
|
|
|
|
|
# have to leave @_ alone so aio_read will get proper $buffer reference :( |
392
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
393
|
0
|
|
|
|
|
|
my $fh = shift; |
394
|
|
|
|
|
|
|
|
395
|
|
|
|
|
|
|
# get the proper mount |
396
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
397
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
398
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
399
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
400
|
|
|
|
|
|
|
|
401
|
0
|
|
|
|
|
|
$mount->write( $fh, $_[0], $_[1], $_[2], $_[3], $_[4] ); |
402
|
|
|
|
|
|
|
} else { |
403
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
404
|
|
|
|
|
|
|
} |
405
|
|
|
|
|
|
|
} else { |
406
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
407
|
|
|
|
|
|
|
} |
408
|
|
|
|
|
|
|
|
409
|
0
|
|
|
|
|
|
return; |
410
|
|
|
|
|
|
|
} |
411
|
|
|
|
|
|
|
|
412
|
|
|
|
|
|
|
sub sendfile { |
413
|
0
|
|
|
0
|
1
|
|
my( $self, $out_fh, $in_fh, $in_offset, $length, $callback ) = @_; |
414
|
|
|
|
|
|
|
|
415
|
|
|
|
|
|
|
# FIXME make sure both fh's belong to the same mount? |
416
|
|
|
|
|
|
|
# also, which fh should we "select" from to determine mountpoint? I'm defaulting to $in_fh here... |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
# get the proper mount |
419
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $in_fh ); |
420
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
421
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
422
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
423
|
|
|
|
|
|
|
|
424
|
0
|
|
|
|
|
|
$mount->sendfile( $out_fh, $in_fh, $in_offset, $length, $callback ); |
425
|
|
|
|
|
|
|
} else { |
426
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $in_fh"; |
427
|
|
|
|
|
|
|
} |
428
|
|
|
|
|
|
|
} else { |
429
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $in_fh"; |
430
|
|
|
|
|
|
|
} |
431
|
|
|
|
|
|
|
|
432
|
0
|
|
|
|
|
|
return; |
433
|
|
|
|
|
|
|
} |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
sub readahead { |
436
|
0
|
|
|
0
|
1
|
|
my( $self, $fh, $offset, $length, $callback ) = @_; |
437
|
|
|
|
|
|
|
|
438
|
|
|
|
|
|
|
# get the proper mount |
439
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
440
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
441
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
442
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
443
|
|
|
|
|
|
|
|
444
|
0
|
|
|
|
|
|
$mount->readahead( $fh, $offset, $length, $callback ); |
445
|
|
|
|
|
|
|
} else { |
446
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
447
|
|
|
|
|
|
|
} |
448
|
|
|
|
|
|
|
} else { |
449
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
450
|
|
|
|
|
|
|
} |
451
|
|
|
|
|
|
|
|
452
|
0
|
|
|
|
|
|
return; |
453
|
|
|
|
|
|
|
} |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
sub stat { |
456
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $callback ) = @_; |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
# FIXME we don't support array mode because it would require insane amounts of munging the paths |
459
|
0
|
0
|
0
|
|
|
|
if ( ref $fh_or_path and ref( $fh_or_path ) eq 'ARRAY' ) { |
460
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
461
|
|
|
|
|
|
|
warn 'Passing an ARRAY to stat() is not supported by the Dispatcher!'; |
462
|
|
|
|
|
|
|
} |
463
|
0
|
|
|
|
|
|
$callback->( undef ); |
464
|
0
|
|
|
|
|
|
return; |
465
|
|
|
|
|
|
|
} |
466
|
|
|
|
|
|
|
|
467
|
|
|
|
|
|
|
# is it a fh or path? |
468
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
469
|
|
|
|
|
|
|
# get the proper mount |
470
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
471
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
472
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
473
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
474
|
0
|
|
|
|
|
|
$mount->stat( $fh_or_path, $callback ); |
475
|
|
|
|
|
|
|
} else { |
476
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
477
|
|
|
|
|
|
|
} |
478
|
|
|
|
|
|
|
} else { |
479
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
480
|
|
|
|
|
|
|
} |
481
|
|
|
|
|
|
|
} else { |
482
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
483
|
0
|
|
|
|
|
|
$mount->stat( $where, $callback ); |
484
|
|
|
|
|
|
|
} |
485
|
|
|
|
|
|
|
|
486
|
0
|
|
|
|
|
|
return; |
487
|
|
|
|
|
|
|
} |
488
|
|
|
|
|
|
|
|
489
|
|
|
|
|
|
|
sub lstat { |
490
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $callback ) = @_; |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
# FIXME we don't support array mode because it would require insane amounts of munging the paths |
493
|
0
|
0
|
0
|
|
|
|
if ( ref $fh_or_path and ref( $fh_or_path ) eq 'ARRAY' ) { |
494
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
495
|
|
|
|
|
|
|
warn 'Passing an ARRAY to lstat() is not supported by the Dispatcher!'; |
496
|
|
|
|
|
|
|
} |
497
|
0
|
|
|
|
|
|
$callback->( undef ); |
498
|
0
|
|
|
|
|
|
return; |
499
|
|
|
|
|
|
|
} |
500
|
|
|
|
|
|
|
|
501
|
|
|
|
|
|
|
# is it a fh or path? |
502
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
503
|
|
|
|
|
|
|
# get the proper mount |
504
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
505
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
506
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
507
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
508
|
0
|
|
|
|
|
|
$mount->lstat( $fh_or_path, $callback ); |
509
|
|
|
|
|
|
|
} else { |
510
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
511
|
|
|
|
|
|
|
} |
512
|
|
|
|
|
|
|
} else { |
513
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
514
|
|
|
|
|
|
|
} |
515
|
|
|
|
|
|
|
} else { |
516
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
517
|
0
|
|
|
|
|
|
$mount->lstat( $where, $callback ); |
518
|
|
|
|
|
|
|
} |
519
|
|
|
|
|
|
|
|
520
|
0
|
|
|
|
|
|
return; |
521
|
|
|
|
|
|
|
} |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
sub utime { |
524
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $atime, $mtime, $callback ) = @_; |
525
|
|
|
|
|
|
|
|
526
|
|
|
|
|
|
|
# is it a fh or path? |
527
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
528
|
|
|
|
|
|
|
# get the proper mount |
529
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
530
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
531
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
532
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
533
|
0
|
|
|
|
|
|
$mount->utime( $fh_or_path, $atime, $mtime, $callback ); |
534
|
|
|
|
|
|
|
} else { |
535
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
536
|
|
|
|
|
|
|
} |
537
|
|
|
|
|
|
|
} else { |
538
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
539
|
|
|
|
|
|
|
} |
540
|
|
|
|
|
|
|
} else { |
541
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
542
|
0
|
|
|
|
|
|
$mount->utime( $where, $atime, $mtime, $callback ); |
543
|
|
|
|
|
|
|
} |
544
|
|
|
|
|
|
|
|
545
|
0
|
|
|
|
|
|
return; |
546
|
|
|
|
|
|
|
} |
547
|
|
|
|
|
|
|
|
548
|
|
|
|
|
|
|
sub chown { |
549
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $uid, $gid, $callback ) = @_; |
550
|
|
|
|
|
|
|
|
551
|
|
|
|
|
|
|
# is it a fh or path? |
552
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
553
|
|
|
|
|
|
|
# get the proper mount |
554
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
555
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
556
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
557
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
558
|
0
|
|
|
|
|
|
$mount->chown( $fh_or_path, $uid, $gid, $callback ); |
559
|
|
|
|
|
|
|
} else { |
560
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
561
|
|
|
|
|
|
|
} |
562
|
|
|
|
|
|
|
} else { |
563
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
564
|
|
|
|
|
|
|
} |
565
|
|
|
|
|
|
|
} else { |
566
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
567
|
0
|
|
|
|
|
|
$mount->chown( $where, $uid, $gid, $callback ); |
568
|
|
|
|
|
|
|
} |
569
|
|
|
|
|
|
|
|
570
|
0
|
|
|
|
|
|
return; |
571
|
|
|
|
|
|
|
} |
572
|
|
|
|
|
|
|
|
573
|
|
|
|
|
|
|
sub truncate { |
574
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $offset, $callback ) = @_; |
575
|
|
|
|
|
|
|
|
576
|
|
|
|
|
|
|
# is it a fh or path? |
577
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
578
|
|
|
|
|
|
|
# get the proper mount |
579
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
580
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
581
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
582
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
583
|
0
|
|
|
|
|
|
$mount->truncate( $fh_or_path, $offset, $callback ); |
584
|
|
|
|
|
|
|
} else { |
585
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
586
|
|
|
|
|
|
|
} |
587
|
|
|
|
|
|
|
} else { |
588
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
589
|
|
|
|
|
|
|
} |
590
|
|
|
|
|
|
|
} else { |
591
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
592
|
0
|
|
|
|
|
|
$mount->truncate( $where, $offset, $callback ); |
593
|
|
|
|
|
|
|
} |
594
|
|
|
|
|
|
|
|
595
|
0
|
|
|
|
|
|
return; |
596
|
|
|
|
|
|
|
} |
597
|
|
|
|
|
|
|
|
598
|
|
|
|
|
|
|
sub chmod { |
599
|
0
|
|
|
0
|
1
|
|
my( $self, $fh_or_path, $mode, $callback ) = @_; |
600
|
|
|
|
|
|
|
|
601
|
|
|
|
|
|
|
# is it a fh or path? |
602
|
0
|
0
|
|
|
|
|
if ( ref $fh_or_path ) { |
603
|
|
|
|
|
|
|
# get the proper mount |
604
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh_or_path ); |
605
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
606
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
607
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
608
|
0
|
|
|
|
|
|
$mount->chmod( $fh_or_path, $mode, $callback ); |
609
|
|
|
|
|
|
|
} else { |
610
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
611
|
|
|
|
|
|
|
} |
612
|
|
|
|
|
|
|
} else { |
613
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh_or_path"; |
614
|
|
|
|
|
|
|
} |
615
|
|
|
|
|
|
|
} else { |
616
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $fh_or_path ); |
617
|
0
|
|
|
|
|
|
$mount->chmod( $where, $mode, $callback ); |
618
|
|
|
|
|
|
|
} |
619
|
|
|
|
|
|
|
|
620
|
0
|
|
|
|
|
|
return; |
621
|
|
|
|
|
|
|
} |
622
|
|
|
|
|
|
|
|
623
|
|
|
|
|
|
|
sub unlink { |
624
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $callback ) = @_; |
625
|
|
|
|
|
|
|
|
626
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
627
|
0
|
|
|
|
|
|
$mount->unlink( $where, $callback ); |
628
|
|
|
|
|
|
|
|
629
|
0
|
|
|
|
|
|
return; |
630
|
|
|
|
|
|
|
} |
631
|
|
|
|
|
|
|
|
632
|
|
|
|
|
|
|
sub mknod { |
633
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $mode, $dev, $callback ) = @_; |
634
|
|
|
|
|
|
|
|
635
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
636
|
0
|
|
|
|
|
|
$mount->mknod( $where, $mode, $dev, $callback ); |
637
|
|
|
|
|
|
|
|
638
|
0
|
|
|
|
|
|
return; |
639
|
|
|
|
|
|
|
} |
640
|
|
|
|
|
|
|
|
641
|
|
|
|
|
|
|
sub link { |
642
|
0
|
|
|
0
|
1
|
|
my( $self, $srcpath, $dstpath, $callback ) = @_; |
643
|
|
|
|
|
|
|
|
644
|
|
|
|
|
|
|
# we disallow links across mounts, because it's impossible to get arbitrary mounts to cooperate :( |
645
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $srcpath ); |
646
|
0
|
|
|
|
|
|
my( $mount2, $where2 ) = $self->_findmount( $dstpath ); |
647
|
0
|
0
|
|
|
|
|
if ( $mount != $mount2 ) { |
648
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
649
|
|
|
|
|
|
|
warn 'linking across mounts is not supported by the Dispatcher!'; |
650
|
|
|
|
|
|
|
} |
651
|
0
|
|
|
|
|
|
$callback->( -1 ); # FIXME what's the proper failure code? |
652
|
0
|
|
|
|
|
|
return; |
653
|
|
|
|
|
|
|
} |
654
|
|
|
|
|
|
|
|
655
|
0
|
|
|
|
|
|
$mount->link( $where, $where2, $callback ); |
656
|
|
|
|
|
|
|
|
657
|
0
|
|
|
|
|
|
return; |
658
|
|
|
|
|
|
|
} |
659
|
|
|
|
|
|
|
|
660
|
|
|
|
|
|
|
sub symlink { |
661
|
0
|
|
|
0
|
1
|
|
my( $self, $srcpath, $dstpath, $callback ) = @_; |
662
|
|
|
|
|
|
|
|
663
|
|
|
|
|
|
|
# we disallow links across mounts, because it's impossible to get arbitrary mounts to cooperate :( |
664
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $srcpath ); |
665
|
0
|
|
|
|
|
|
my( $mount2, $where2 ) = $self->_findmount( $dstpath ); |
666
|
0
|
0
|
|
|
|
|
if ( $mount != $mount2 ) { |
667
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
668
|
|
|
|
|
|
|
warn 'linking across mounts is not supported by the Dispatcher!'; |
669
|
|
|
|
|
|
|
} |
670
|
0
|
|
|
|
|
|
$callback->( -1 ); # FIXME what's the proper failure code? |
671
|
0
|
|
|
|
|
|
return; |
672
|
|
|
|
|
|
|
} |
673
|
|
|
|
|
|
|
|
674
|
0
|
|
|
|
|
|
$mount->symlink( $where, $where2, $callback ); |
675
|
|
|
|
|
|
|
|
676
|
0
|
|
|
|
|
|
return; |
677
|
|
|
|
|
|
|
} |
678
|
|
|
|
|
|
|
|
679
|
|
|
|
|
|
|
sub readlink { |
680
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $callback ) = @_; |
681
|
|
|
|
|
|
|
|
682
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
683
|
0
|
|
|
|
|
|
$mount->readlink( $where, $callback ); |
684
|
|
|
|
|
|
|
|
685
|
0
|
|
|
|
|
|
return; |
686
|
|
|
|
|
|
|
} |
687
|
|
|
|
|
|
|
|
688
|
|
|
|
|
|
|
sub rename { |
689
|
0
|
|
|
0
|
1
|
|
my( $self, $srcpath, $dstpath, $callback ) = @_; |
690
|
|
|
|
|
|
|
|
691
|
|
|
|
|
|
|
# FIXME we theoretically could rename across mounts by implementing it ourself, but I'm lazy now :) |
692
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $srcpath ); |
693
|
0
|
|
|
|
|
|
my( $mount2, $where2 ) = $self->_findmount( $dstpath ); |
694
|
0
|
0
|
|
|
|
|
if ( $mount != $mount2 ) { |
695
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
696
|
|
|
|
|
|
|
warn 'renaming across mounts is not supported by the Dispatcher!'; |
697
|
|
|
|
|
|
|
} |
698
|
0
|
|
|
|
|
|
$callback->( -1 ); # FIXME what's the proper failure code? |
699
|
0
|
|
|
|
|
|
return; |
700
|
|
|
|
|
|
|
} |
701
|
|
|
|
|
|
|
|
702
|
0
|
|
|
|
|
|
$mount->rename( $where, $where2, $callback ); |
703
|
|
|
|
|
|
|
|
704
|
0
|
|
|
|
|
|
return; |
705
|
|
|
|
|
|
|
} |
706
|
|
|
|
|
|
|
|
707
|
|
|
|
|
|
|
sub mkdir { |
708
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $mode, $callback ) = @_; |
709
|
|
|
|
|
|
|
|
710
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
711
|
0
|
|
|
|
|
|
$mount->mkdir( $where, $mode, $callback ); |
712
|
|
|
|
|
|
|
|
713
|
0
|
|
|
|
|
|
return; |
714
|
|
|
|
|
|
|
} |
715
|
|
|
|
|
|
|
|
716
|
|
|
|
|
|
|
sub rmdir { |
717
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $callback ) = @_; |
718
|
|
|
|
|
|
|
|
719
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
720
|
0
|
|
|
|
|
|
$mount->rmdir( $where, $callback ); |
721
|
|
|
|
|
|
|
|
722
|
0
|
|
|
|
|
|
return; |
723
|
|
|
|
|
|
|
} |
724
|
|
|
|
|
|
|
|
725
|
|
|
|
|
|
|
sub readdir { |
726
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $callback ) = @_; |
727
|
|
|
|
|
|
|
|
728
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
729
|
0
|
|
|
|
|
|
$mount->readdir( $where, $callback ); |
730
|
|
|
|
|
|
|
|
731
|
0
|
|
|
|
|
|
return; |
732
|
|
|
|
|
|
|
} |
733
|
|
|
|
|
|
|
|
734
|
|
|
|
|
|
|
sub load { |
735
|
|
|
|
|
|
|
# have to leave @_ alone so caller will get proper $data reference :( |
736
|
0
|
|
|
0
|
1
|
|
my $self = shift; |
737
|
0
|
|
|
|
|
|
my $path = shift; |
738
|
|
|
|
|
|
|
|
739
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
740
|
0
|
|
|
|
|
|
$mount->load( $where, $_[0], $_[1] ); |
741
|
|
|
|
|
|
|
|
742
|
0
|
|
|
|
|
|
return; |
743
|
|
|
|
|
|
|
} |
744
|
|
|
|
|
|
|
|
745
|
|
|
|
|
|
|
sub copy { |
746
|
0
|
|
|
0
|
1
|
|
my( $self, $srcpath, $dstpath, $callback ) = @_; |
747
|
|
|
|
|
|
|
|
748
|
|
|
|
|
|
|
# FIXME we theoretically could copy across mounts by implementing it ourself, but I'm lazy now :) |
749
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $srcpath ); |
750
|
0
|
|
|
|
|
|
my( $mount2, $where2 ) = $self->_findmount( $dstpath ); |
751
|
0
|
0
|
|
|
|
|
if ( $mount != $mount2 ) { |
752
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
753
|
|
|
|
|
|
|
warn 'copying across mounts is not supported by the Dispatcher!'; |
754
|
|
|
|
|
|
|
} |
755
|
0
|
|
|
|
|
|
$callback->( 0 ); |
756
|
0
|
|
|
|
|
|
return; |
757
|
|
|
|
|
|
|
} |
758
|
|
|
|
|
|
|
|
759
|
0
|
|
|
|
|
|
$mount->copy( $where, $where2, $callback ); |
760
|
|
|
|
|
|
|
|
761
|
0
|
|
|
|
|
|
return; |
762
|
|
|
|
|
|
|
} |
763
|
|
|
|
|
|
|
|
764
|
|
|
|
|
|
|
sub move { |
765
|
0
|
|
|
0
|
1
|
|
my( $self, $srcpath, $dstpath, $callback ) = @_; |
766
|
|
|
|
|
|
|
|
767
|
|
|
|
|
|
|
# FIXME we theoretically could move across mounts by implementing it ourself, but I'm lazy now :) |
768
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $srcpath ); |
769
|
0
|
|
|
|
|
|
my( $mount2, $where2 ) = $self->_findmount( $dstpath ); |
770
|
0
|
0
|
|
|
|
|
if ( $mount != $mount2 ) { |
771
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
772
|
|
|
|
|
|
|
warn 'moving across mounts is not supported by the Dispatcher!'; |
773
|
|
|
|
|
|
|
} |
774
|
0
|
|
|
|
|
|
$callback->( -1 ); # FIXME what's the proper failure code? |
775
|
0
|
|
|
|
|
|
return; |
776
|
|
|
|
|
|
|
} |
777
|
|
|
|
|
|
|
|
778
|
0
|
|
|
|
|
|
$mount->move( $where, $where2, $callback ); |
779
|
|
|
|
|
|
|
|
780
|
0
|
|
|
|
|
|
return; |
781
|
|
|
|
|
|
|
} |
782
|
|
|
|
|
|
|
|
783
|
|
|
|
|
|
|
sub scandir { |
784
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $maxreq, $callback ) = @_; |
785
|
|
|
|
|
|
|
|
786
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
787
|
0
|
|
|
|
|
|
$mount->scandir( $where, $maxreq, $callback ); |
788
|
|
|
|
|
|
|
|
789
|
0
|
|
|
|
|
|
return; |
790
|
|
|
|
|
|
|
} |
791
|
|
|
|
|
|
|
|
792
|
|
|
|
|
|
|
sub rmtree { |
793
|
0
|
|
|
0
|
1
|
|
my( $self, $path, $callback ) = @_; |
794
|
|
|
|
|
|
|
|
795
|
0
|
|
|
|
|
|
my( $mount, $where ) = $self->_findmount( $path ); |
796
|
|
|
|
|
|
|
|
797
|
|
|
|
|
|
|
# we disallow rmtree if there's a mount under the path ( because of complications ) |
798
|
0
|
|
|
|
|
|
my $matches = grep { $_ =~ /^$path.+/ } ( keys %{ $self->{'mounts'} } ); |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
799
|
0
|
0
|
|
|
|
|
if ( $matches ) { |
800
|
0
|
|
|
|
|
|
if ( DEBUG ) { |
801
|
|
|
|
|
|
|
warn 'rmtree across mounts is not supported by the Dispatcher!'; |
802
|
|
|
|
|
|
|
} |
803
|
0
|
|
|
|
|
|
$callback->( -1 ); # FIXME what's the proper failure code? |
804
|
|
|
|
|
|
|
} else { |
805
|
0
|
|
|
|
|
|
$mount->rmtree( $where, $callback ); |
806
|
|
|
|
|
|
|
} |
807
|
|
|
|
|
|
|
|
808
|
0
|
|
|
|
|
|
return; |
809
|
|
|
|
|
|
|
} |
810
|
|
|
|
|
|
|
|
811
|
|
|
|
|
|
|
sub fsync { |
812
|
0
|
|
|
0
|
1
|
|
my( $self, $fh, $callback ) = @_; |
813
|
|
|
|
|
|
|
|
814
|
|
|
|
|
|
|
# get the proper mount |
815
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
816
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
817
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
818
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
819
|
|
|
|
|
|
|
|
820
|
0
|
|
|
|
|
|
$mount->fsync( $fh, $callback ); |
821
|
|
|
|
|
|
|
} else { |
822
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
823
|
|
|
|
|
|
|
} |
824
|
|
|
|
|
|
|
} else { |
825
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
826
|
|
|
|
|
|
|
} |
827
|
|
|
|
|
|
|
|
828
|
0
|
|
|
|
|
|
return; |
829
|
|
|
|
|
|
|
} |
830
|
|
|
|
|
|
|
|
831
|
|
|
|
|
|
|
sub fdatasync { |
832
|
0
|
|
|
0
|
1
|
|
my( $self, $fh, $callback ) = @_; |
833
|
|
|
|
|
|
|
|
834
|
|
|
|
|
|
|
# get the proper mount |
835
|
0
|
|
|
|
|
|
my $mapping = $self->_resolve_fh( $fh ); |
836
|
0
|
0
|
|
|
|
|
if ( defined $mapping ) { |
837
|
0
|
0
|
|
|
|
|
if ( exists $self->{'fhmap'}->{ $mapping } ) { |
838
|
0
|
|
|
|
|
|
my( $mount, undef ) = $self->_findmount( $self->{'fhmap'}->{ $mapping } ); |
839
|
|
|
|
|
|
|
|
840
|
0
|
|
|
|
|
|
$mount->fdatasync( $fh, $callback ); |
841
|
|
|
|
|
|
|
} else { |
842
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
843
|
|
|
|
|
|
|
} |
844
|
|
|
|
|
|
|
} else { |
845
|
0
|
|
|
|
|
|
die "internal inconsistency - unknown fh: $fh"; |
846
|
|
|
|
|
|
|
} |
847
|
|
|
|
|
|
|
|
848
|
0
|
|
|
|
|
|
return; |
849
|
|
|
|
|
|
|
} |
850
|
|
|
|
|
|
|
|
851
|
|
|
|
|
|
|
1; |
852
|
|
|
|
|
|
|
__END__ |