X-Git-Url: http://erislabs.net/gitweb/?a=blobdiff_plain;f=lib%2FID3FS%2FFuse.pm;h=62dd3a8aa494368173f3ebd29c915353867c519b;hb=fb36f92d827b5e57b2d3238e41bf53f98d6b52b1;hp=014706e762fea1c9e7a91e0739384625877b71ae;hpb=ecd1b309450674842c673f2d779bbdd2a8d97171;p=id3fs.git diff --git a/lib/ID3FS/Fuse.pm b/lib/ID3FS/Fuse.pm index 014706e..62dd3a8 100644 --- a/lib/ID3FS/Fuse.pm +++ b/lib/ID3FS/Fuse.pm @@ -2,8 +2,11 @@ package ID3FS::Fuse; use strict; use warnings; -use POSIX qw(EINVAL ENOENT EROFS EOPNOTSUPP); +use ID3FS::Path; use Fuse; +use Cwd; +use POSIX qw(EINVAL EROFS ENOENT EOPNOTSUPP S_IRUSR S_IRGRP S_IROTH S_IXUSR S_IXGRP S_IXOTH); +our ($TYPE_DIR, $TYPE_SYMLINK)=(0040, 0120); sub new { @@ -14,7 +17,9 @@ sub new $self->{db}=shift; $self->{source}=shift; - $self->{mountpoint}=shift; + $self->{mountpoint}=Cwd::abs_path(shift); + $self->{debug}=shift; + $self->{perms} = S_IRUSR() | S_IXUSR() | S_IRGRP() | S_IXGRP() | S_IROTH() | S_IXOTH(); return $self; } @@ -24,59 +29,148 @@ sub run my($self)=@_; Fuse::main( mountpoint => $self->{mountpoint}, - getattr => "ID3FS::Fuse::getattr", - readlink => "ID3FS::Fuse::readlink", - getdir => "ID3FS::Fuse::getdir", - mknod => "ID3FS::Fuse::mknod", - mkdir => "ID3FS::Fuse::mkdir", - unlink => "ID3FS::Fuse::unlink", - rmdir => "ID3FS::Fuse::rmdir", - symlink => "ID3FS::Fuse::symlink", - rename => "ID3FS::Fuse::rename", - link => "ID3FS::Fuse::link", - chmod => "ID3FS::Fuse::chmod", - chown => "ID3FS::Fuse::chown", - truncate => "ID3FS::Fuse::truncate", - utime => "ID3FS::Fuse::utime", - open => "ID3FS::Fuse::open", - read => "ID3FS::Fuse::read", - write => "ID3FS::Fuse::write", - statfs => "ID3FS::Fuse::statfs", - release => "ID3FS::Fuse::release", - fsync => "ID3FS::Fuse::fsync", - setxattr => "ID3FS::Fuse::setxattr", - getxattr => "ID3FS::Fuse::getxattr", - listxattr => "ID3FS::Fuse::listxattr", - removexattr => "ID3FS::Fuse::removexattr", - threaded=>0, - debug => 1, + threaded => 0, + debug => $self->{debug}, + mountopts => "allow_other,ro", + getattr => sub { $self->getattr(@_); }, + readlink => sub { $self->readlink(@_); }, + getdir => sub { $self->getdir(@_); }, + + # Not used +# mknod => sub { $self->mknod(@_); }, +# mkdir => sub { $self->mkdir(@_); }, +# unlink => sub { $self->unlink(@_); }, +# rmdir => sub { $self->rmdir(@_); }, +# symlink => sub { $self->symlink(@_); }, +# rename => sub { $self->rename(@_); }, +# link => sub { $self->link(@_); }, +# chmod => sub { $self->chmod(@_); }, +# chown => sub { $self->chown(@_); }, +# truncate => sub { $self->truncate(@_); }, +# utime => sub { $self->utime(@_); }, +# open => sub { $self->open(@_); }, +# read => sub { $self->read(@_); }, +# write => sub { $self->write(@_); }, +# statfs => sub { $self->statfs(@_); }, +# release => sub { $self->release(@_); }, +# fsync => sub { $self->fsync(@_); }, +# setxattr => sub { $self->setxattr(@_); }, +# getxattr => sub { $self->getxattr(@_); }, +# listxattr => sub { $self->listxattr(@_); }, +# removexattr => sub { $self->removexattr(@_); }, ); +} + +sub getattr +{ + my($self, $filename)=@_; +# print "**GETATTR: $filename\n"; + my $path=ID3FS::Path->new($self->{db}, $filename); + my $last_update=$self->{db}->last_update(); + return(-ENOENT()) unless($path->isvalid()); + my($dev,$ino,$nlink)=(0,0,1); + my $uid=$<; + my $gid=(split(/ /, $( ))[0]; + my($rdev,$size)=(0,1); + my($atime,$mtime,$ctime)=($last_update) x 3; + my($blksize,$blocks)=(512,1); + my $mode=$self->mode( $path->isdir() ? $TYPE_DIR : $TYPE_SYMLINK ); + return($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size, + $atime, $mtime, $ctime, $blksize, $blocks); +} +sub readlink +{ + my($self,$filename)=@_; +# print "**READLINK: $filename\n"; + my $path=ID3FS::Path->new($self->{db}, $filename); + return(-EINVAL()) unless($path->isfile()); + return $path->dest($self->{mountpoint}); } -sub getattr { return -ENOENT(); } -sub readlink { return "FIXME"; } -sub getdir { return(0); } -sub mknod { return -EINVAL(); } -sub mkdir { return -EROFS(); } -sub unlink { return -EINVAL(); } -sub rmdir { return -EROFS(); } -sub symlink { return -EROFS(); } -sub rename { return -EROFS(); } -sub link { return -EROFS(); } -sub chmod { return -EINVAL(); } -sub chown { return -EINVAL(); } -sub truncate { return -EROFS(); } -sub utime { return -EINVAL(); } -sub open { return -EINVAL(); } -sub read { return -EINVAL(); } -sub write { return -EINVAL(); } -sub statfs { return -EINVAL(); } -sub release { return 0; } -sub fsync { return 0; } -sub setxattr { return -EOPNOTSUPP(); } -sub getxattr { return -EOPNOTSUPP(); } -sub listxattr { return -EOPNOTSUPP(); } -sub removexattr { return -EOPNOTSUPP(); } +sub getdir +{ + my($self, $filename)=@_; +# print "**GETDIR: $filename\n"; + my $path=ID3FS::Path->new($self->{db}, $filename); + return(-ENOENT()) unless($path->isvalid()); + return(-ENOTDIR()) unless($path->isdir()); + my @dents=(); + my($dirs, $files)=$path->dirents(); + push(@dents, $self->filter($filename, @$dirs)); + push(@dents, @$files); + if(@dents) + { + return( (".", "..", @dents, 0) ); + } + return(0); +} + +sub filter +{ + my($self, $base, @dirs)=@_; + my @outdirs=(); + for my $dir (@dirs) + { + print "hascontents: $base / $dir\n"; + my $path=ID3FS::Path->new($self->{db}, "$base/$dir"); + next unless($path->isvalid()); + my($subdirs,$subfiles)=$path->dirents(); + print "SUBDENTS: ", join(", ", @$subdirs, @$subfiles), "\n"; + next unless(@$subdirs || @$subfiles); + if(!@$subfiles || scalar(@$subdirs) < 3) + { + my $subdirents=0; + for my $subdir (@$subdirs) + { + if(grep { $_ eq $subdir; } qw(AND OR NOT)) + { + my $subsubpath=ID3FS::Path->new($self->{db}, "$base/$dir/$subdir"); + if($path->isvalid()) + { + my($subsubdirs,$subsubfiles)=$subsubpath->dirents(); + $subdirents++ if(@$subsubdirs || @$subsubfiles); + } + } + else + { + $subdirents++; + } + } + next unless($subdirents); + } + push(@outdirs, $dir); + } + return(@outdirs) +} + +# unused stubs +sub mknod { print "FUSE: mknod\n"; return -EROFS(); } +sub mkdir { print "FUSE: mkdir\n"; return -EROFS(); } +sub unlink { print "FUSE: unlink\n"; return -EROFS(); } +sub rmdir { print "FUSE: rmdir\n"; return -EROFS(); } +sub symlink { print "FUSE: symlink\n"; return -EROFS(); } +sub rename { print "FUSE: rename\n"; return -EROFS(); } +sub link { print "FUSE: link\n"; return -EROFS(); } +sub chmod { print "FUSE: chmod\n"; return -EROFS(); } +sub chown { print "FUSE: chown\n"; return -EROFS(); } +sub truncate { print "FUSE: truncate\n"; return -EROFS(); } +sub utime { print "FUSE: utime\n"; return -EINVAL(); } +sub open { print "FUSE: open\n"; return -EINVAL(); } +sub read { print "FUSE: read\n"; return -EINVAL(); } +sub write { print "FUSE: write\n"; return -EROFS(); } +sub statfs { print "FUSE: statfs\n"; return -EINVAL(); } +sub release { print "FUSE: release\n"; return 0; } +sub fsync { print "FUSE: fsync\n"; return 0; } +sub setxattr { print "FUSE: setxattr\n"; return -EOPNOTSUPP(); } +sub getxattr { print "FUSE: getxattr\n"; return -EOPNOTSUPP(); } +sub listxattr { print "FUSE: listxattr\n"; return -EOPNOTSUPP(); } +sub removexattr { print "FUSE: removexattr\n"; return -EOPNOTSUPP(); } + +sub mode +{ + my($self, $type)=@_; + return(($type << 9) | $self->{perms}); +} 1;