| 75 | | : S_IFREG | 0644; |
| 76 | | |
| 77 | | return ( |
| 78 | | 0, 0, # $dev, $ino, |
| 79 | | $mode, |
| 80 | | 1, # $nlink, see fuse.sourceforge.net/wiki/index.php/FAQ |
| 81 | | $>, $) + 0, # $uid, $gid, |
| 82 | | 0, # $rdev, |
| 83 | | ref($file) ? 1 : length $file || 0, # $size, |
| 84 | | $self->{mounttime}, $self->{mounttime}, |
| 85 | | $self->{mounttime}, # actually $atime, $mtime, $ctime, |
| 86 | | 1024, 1, # $blksize, $blocks, |
| | 76 | : ref($file) eq '' ? S_IFREG | 0644 |
| | 77 | : S_IFREG | 0000; |
| | 78 | |
| | 79 | $mode = S_IFREG | 0200 unless defined $file; |
| | 80 | |
| | 81 | my $size = ref($file) ? 1 : defined($file) ? length($file) : 0; |
| | 82 | |
| | 83 | return( |
| | 84 | 0, 0, $mode, 1, $>, $)+0, 0, $size, $mtime, $mtime, $mtime, 1024, 1 |
| 102 | | |
| 103 | | my $file = $self->find($path); |
| 104 | | return -ENOSYS() unless defined $file; |
| 105 | | return -ENOENT() unless ref $file eq 'HASH'; |
| 106 | | |
| 107 | | (qw/. ../, sort( keys %$file ), 0); |
| | 117 | my $dir = $self->find($path); |
| | 118 | |
| | 119 | return -ENOENT() unless defined $dir; |
| | 120 | return -ENOENT() unless ref $dir eq 'HASH'; |
| | 121 | |
| | 122 | (qw/. ../, sort(keys %$dir), 0); |
| 111 | | my ($self, $path, $flags) = @_; |
| 112 | | |
| 113 | | my $file = $self->find($path); |
| 114 | | return -ENOSYS() unless defined $file; |
| 115 | | # return -EBADF() unless $flags & O_ACCMODE; |
| 116 | | |
| 117 | | if (ref($file) eq 'HASH') { |
| 118 | | return -EISDIR(); |
| 119 | | } |
| 120 | | else { |
| 121 | | return 0; |
| 122 | | } |
| | 126 | my ($self, $path, $mode) = @_; |
| | 127 | my $file = $self->find($path); |
| | 128 | |
| | 129 | # return -EBADF() unless defined($file) or ($mode & O_ACCMODE()); |
| | 130 | return ref $file eq 'HASH' ? -EISDIR() : ref $file eq '' ? 0 : -ENOSYS(); |
| 152 | | my $date; |
| 153 | | my $file = $self->{files}; |
| 154 | | |
| 155 | | my @p = grep { $_ } split '/', $path; |
| 156 | | while (my $p = shift @p) { |
| 157 | | if (@p) { |
| 158 | | $file = $file->{$p}; |
| 159 | | } |
| 160 | | else { |
| 161 | | my $len = length $file->{$p}; |
| 162 | | if ($offset > $len) { |
| 163 | | $file->{$p} .= "\0" x ($offset - $len); |
| | 157 | my $file = $self->find($path); |
| | 158 | return -ENOENT() unless defined $file; |
| | 159 | return -ENOSYS() unless ref $file eq ''; |
| | 160 | # return -ENOSYS() unless 書き込み権限ないとき |
| | 161 | |
| | 162 | $file = $self->{files}; |
| | 163 | my @path = grep {$_} split '/', $path; |
| | 164 | |
| | 165 | while (my $p = shift @path) { |
| | 166 | if (@path) { |
| | 167 | $file = $file->{$p}; |
| | 168 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 169 | } |
| | 170 | else { |
| | 171 | return -EINVAL() unless ref $file->{$p} eq ''; |
| | 172 | |
| | 173 | if ($offset > length($file->{$p})) { |
| | 174 | $file->{$p} .= "\0" x ($offset - length $file->{$p}); |
| 165 | | substr( $file->{$p}, $offset ) = $buf; |
| 166 | | } |
| 167 | | } |
| 168 | | |
| 169 | | length $buf; |
| 170 | | } |
| 171 | | |
| 172 | | sub fuse_mknod { |
| 173 | | my ($self, $path) = @_; |
| 174 | | |
| 175 | | my $file = $self->{files}; |
| 176 | | for my $p (split '/', $path) { |
| 177 | | next if $p eq ''; |
| 178 | | |
| 179 | | unless (exists $file->{$p}) { |
| 180 | | $file->{$p} = ''; |
| 181 | | return 0; |
| 182 | | } |
| 183 | | |
| 184 | | $file = $file->{$p}; |
| 185 | | } |
| 186 | | |
| 187 | | -EEXIST(); |
| 188 | | } |
| 189 | | |
| 190 | | sub fuse_mkdir { |
| 191 | | my ($self, $path) = @_; |
| 192 | | |
| 193 | | my $file = $self->{files}; |
| 194 | | for my $p (split '/', $path) { |
| 195 | | next if $p eq ''; |
| 196 | | |
| 197 | | unless (exists $file->{$p}) { |
| 198 | | $file->{$p} = {}; |
| 199 | | return 0; |
| 200 | | } |
| 201 | | |
| 202 | | $file = $file->{$p}; |
| 203 | | } |
| 204 | | |
| 205 | | -EEXIST(); |
| | 176 | substr($file->{$p}, $offset) = $buf; |
| | 177 | } |
| | 178 | } |
| | 179 | $self->attr($path => { mtime => time }); |
| | 180 | |
| | 181 | length($buf); |
| | 182 | } |
| | 183 | |
| | 184 | sub fuse_readlink { |
| | 185 | my ($self, $path) = @_; |
| | 186 | |
| | 187 | my $file = $self->find($path); |
| | 188 | return -EINVAL() unless ref $file eq 'SCALAR'; |
| | 189 | |
| | 190 | $$file; |
| 222 | | return 0; |
| 223 | | } |
| 224 | | } |
| 225 | | |
| 226 | | -ENOENT(); |
| 227 | | } |
| 228 | | |
| 229 | | sub fuse_rmdir { |
| 230 | | my ($self, $path) = @_; |
| 231 | | |
| 232 | | my $file = $self->{files}; |
| 233 | | my @p = grep { $_ } split '/', $path; |
| 234 | | while (my $p = shift @p) { |
| 235 | | if (@p) { |
| 236 | | $file = $file->{$p}; |
| 237 | | } |
| 238 | | else { |
| 239 | | delete $file->{$p}; |
| | 206 | delete $self->{attrs}{$path}; |
| | 207 | return 0; |
| | 208 | } |
| | 209 | } |
| | 210 | |
| | 211 | -ENOENT(); |
| | 212 | } |
| | 213 | |
| | 214 | sub fuse_symlink { |
| | 215 | my ($self, $target, $path) = @_; |
| | 216 | |
| | 217 | my $file = $self->{files}; |
| | 218 | my @path = grep {$_} split '/', $path; |
| | 219 | |
| | 220 | while (my $p = shift @path) { |
| | 221 | if (@path) { |
| | 222 | $file = $file->{$p}; |
| | 223 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 224 | } |
| | 225 | else { |
| | 226 | if (exists $file->{$p}) { |
| | 227 | return -EEXIST(); |
| | 228 | } |
| | 229 | else { |
| | 230 | $file->{$p} = \$target; |
| | 231 | return 0; |
| | 232 | } |
| | 233 | } |
| | 234 | } |
| | 235 | |
| | 236 | -ENOENT(); |
| | 237 | } |
| | 238 | |
| | 239 | sub fuse_rename { |
| | 240 | my ($self, $old, $new) = @_; |
| | 241 | |
| | 242 | return -EEXIST() if $self->find($new); |
| | 243 | |
| | 244 | my $file = $self->{files}; |
| | 245 | my @path = grep {$_} split '/', $new; |
| | 246 | |
| | 247 | while (my $p = shift @path) { |
| | 248 | if (@path) { |
| | 249 | $file = $file->{$p}; |
| | 250 | } |
| | 251 | else { |
| | 252 | delete $self->{attrs}{$old}; |
| | 253 | $old = delete $file->{$p}; |
| | 254 | } |
| | 255 | } |
| | 256 | |
| | 257 | $file = $self->{files}; |
| | 258 | @path = grep {$_} split '/', $new; |
| | 259 | |
| | 260 | while (my $p = shift @path) { |
| | 261 | if (@path) { |
| | 262 | $file = $file->{$p}; |
| | 263 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 264 | } |
| | 265 | else { |
| | 266 | $file->{$p} = $old; |
| 258 | | sub fuse_readlink { |
| 259 | | my ($self, $path) = @_; |
| 260 | | |
| 261 | | my $file = $self->find($path); |
| 262 | | return -ENOENT() unless defined $file; |
| 263 | | return -EINVAL() unless ref $file eq 'SCALAR'; |
| 264 | | |
| 265 | | $$file; |
| 266 | | } |
| 267 | | |
| 268 | | sub fuse_symlink { |
| 269 | | my ($self, $target, $path) = @_; |
| 270 | | |
| 271 | | my $file = $self->{files}; |
| 272 | | for my $p (split '/', $path) { |
| 273 | | next if $p eq ''; |
| 274 | | |
| 275 | | unless (exists $file->{$p}) { |
| 276 | | $file->{$p} = \$target; |
| 277 | | return 0; |
| 278 | | } |
| 279 | | |
| 280 | | $file = $file->{$p}; |
| 281 | | } |
| 282 | | |
| 283 | | -EEXIST(); |
| 284 | | } |
| 285 | | |
| 286 | | sub fuse_statfs { (255,1,1,1,1,2) } |
| | 290 | sub fuse_truncate { |
| | 291 | my ($self, $path, $offset) = @_; |
| | 292 | |
| | 293 | my $file = $self->{files}; |
| | 294 | my @path = grep {$_} split '/', $path; |
| | 295 | |
| | 296 | while (my $p = shift @path) { |
| | 297 | if (@path) { |
| | 298 | $file = $file->{$p}; |
| | 299 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 300 | } |
| | 301 | else { |
| | 302 | return -ENOENT() unless ref $file->{$p} eq ''; |
| | 303 | $file->{$p} = substr($file->{$p}, 0, $offset); |
| | 304 | return 0; |
| | 305 | } |
| | 306 | } |
| | 307 | |
| | 308 | -ENOSYS(); |
| | 309 | } |
| | 310 | |
| | 311 | sub fuse_utime { |
| | 312 | my ($self, $path, $atime, $mtime) = @_; |
| | 313 | |
| | 314 | $self->attr($path => { atime => $atime, mtime => $mtime }); |
| | 315 | |
| | 316 | 0; |
| | 317 | } |
| | 318 | |
| | 319 | sub fuse_mkdir { |
| | 320 | my ($self, $path, $mode) = @_; |
| | 321 | |
| | 322 | my $file = $self->{files}; |
| | 323 | my @path = grep {$_} split '/', $path; |
| | 324 | |
| | 325 | while (my $p = shift @path) { |
| | 326 | if (@path) { |
| | 327 | $file = $file->{$p}; |
| | 328 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 329 | } |
| | 330 | else { |
| | 331 | return -EEXIST() if defined $file->{$p}; |
| | 332 | |
| | 333 | $file->{$p} = {}; |
| | 334 | $self->attr( $path => { mode => S_IFDIR | $mode } ); |
| | 335 | return 0; |
| | 336 | } |
| | 337 | } |
| | 338 | |
| | 339 | -ENOENT(); |
| | 340 | } |
| | 341 | |
| | 342 | sub fuse_rmdir { |
| | 343 | my ($self, $path) = @_; |
| | 344 | |
| | 345 | my $file = $self->{files}; |
| | 346 | my @path = grep {$_} split '/', $path; |
| | 347 | |
| | 348 | while (my $p = shift @path) { |
| | 349 | if (@path) { |
| | 350 | $file = $file->{$p}; |
| | 351 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 352 | } |
| | 353 | else { |
| | 354 | delete $file->{$p}; |
| | 355 | delete $self->{attrs}{$path}; |
| | 356 | return 0; |
| | 357 | } |
| | 358 | } |
| | 359 | |
| | 360 | -ENOSYS(); |
| | 361 | } |
| | 362 | |
| | 363 | sub fuse_mknod { |
| | 364 | my ($self, $path) = @_; |
| | 365 | |
| | 366 | my $file = $self->{files}; |
| | 367 | my @path = grep {$_} split '/', $path; |
| | 368 | |
| | 369 | while (my $p = shift @path) { |
| | 370 | if (@path) { |
| | 371 | $file = $file->{$p}; |
| | 372 | return -ENOENT() unless defined $file and ref $file eq 'HASH'; |
| | 373 | } |
| | 374 | else { |
| | 375 | return -EEXIST() if defined $file->{$p}; |
| | 376 | $file->{$p} = ''; |
| | 377 | return 0; |
| | 378 | } |
| | 379 | } |
| | 380 | |
| | 381 | -ENOENT(); |
| | 382 | } |
| | 383 | |
| | 384 | sub fuse_statfs { 255, 1000000, 500000, 1000000, 500000, 4096 } |
| | 385 | |
| | 386 | sub fuse_release {0} |
| | 387 | |
| | 388 | sub fuse_flush {0} |