+# id3fs - a FUSE-based filesystem for browsing audio metadata
+# Copyright (C) 2010 Ian Beckwith <ianb@erislabs.net>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <http://www.gnu.org/licenses/>.
+
package ID3FS::Fuse;
use strict;
use warnings;
use ID3FS::Path;
use Fuse;
-use POSIX qw(EINVAL EROFS EOPNOTSUPP S_IRUSR S_IRGRP S_IROTH S_IXUSR S_IXGRP S_IXOTH);
-use vars qw($TYPE_DIR $TYPE_SYMLINK);
-($TYPE_DIR, $TYPE_SYMLINK)=(0040, 0120);
+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 = 6;
sub new
{
$self->{db}=shift;
$self->{source}=shift;
- $self->{mountpoint}=shift;
- $self->{debug}=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;
Fuse::main(
mountpoint => $self->{mountpoint},
threaded => 0,
- debug => $self->{debug},
+ 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(@_); },
+# 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";
+# 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)=(0,0,0);
+ my($atime,$mtime,$ctime)=($last_update) x 3;
my($blksize,$blocks)=(512,1);
-
- my $path=ID3FS::Path->new($self->{db}, $filename);
my $mode=$self->mode( $path->isdir() ? $TYPE_DIR : $TYPE_SYMLINK );
- return($dev,$ino,$mode,$nlink,$uid,$gid,$rdev,$size,
- $atime,$mtime,$ctime,$blksize,$blocks);
+ return($dev, $ino, $mode, $nlink, $uid, $gid, $rdev, $size,
+ $atime, $mtime, $ctime, $blksize, $blocks);
+}
+
+sub mode
+{
+ my($self, $type)=@_;
+ return(($type << 9) | $self->{perms});
}
sub readlink
{
my($self,$filename)=@_;
- print "READLINK: $filename\n";
- my $path=ID3FS::Path->new($self->{db}, $filename);
- return(-EINVAL()) if($path->isdir());
- return $path->dest();
+# 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);
- if($path->isdir())
+# 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();
+ push(@dents, @$dirs);
+ push(@dents, @$files);
+ if(@dents)
{
- return(".", "..", $path->dirents(), 0);
+ return( (".", "..", @dents, 0) );
}
- return -ENOTDIR();
+ return(0);
}
# unused stubs
-sub mknod { print "mknod\n"; return -EROFS(); }
-sub mkdir { print "mkdir\n"; return -EROFS(); }
-sub unlink { print "unlink\n"; return -EROFS(); }
-sub rmdir { print "rmdir\n"; return -EROFS(); }
-sub symlink { print "symlink\n"; return -EROFS(); }
-sub rename { print "rename\n"; return -EROFS(); }
-sub link { print "link\n"; return -EROFS(); }
-sub chmod { print "chmod\n"; return -EROFS(); }
-sub chown { print "chown\n"; return -EROFS(); }
-sub truncate { print "truncate\n"; return -EROFS(); }
-sub utime { print "utime\n"; return -EINVAL(); }
-sub open { print "open\n"; return -EINVAL(); }
-sub read { print "read\n"; return -EINVAL(); }
-sub write { print "write\n"; return -EROFS(); }
-sub statfs { print "statfs\n"; return -EINVAL(); }
-sub release { print "release\n"; return 0; }
-sub fsync { print "fsync\n"; return 0; }
-sub setxattr { print "setxattr\n"; return -EOPNOTSUPP(); }
-sub getxattr { print "getxattr\n"; return -EOPNOTSUPP(); }
-sub listxattr { print "listxattr\n"; return -EOPNOTSUPP(); }
-sub removexattr { print "removexattr\n"; return -EOPNOTSUPP(); }
-
-sub mode
-{
- my($self, $type)=@_;
- return(($type << 9) | $self->{perms});
-}
-
-
+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(); }
1;