drop maxdepth to 10, spell TRACKS as ALLTRACKS
[id3fs.git] / lib / ID3FS / Fuse.pm
index 014706e..da46921 100644 (file)
@@ -2,9 +2,13 @@ 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);
+our $DEFAULT_MAXTAGDEPTH = 10;
 sub new
 {
     my $proto=shift;
@@ -14,7 +18,11 @@ sub new
 
     $self->{db}=shift;
     $self->{source}=shift;
-    $self->{mountpoint}=shift;
+    $self->{mountpoint}=Cwd::abs_path(shift);
+    $self->{verbose}=shift;
+    $self->{tagdepth}=shift;
+    $self->{tagdepth}=$DEFAULT_MAXTAGDEPTH unless($self->{tagdepth});
+    $self->{perms} = S_IRUSR() | S_IXUSR() | S_IRGRP() | S_IXGRP() | S_IROTH() | S_IXOTH();
 
     return $self;
 }
@@ -24,59 +32,112 @@ 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->{verbose} > 1),
+       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, $self->{verbose}, $self->{tagdepth});
+    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, $self->{verbose}, $self->{tagdepth});
+    return(-EINVAL()) unless($path->isfile());
+    return $path->dest($self->{mountpoint});
+}
 
+sub getdir
+{
+    my($self, $filename)=@_;
+#    print "**GETDIR: $filename\n";
+    my $path=ID3FS::Path->new($self->{db}, $filename, $self->{verbose}, $self->{tagdepth});
+    return(-ENOENT()) unless($path->isvalid());
+    return(-ENOTDIR()) unless($path->isdir());
+    my @dents=();
+    my($dirs, $files)=$path->dirents();
+    # too slow
+#    push(@dents, $path->filter(@$dirs));
+    push(@dents, @$dirs);
+    push(@dents, @$files);
+    if(@dents)
+    {
+       return( (".", "..", @dents, 0) );
+    }
+    return(0);
 }
 
-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(); }
+# 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;