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
{
$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;
}
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;