File Coverage

blib/lib/Fuse/Filesys/Virtual.pm
Criterion Covered Total %
statement 12 12 100.0
branch n/a
condition n/a
subroutine 4 4 100.0
pod n/a
total 16 16 100.0


line stmt bran cond sub pod time code
1             #
2             # Fuse::Filesys::Virtual
3             #
4             # bridge of Fuse and Filesys::Virtual
5             #
6              
7             package Fuse::Filesys::Virtual;
8              
9 7     7   294970 use warnings;
  7         19  
  7         408  
10 7     7   45 use strict;
  7         47  
  7         445  
11              
12             =head1 NAME
13              
14             Fuse::Filesys::Virtual - mount Perl module written using Filesys::Virtual
15              
16             =head1 VERSION
17              
18             Version 0.02
19              
20             =cut
21              
22             our $VERSION = '0.02';
23              
24             =head1 SYNOPSIS
25              
26             use Fuse::Filesys::Virtual;
27              
28             my $fs = Filesys::Virtual::Foo->new();
29             my $fuse = Fuse::Filesys::Virtual->new($fs, { debug => 1});
30              
31             $fuse->main(mountpoint => '/mnt', mountopts => "allow_other");
32              
33             =head1 EXPORT
34              
35             Nothing.
36              
37             =cut
38              
39 7     7   3216 use POSIX qw(:errno_h :fcntl_h);
  7         29612  
  7         49  
40              
41 7     7   9976 use base qw(Fuse::Class);
  7         35  
  7         15086  
42              
43             use Fuse::Filesys::Virtual::FSWrapper;
44             use Fuse::Filesys::Virtual::HandleCache;
45              
46             =head1 FUNCTIONS
47              
48             =cut
49              
50             sub _debug {
51             my $self = shift;
52             my (@msg) = @_;
53              
54             local ($@, $!);
55             print STDERR __PACKAGE__, ": ", @msg if ($self->{debug});
56             }
57              
58             =head2 new (FS, ATTR_HASH_REF)
59              
60             Constructor. Takes FS and ATTR_HASH_REF as a parameter.
61              
62             FS - An instance of Virtual::Filesys
63             ATTR_HASH_REF - reference to attribute hash.
64              
65             Following key-value is recognized.
66              
67             debug : true or false
68              
69             =cut
70              
71             sub new {
72             my $class = shift;
73             my ($filesys, $attr) = @_;
74              
75             my $wrapped = Fuse::Filesys::Virtual::FSWrapper->new($filesys);
76             my $self = {
77             _filesys => $wrapped,
78             _cache => Fuse::Filesys::Virtual::HandleCache->new($wrapped),
79             debug => $attr->{debug},
80             };
81              
82             bless $self, $class;
83             }
84              
85             =head2 getattr
86              
87             Same as Fuse.
88              
89             =cut
90              
91             sub getattr {
92             my $self = shift;
93             my ($fname) = @_;
94              
95             my @ret = eval {
96             $self->{_filesys}->stat($fname);
97             };
98             if ($@) {
99             $self->_debug($@);
100             $! = EPERM if ($! == 0);
101             return -$!;
102             }
103             return @ret;
104             }
105              
106             =head2 readlink
107              
108             Always returns -EPERM.
109             This function is not supported by Virtual::Filesys.
110              
111             =cut
112              
113             sub readlink {
114             my $self = shift;
115             return -EPERM();
116             }
117              
118             =head2 getdir
119              
120             Same as Fuse.
121              
122             =cut
123              
124             sub getdir {
125             my $self = shift;
126             my ($dirname) = @_;
127              
128             my @ret = eval {
129             $self->{_filesys}->list($dirname);
130             };
131             if ($@) {
132             $self->_debug($@);
133             $! = EPERM if ($! == 0);
134             return -$!;
135             }
136              
137             push(@ret, 0);
138             return @ret;
139             }
140              
141             =head2 mknod
142              
143             Same as Fuse.
144              
145             =cut
146              
147             sub mknod {
148             my $self = shift;
149             my ($fname, $modes) = @_;
150              
151             eval {
152             if ($self->{_filesys}->stat($fname)) {
153             $! = EEXIST;
154             die "file exists";
155             }
156             else {
157             my $fh = $self->{_filesys}->open_write($fname, 0);
158             die "cannot create $fname: $!" unless($fh);
159             $self->{_filesys}->close_write($fh);
160             }
161             };
162             if ($@) {
163             $self->_debug($@);
164             $! = EPERM if ($! == 0);
165             return -$!;
166             }
167              
168             return 0;
169             }
170              
171             =head2 mkdir
172              
173             Same as Fuse.
174              
175             =cut
176              
177             sub mkdir {
178             my $self = shift;
179             my ($dirname, $modes) = @_;
180              
181             eval {
182             $self->{_filesys}->mkdir($dirname);
183             };
184             if ($@) {
185             $self->_debug($@);
186             $! = EPERM if ($! == 0);
187             return -$!;
188             }
189              
190             return 0;
191             }
192              
193             =head2 unlink
194              
195             Same as Fuse.
196              
197             =cut
198              
199             sub unlink {
200             my $self = shift;
201             my ($fname) = @_;
202              
203             my $busy = eval {
204             return -EBUSY() if ($self->{_cache}->is_busy($fname));
205             };
206             return $busy if ($busy);
207              
208             eval {
209             unless ($self->{_filesys}->delete($fname)) {
210             $! = EPERM;
211             die "failure";
212             }
213             };
214             if ($@) {
215             $self->_debug($@);
216             $! = EPERM if ($! == 0);
217             return -$!;
218             }
219              
220             return 0;
221             }
222              
223             =head2 rmdir
224              
225             Same as Fuse.
226              
227             =cut
228              
229             sub rmdir {
230             my $self = shift;
231             my ($dirname) = @_;
232              
233             my $busy = eval {
234             return -EBUSY() if ($self->{_cache}->is_busy($dirname));
235             };
236             return $busy if ($busy);
237              
238             eval {
239             $self->{_filesys}->rmdir($dirname);
240             };
241             if ($@) {
242             $self->_debug($@);
243             $! = EPERM if ($! == 0);
244             return -$!;
245             }
246              
247             return 0;
248             }
249              
250             =head2 symlink
251              
252             Always returns -EPERM.
253             This function is not supported by Virtual::Filesys.
254              
255             =cut
256              
257             sub symlink {
258             my $self = shift;
259             return -EPERM();
260             }
261              
262             =head2 rename
263              
264             Same as Fuse.
265             But his function is implemented by Copy & Delete.
266              
267             =cut
268              
269             sub rename {
270             my $self = shift;
271             my ($oldname, $newname) = @_;
272              
273             my $busy = eval {
274             return -EBUSY() if ($self->{_cache}->is_busy($oldname));
275             };
276             return $busy if ($busy);
277              
278             $busy = eval {
279             return -EBUSY() if (!$self->{_filesys}->test('d', $newname)
280             && $self->{_cache}->is_busy($newname));
281             };
282             return $busy if ($busy);
283              
284             eval {
285             $self->{_filesys}->rename($oldname, $newname)
286             or die "cannot rename: $!";
287             };
288             if ($@) {
289             $self->_debug($@);
290             $! = EPERM if ($! == 0);
291             return -$!;
292             }
293              
294             return 0;
295             }
296              
297             =head2 link
298              
299             Always returns -EPERM.
300             This function is not supported by Virtual::Filesys.
301              
302             =cut
303              
304             sub link {
305             my $self = shift;
306             return -EPERM();
307             }
308              
309             =head2 chmod
310              
311             Always returns 0(success), but nothing is done.
312             This function is not supported by Virtual::Filesys.
313              
314             =cut
315              
316             sub chmod {
317             my $self = shift;
318             return 0;
319             }
320              
321             =head2 chown
322              
323             Always returns -EPERM.
324             This function is not supported by Virtual::Filesys.
325              
326             =cut
327              
328             sub chown {
329             my $self = shift;
330             return -EPERM();
331             }
332              
333             =head2 truncate
334              
335             Always returns -EPERM.
336             This function is not supported by Virtual::Filesys.
337              
338             =cut
339              
340             sub truncate {
341             my $self = shift;
342             my ($fname) = @_;
343              
344             eval {
345             $self->{_cache}->truncate($fname);
346             };
347             if ($@) {
348             $self->_debug($@);
349             $! = EPERM if ($! == 0);
350             return -$!;
351             }
352              
353             return 0;
354             }
355              
356             =head2 utime
357              
358             Same as Fuse.
359              
360             =cut
361              
362             sub utime {
363             my $self = shift;
364             my ($fname, $atime, $mtime) = @_;
365              
366             eval {
367             $self->{_filesys}->utime($atime, $mtime, $fname);
368             };
369             if ($@) {
370             $self->_debug($@);
371             $! = EPERM if ($! == 0);
372             return -$!;
373             }
374              
375             return 0;
376             }
377              
378             =head2 open
379              
380             Same as Fuse.
381              
382             =cut
383              
384             sub open {
385             my $self = shift;
386             my ($fname, $flags) = @_;
387              
388             my $ret = eval {
389             if ($flags & O_RDONLY) {
390             return -ENOENT() if ($self->{_filesys}->test('f', $fname));
391             }
392              
393             # parent directory found?
394             my $dir = $fname;
395             $dir =~ s/\/[^\/]+$//;
396             if ($dir eq '' || $self->{_filesys}->test('d', $dir)) {
397             return 0;
398             }
399             else {
400             return -ENOENT();
401             }
402             };
403             if ($@) {
404             $self->_debug($@);
405             $! = EPERM if ($! == 0);
406             return -$!;
407             }
408              
409             return $ret;
410             }
411              
412             =head2 read
413              
414             Same as Fuse.
415              
416             =cut
417              
418             sub read {
419             my $self = shift;
420             my ($fname, $size, $offset) = @_;
421              
422             my $ret = eval {
423             $self->{_cache}->read($fname, $size, $offset);
424             };
425             if ($@) {
426             $self->_debug($@);
427             $! = EPERM if ($! == 0);
428             return -$!;
429             }
430              
431             return $ret;
432             };
433              
434             =head2 write
435              
436             Same as Fuse.
437              
438             =cut
439              
440             sub write {
441             my $self = shift;
442             my ($fname, $buf, $offset) = @_;
443              
444             my $ret = eval {
445             $self->{_cache}->write($fname, $buf, $offset);
446             };
447             if ($@) {
448             $self->_debug($@);
449             $! = EPERM if ($! == 0);
450             return -$!;
451             }
452              
453             # Fuse pod says we must return 'errno', but it does not work...
454             # return written size here.
455             return $ret;
456             }
457              
458             =head2 flush
459              
460             Always returns 0(no error).
461             This function is not supported by Virtual::Filesys.
462              
463             =cut
464              
465             sub flush {
466             my $self = shift;
467             my ($fname) = @_;
468              
469             return 0;
470             }
471              
472             =head2 release
473              
474             Same as Fuse.
475              
476             =cut
477              
478             sub release {
479             my $self = shift;
480             my ($fname) = @_;
481              
482             eval {
483             $self->{_cache}->release($fname);
484             };
485              
486             return 0;
487             }
488              
489             =head2 fsync
490              
491             Always returns 0(no error).
492             This function is not supported by Virtual::Filesys.
493              
494             =cut
495              
496             sub fsync {
497             my $self = shift;
498             my ($fname) = @_;
499              
500             eval {
501             $self->flush($fname);
502             };
503             if ($@) {
504             $self->_debug($@);
505             $! = EPERM if ($! == 0);
506             return $!;
507             }
508              
509             return 0;
510             }
511              
512              
513             =head1 AUTHOR
514              
515             Toshimitsu FUJIWARA, C<< >>
516              
517             =head1 BUGS
518              
519             Threading is not supported.
520              
521              
522             =head1 SUPPORT
523              
524             You can find documentation for this module with the perldoc command.
525              
526             perldoc Fuse::Filesys::Virtual
527              
528             =head1 ACKNOWLEDGEMENTS
529              
530              
531             =head1 COPYRIGHT & LICENSE
532              
533             Copyright 2008 Toshimitsu FUJIWARA, all rights reserved.
534              
535             This program is free software; you can redistribute it and/or modify it
536             under the same terms as Perl itself.
537              
538              
539             =cut
540              
541             1; # End of Fuse::Filesys::Virtual