File Coverage

blib/lib/Fuse/Class.pm
Criterion Covered Total %
statement 7 9 77.7
branch n/a
condition n/a
subroutine 3 3 100.0
pod n/a
total 10 12 83.3


line stmt bran cond sub pod time code
1             #
2             # Fuse::Class
3             #
4             # For implementation using class.
5             #
6              
7             package Fuse::Class;
8              
9 2     2   88884 use warnings;
  2         4  
  2         53  
10 2     2   9 use strict;
  2         3  
  2         73  
11              
12             =head1 NAME
13              
14             Fuse::Class - Base clsas for Fuse module implementation using class.
15              
16             =head1 VERSION
17              
18             Version 0.03
19              
20             =cut
21              
22             our $VERSION = '0.03';
23              
24             =head1 SYNOPSIS
25              
26             Fuse::Class is just a abstract class. First, you must write subclass
27             overriding methods like named 'getattr'. (callbacks defined in Fuse)
28              
29             Subclass will be written like following:
30              
31             package SampleFS;
32              
33             use base qw(Fuse::Class);
34              
35             sub getattr {
36             my $self = shift; # instance or class is passed as first argment.
37             my ($fname) = @_; # same as Fuse.
38            
39             ...
40              
41             return @attr; # same as Fuse.
42             }
43             ...
44              
45             To mount your filesystem:
46              
47             use SampleFS;
48              
49             my $fuse = SampleFS->new("your", "parameters", "here");
50             $fuse->main(mountpoint => '/mnt/sample', mountopts => "allow_other");
51              
52             # control will be not returned until file system is unmouted...
53              
54             When file on your filesystem is opened, it will be seen that method
55             is called like this:
56              
57             $fuse->open($path_name, $flags, $file_info);
58              
59             =head1 DESCRIPTION
60              
61             This module supports writing Fuse callback as method.
62             Method name is same as Fuse callback, but first argment is an object (it's named '$self' usually).
63              
64             This is a small change for Fuse, but you can use power of OO like
65             inheritance, encapsulation, ...
66              
67             Exception handling:
68              
69             Returned value will be treated as negative errno in Fuse way, but you can
70             use exception, too.
71             If exception is thrown in your method ("die" is called), $! will be used
72             as errno to notify error to Fuse.
73              
74              
75             =head1 EXPORT
76              
77             Nothing.
78              
79             =head1 CONSTRUCTOR
80              
81             =cut
82              
83 2     2   823 use Fuse;
  0            
  0            
84             use Errno;
85              
86             # instance calling main
87             use vars qw($_Module);
88              
89             =head2 new
90              
91             Create a new instance. This method is defined just for your convenience.
92             Default implementation returns blessed empty HASHREF.
93              
94             =cut
95              
96             #
97             # for your convenience.
98             #
99             sub new {
100             my $class = shift;
101             bless {}, $class;
102             }
103              
104             my @callback;
105              
106             =head1 METHODS
107              
108             =cut
109              
110             =head2 main(OPT_KEY1 => OPT_VALUE1, OPT_KEY2 => OPT_VALUE2, ...)
111              
112             Start a main loop. Filesystem is mounted to the mountpoint pointed by
113             option "mountpoint".
114              
115             Options are taken as key=>value pair selected from following:
116              
117             =over
118              
119             =item debug => boolean
120              
121             This option controls tracing on or off. (Default is off).
122              
123             =item mountpoint => "path_to_mountpoint"
124              
125             Directory name to mount filesystem like "/mnt/mypoint".
126             This option has no default value and is mandatory.
127              
128             =item mountopts => "opt1,op2,..."
129              
130             Comma separated options for FUSE kernel module.
131              
132             =item nullpath_ok => boolean
133              
134             If true, empty pathname is passed to the methods like read, write, flush,
135             release, fsync, readdir, releasedir, fsyncdir, ftruncate, fgetattr and lock.
136              
137             To use this option, you must return file/directory handle from
138             open, opendir and create, and you must operate file/directory by
139             that handle insted of pathname.
140              
141             Only effective on Fuse 2.8 or later.
142              
143             =back
144              
145             For more information, see the documentation of Fuse.
146              
147             =cut
148              
149             sub main {
150             my $self = shift;
151             my %attr = @_;
152              
153             my @args;
154             for my $opt (qw(debug mountpoint mountopts nullpath_ok)) {
155             push(@args, $opt, $attr{$opt}) if (defined($attr{$opt}));
156             }
157              
158             local $_Module = $self;
159              
160             my %fnmap;
161             foreach my $fnname (@callback) {
162             if ($_Module->can($fnname)) {
163             $fnmap{$fnname} = __PACKAGE__ . '::_' . $fnname;
164             }
165             }
166              
167             Fuse::main(@args, %fnmap);
168             }
169              
170             BEGIN {
171             @callback = qw (getattr readlink getdir mknod mkdir unlink
172             rmdir symlink rename link chmod chown truncate
173             utime open read write statfs flush release fsync
174             setxattr getxattr listxattr removexattr);
175             if (Fuse->can('fuse_version')) {
176             my $fuse_version = Fuse::fuse_version();
177             if ($fuse_version >= 2.3) {
178             push(@callback, qw(opendir readdir releasedir fsyncdir init destroy));
179             }
180             if ($fuse_version >= 2.5) {
181             push(@callback, qw(access create ftruncate fgetattr));
182             }
183             if ($fuse_version >= 2.6) {
184             push(@callback, qw(lock utimens bmap));
185             }
186             }
187              
188             no strict "refs";
189             for my $m (@callback) {
190             my $method = __PACKAGE__ . "::_$m";
191              
192             *$method = sub {
193             my $method_name = $m;
194              
195             if ($_Module->can($method_name)) {
196             my @ret = eval {
197             $_Module->$m(@_);
198             };
199             if ($@) {
200             return $! ? -$! : -Errno::EPERM();
201             }
202             else {
203             return (wantarray() ? @ret : $ret[0]);
204             }
205             }
206             else {
207             return -Errno::EPERM();
208             }
209             }
210             }
211             }
212              
213             =head1 METHODS MAY BE OVERRIDDEN
214              
215             =cut
216              
217             =head2 getattr(PATH_NAME)
218              
219             Return a list of file attributes. Meaning of fields are same as
220             "stat" function like this:
221              
222             ($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
223             $atime,$mtime,$ctime,$blksize,$blocks)
224              
225             On error, return scalar value like -ENOENT().
226              
227             =head2 readlink(PATH_NAME)
228              
229             This method is called to dereference symbolic link.
230             Return a destination path string or numeric error value.
231              
232             By Default implementation, returns -ENOENT().
233             You can leave this method if your FS does not have symlink.
234              
235             =cut
236              
237             sub readlink {
238             return -Errno::ENOENT();
239             }
240              
241             =head2 getdir(DIRECTORY_NAME)
242              
243             Return a list of file/directory names and an errno (0 if success).
244             ex: ('..', '.', 'a', 'b', 0)
245              
246             If 'readdir' method is implemented, this function will never be called.
247              
248             =head2 mknod(PATH_NAME, MODE, DEVNO)
249              
250             Return an errno (0 if success).
251             This method is called to create an entity (device or file).
252              
253             =head2 mkdir(DIRECTORY_NAME, MODE)
254              
255             Return an errno (0 if success).
256             This method is called to create a directory.
257              
258             =head2 unlink(PATH_NAME)
259              
260             Return an errno (0 if success).
261             This method is called to remove an entity (device, file or symlink).
262              
263             =head2 rmdir(PATH_NAME)
264              
265             Return an errno (0 if success).
266             This method is called to remove a directory.
267              
268             =head2 symlink(EXISTING_PATH_NAME, SYMLINK_NAME)
269              
270             Return an errno (0 if success).
271             This method is called to create a symbolic link.
272              
273             =head2 rename(OLD_NAME, NEW_NAME)
274              
275             Return an errno (0 if success).
276             This method is called to rename/move a entity.
277              
278             =head2 link(EXISTING_PATH_NAME, HADLINK_NAME)
279              
280             Return an errno (0 if success).
281             This method is called to create a hard link.
282              
283             =head2 chmod(PATH_NAME, MODE).
284              
285             Return an errno (0 if success).
286             This method is called to change permissions on a entity.
287              
288             =head2 chown(PATH_NAME, UID, GID).
289              
290             Return an errno (0 if success).
291             This method is called to change ownership of a entity.
292              
293             =head2 truncate(PATH_NAME, OFFSET).
294              
295             Return an errno (0 if success).
296             This method is called to truncate a file at the given offset.
297              
298             =head2 utime(PATH_NAME, ACCESS_TIME, MODIFIED_TIME).
299              
300             Return an errno (0 if success).
301             This method is called to change atime/mtime on a entity.
302              
303             =head2 open(PATH_NAME, FLAGS, FILE_INFO)
304              
305             Return an errno, and a file handle (optional)
306              
307             First style means like this:
308              
309             return 0; # success
310              
311             and second one is following:
312              
313             return (0, $file_handle_you_made); # success and handle
314              
315             FLAGS is an OR-combined value of flags (O_RDONLY, O_SYNC, etc).
316             FILE_INFO is a hashref.
317              
318             Returned file handle will be passed to subsequent method call
319             to operate on opend file.
320              
321             =head2 read(PATH_NAME, SIZE, OFFSET, FILE_HANDLE)
322              
323             Return an errno, or string scalar of read data.
324              
325             This method is called to read data (SIZE bytes)
326             at the given offset of opened file.
327              
328             =head2 write(PATH_NAME, BUFFER, OFFSET, FILE_HANDLE)
329              
330             Return a written byte size or an errno.
331              
332             This method is called to write data (BUFFER)
333             at the given offset of opened file.
334              
335             =head2 statfs
336              
337             Return status of filesystem in one of follwing style:
338              
339             =over
340              
341             =item -ENOANO()
342              
343             or
344              
345             =item $namelen, $files, $files_free, $blocks, $blocks_avail, $blocksize
346              
347             or
348              
349             =item -ENOANO(), $namelen, $files, $files_free, $blocks, $blocks_avail, $blocksize
350              
351             =back
352              
353             =cut
354              
355             sub statfs {
356             return -Errno::ENOANO();
357             }
358              
359             =head2 flush(PATH_NAME, FILE_HANDLE)
360              
361             Return an errno (0 if success).
362             This method is called to synchronize any cached data.
363              
364             =cut
365              
366             sub flush {
367             return 0;
368             }
369              
370             =head2 release(PATH_NAME, FLAGS, FILE_HANDLE)
371              
372             Return an errno (0 if success).
373              
374             FLAGS is a same value passed when 'open' is called.
375              
376             Called to indicate that there are no more references to the file and flags.
377              
378             =cut
379              
380             sub release {
381             return 0;
382             }
383              
384             =head2 fsync(PATH_NAME, DATA_SYNC, FILE_HANDLE)
385              
386             Return an errno (0 if success).
387              
388             Called to synchronize file contents.
389              
390             DATA_SYNC indicates 'user data only'. If DATA_SYNC is non-zero,
391             only the user data should be synchronized. Otherwise synchronize
392             user and meta data.
393              
394             =cut
395              
396             sub fsync {
397             return 0;
398             }
399              
400             =head2 setxattr(PATH_NAME, ATTR_NAME, ATTR_VALUE, FLAGS)
401              
402             FLAGS is OR-ed value of Fuse::XATTR_CREATE and Fuse::XATTR_REPLACE
403              
404             Return an errno (0 if success).
405              
406             This method is called to set extended attribute.
407              
408             -EOPNOTSUPP means that setting the attribute is rejected.
409              
410             If XATTR_CREATE is passed and the attribute already exists, return -EEXIST.
411              
412             If XATTR_REPLACE is passed and the attribute does not exist, return -ENOATTR.
413              
414             By default implementation, returns -EOPNOTSUPP.
415             You can leave this method if your FS does not have any extended attributes.
416              
417             =cut
418              
419             sub setxattr {
420             return -Errno::EOPNOTSUPP();
421             }
422              
423             =head2 getxattr(PATH_NAME, ATTR_NAME)
424              
425             Return attribute value or errno (0 if no value).
426              
427             This method is called to get extended attribute value.
428              
429             By default implementation, returns 0.
430             You can leave this method if your FS does not have any extended attributes.
431              
432             =cut
433              
434             sub getxattr {
435             return 0;
436             }
437              
438             =head2 listxattr(PATH_NAME)
439              
440             Return a list of attribute names and an errno (0 if success).
441             ex: ('attr1', 'attr2', 'attr3', 0)
442              
443             By default implementation, returns 0.
444             You can leave this method if your FS does not have any extended attributes.
445              
446             =cut
447              
448             sub listxattr {
449             return 0;
450             }
451              
452             =head2 removexattr(PATH_NAME, ATTR_NAME)
453              
454             Return an errno (0 if success).
455              
456             This method is called to remove an attribute from entity.
457              
458             By default implementation, returns 0.
459             You can leave this method if your FS does not have any extended attributes.
460              
461             =cut
462              
463             sub removexattr {
464             return 0;
465             }
466              
467             =head2 opendir(DIRECTORY_NAME)
468              
469             Return an errno, and a directory handle (optional).
470              
471             This method is called to open a directory for reading.
472             If special handling is required to open a directory, this method
473             can be implemented.
474              
475             Supported by Fuse version 2.3 or later.
476              
477             =cut
478              
479             # sub opendir {
480             # return -Errno::EOPNOTSUPP();
481             # }
482              
483             =head2 readdir(DIRECTORY_NAME, OFFSET, HANDLE)
484              
485             (HANDLE is optional. see opendir)
486              
487             Return list consists of entries and an errno. Most simple style is
488             same as getdir(). ex: ('..', '.', 'a', 'b', 0)
489              
490             Entry can be array ref containing offset and attributes in following way:
491              
492             ([1, '..'], [2, '.'], [3, 'a'], [4, 'b', ], 0)
493              
494             or
495             ([1, '..', [array_like_getattr]], [2, '.', [array_like_getattr]], 0)
496              
497              
498             Supported by Fuse version 2.3 or later.
499              
500             =cut
501              
502             # sub readdir {
503             # return -Errno::EOPNOTSUPP();
504             # }
505              
506             =head2 releasedir(DIRECTORY_NAME, HANDLE)
507              
508             (HANDLE is optional. see opendir)
509              
510             Return an errno (0 if success).
511              
512             Called to indicate that there are no more references to the opened directory.
513              
514             Supported by Fuse version 2.3 or later.
515              
516             =cut
517              
518             =head2 fsyncdir(DIRECTORY_NAME, FLAGS, HANDLE)
519              
520             (HANDLE is optional. see opendir)
521              
522             Return an errno (0 if success).
523             This method is called to synchronize user data (FLAG is non-zero value)
524             or user data and meta data in directory.
525              
526             Supported by Fuse version 2.3 or later.
527              
528             =cut
529              
530             =head2 init
531              
532             You can return scalar. It can be accessed using fuse_get_context().
533              
534             Supported by Fuse version 2.3 or later.
535              
536             =cut
537              
538             =head2 destroy(SCALAR_VALUE)
539              
540             (SCALAR_VALUE is returned value by init method)
541              
542             Supported by Fuse version 2.3 or later.
543              
544             =cut
545              
546             =head2 access(PATH_NAME, ACCESS_MODE_FLAG)
547              
548             Return an errno (0 if success).
549              
550             This method is called to determine if user can access the file.
551             For more information, see Fuse document and manual for access(2).
552              
553             Supported by Fuse version 2.5 or later.
554              
555             =cut
556              
557             =head2 create(PATH_NAME, MASK, MODE)
558              
559             Return an errno, and a file handle (optional)
560              
561             This method is called to create a file with MASK (like mknod)
562             and open it with MODE atomically.
563             If this method is not implemented, mknod() and open() will be used.
564              
565             Supported by Fuse version 2.5 or later.
566              
567             =cut
568              
569             =head2 ftruncate(PATH_NAME, OFFSET, FILE_HANDLE)
570              
571             (HANDLE is optional. see open)
572              
573             Return an errno (0 if success).
574             This method is called to truncate an opened file at the given offset.
575              
576             Supported by Fuse version 2.5 or later.
577              
578             =cut
579              
580             =head2 fgetattr(PATH_NAME, FILE_HANDLE)
581              
582             (HANDLE is optional. see open)
583              
584             Return a list of file attributes like getattr().
585             This method is called to get attributes for opened file.
586              
587             Supported by Fuse version 2.5 or later.
588              
589             =cut
590              
591             =head2 lock(PATH_NAME, COMMAND_CODE, LOCK_PARAMS, FILE_HANDLE)
592              
593             (HANDLE is optional. see open)
594              
595             Return an errno (0 if success).
596              
597             This method is called to lock or unlock regions of file. Parameters
598             for locking is passed in LOCK_PARAMS as hashref.
599              
600             For more information, see the documentation of Fuse.
601              
602             Supported by Fuse version 2.6 or later.
603              
604             =cut
605              
606             =head2 utimens(PATH_NAME, ACCESS_TIME, MODIFIED_TIME)
607              
608             Return an errno (0 if success).
609             This method is called to change atime/mtime on a entity.
610             (Time has a resolution in nanosecond.)
611              
612             Supported by Fuse version 2.6 or later.
613              
614             =cut
615              
616             =head2 bmap(PATH_NAME, BLOCK_SIZE, BLOCK_NUMBER)
617              
618             Return 0 and physical block numeber on success, otherwise errno.
619              
620             This method is called to get physical block offset on block device.
621              
622             For more information, see the documentation of Fuse.
623              
624             Supported by Fuse version 2.6 or later.
625              
626             =cut
627              
628             =head1 AUTHOR
629              
630             Toshimitsu FUJIWARA, C<< >>
631              
632             =head1 BUGS
633              
634             Threading is not tested.
635              
636             =head1 COPYRIGHT & LICENSE
637              
638             Copyright 2008-2011 Toshimitsu FUJIWARA, all rights reserved.
639              
640             This program is free software; you can redistribute it and/or modify it
641             under the same terms as Perl itself.
642              
643             =head1 SEE ALSO
644              
645             Fuse
646              
647             =cut
648              
649             1; # End of xxx