| 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 |  | 49481 | use warnings; | 
|  | 2 |  |  |  |  | 6 |  | 
|  | 2 |  |  |  |  | 69 |  | 
| 10 | 2 |  |  | 2 |  | 10 | use strict; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 112 |  | 
| 11 |  |  |  |  |  |  |  | 
| 12 |  |  |  |  |  |  | =head1 NAME | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | Fuse::Class - Base clsas for Fuse module implementation using class. | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | =head1 VERSION | 
| 17 |  |  |  |  |  |  |  | 
| 18 |  |  |  |  |  |  | Version 0.02 | 
| 19 |  |  |  |  |  |  |  | 
| 20 |  |  |  |  |  |  | =cut | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | our $VERSION = '0.02'; | 
| 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 |  | 3480 | 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 |