Fuse-Simple

 view release on metacpan or  search on metacpan

lib/Fuse/Simple.pm  view on Meta::CPAN


Includes:
fs_not_imp fs_flush fs_getattr fs_getdir fs_open fs_read
fs_readlink fs_release fs_statfs fs_truncate fs_write

=back

=begin testing

BEGIN { use_ok( 'Fuse::Simple', qw(:usual :debug :tools :filesys)); }

=end testing

=cut

######################################################################
# Some useful stuff
######################################################################

our $debug = 0; # can be set if you really really need it to be
my $ctime = time();
my $uid   = $>;
my $gid   = $) + 0;
our $fs    = {
    # "empty" dir by default
    "README" => "You forgot to pass a '/' parameter to Fuse::Simple::main!\n"
};

######################################################################

=head1 MAIN FUNCTION

=over

=item B<main>(B<arg> => I<value>, ...)

Mount your filesystem, and probably never return. Arguments are:

=over

=item B<mountpoint> => I<"/mnt">,

This is actually optional. If you don't supply a mountpoint, it'll
take it from @ARGV !

=item B<debug> => I<0|1>,

Debug Fuse::Simple. All filesystem calls, arguments, and return values
will be dumped, a bit like L<strace> for perl.

=item B<fuse_debug> => I<0|1>,

Debug FUSE itself. More low-level than B<debug>

=item B<threaded> => I<0|1>,

See L<Fuse>

=item B<"/"> => { hash for your root directory },

=item B<chmod> B<chown> B<flush> B<fsync> B<getattr> B<getdir> etc

See L<Fuse>

You can replace any of the low-level functions if you want, but if
you wanted to mess around with the dirty bits, you'd probably not be
using L<Fuse::Simple>, would you?

=item others

If I've forgotten any L<Fuse> args, you can supply them too.

=back

=back

=cut

sub main {
    # some default args
    my %args = (
	"mountpoint"  => $ARGV[0] || "",
	"debug"       => $debug,
	"fuse_debug"  => 0,
	"threaded"    => 0,
	"/"           => $fs,
    );
    # the default subs
    my %fs_subs = (
	"chmod"       => \&fs_not_imp,
	"chown"       => \&fs_not_imp,
	"flush"       => \&fs_flush,
	"fsync"       => \&fs_not_imp,
	"getattr"     => \&fs_getattr,
	"getdir"      => \&fs_getdir,
	"getxattr"    => \&fs_not_imp,
	"link"        => \&fs_not_imp,
	"listxattr"   => \&fs_not_imp,
	"mkdir"       => \&fs_not_imp,
	"mknod"       => \&fs_not_imp,
	"open"        => \&fs_open,
	"read"        => \&fs_read,
	"readlink"    => \&fs_readlink,
	"release"     => \&fs_release,
	"removexattr" => \&fs_not_imp,
	"rmdir"       => \&fs_not_imp,
	"rename"      => \&fs_not_imp,
	"setxattr"    => \&fs_not_imp,
	"statfs"      => \&fs_statfs,
	"symlink"     => \&fs_not_imp,
	"truncate"    => \&fs_truncate,
	"unlink"      => \&fs_not_imp,
	"utime"       => sub{return 0},
	"write"       => \&fs_write,
    );
    my $name;
    # copy across the arg supplied to main()
    while ($name = shift) {
	$args{$name} = shift;
    }
    # except extract these ones back out.
    $debug = delete $args{"debug"};
    $args{"debug"} = delete( $args{"fuse_debug"} ) || 0;
    $fs = delete $args{"/"};
    # add the functions, if not already defined.
    # wrap in debugger if debug is set.
    for $name (keys %fs_subs) {
	my $sub = $fs_subs{$name};
	$sub = wrap($sub, $name) if $debug;
	$args{$name} ||= $sub;
    }
    Fuse::main(%args);
}

=head1 UTIL FUNCTIONS

These might be useful for people writing their own filesystems

=over

=item B<fetch>(I<$path, @args>)   (not exported)

Given F</a/path/within/my/fs/foo>, return the F<foo> dir or file or
whatever. @args will be passed to the final coderef if supplied.

=begin testing

is(fetch("README"), $Fuse::Simple::fs->{README}, "fetch() test");

=end testing

lib/Fuse/Simple.pm  view on Meta::CPAN

      # we are to return the contents
    }
  }
  my $fs = {
    "magic" => \&mysub,
  };

Will be called like:

  cat /mnt/magic
    mysub();           # the file is being read
  echo "123" > /mnt/magic
    mysub("123\n", 0); # the file is being written
  : > /mnt/magic
    mysub("", 0);      # the file is being truncated

You can return a string, which is the contents of the file.

You can return an fserr() for an error.

You can return a hashref (your sub will look like a directory!)

You can return a scalar ref (your sub will look like a symlink), etc.

You can even return another coderef, which will be called with the same args.

If your program die()s, you'll return ESTALE "Stale file handle".

If you die(fserr(E2BIG)), you'll return that specified error.

If you die(nocache("An error message\n")) you'll actually not return
an error, but return a file containing that error message.

It would be rather disgusting to suggest that you could also
die { "README" => "Contents\n" } to return a directory, so I won't  :-)

Now... This isn't actually the whole story. An "ls" command will also
"read" your "file", because it needs to know the length. To avoid
calling your routines TOO often, the result will be cached on the
first C<getdir()> type operation, and then returned when you REALLY
read it. The cache will then be cleared so, for example:

  ls /mnt/             # mysub("");
  ls /mnt/magic        # return cached copy
  ls -Fal /mnt/magic   # return cached copy
  cat /mnt/magic       # return cached copy, but clear cache
  cat /mnt/magic       # mysub("");          and clear cache
  ls /mnt/magic        # mysub("");
  ls /mnt/magic        # return cached copy
  echo foo >/mnt/magic # mysub("foo",0);
  ls /mnt/magic        # mysub("");
  ls /mnt/magic        # return cached copy

=head1 EXAMPLES

  see L</SYNOPSIS>

=head1 NOTES

Most things apart from coderefs can't be written, and nothing can be
renamed, chown()ed, deleted, etc. This is not considered a bug, but I
reserve the right to add something clever in a later release :-)

=head1 BUGS

accessor() is a bit thick, doesn't handle seeks, multi-block writes,
etc.

Please report any bugs or feature requests to
E<lt>bug-fuse-simple at rt.cpan.orgE<gt>, or through the web interface at
L<http://rt.cpan.org/NoAuth/ReportBug.html?Queue=Fuse-Simple>.
I will be notified, and then you'll automatically be notified of progress on
your bug as I make changes.

=head1 SUPPORT

After installing, you can find documentation for this module with the
perldoc command.

    perldoc Fuse::Simple

You can also look for information at:

=over

=item * AnnoCPAN: Annotated CPAN documentation

L<http://annocpan.org/dist/Fuse-Simple>

=item * CPAN Ratings

L<http://cpanratings.perl.org/d/Fuse-Simple>

=item * RT: CPAN's request tracker

L<http://rt.cpan.org/NoAuth/Bugs.html?Dist=Fuse-Simple>

=item * Search CPAN

L<http://search.cpan.org/dist/Fuse-Simple>

=back

=head1 ACKNOWLEDGEMENTS

Many thanks to:
Mark Glines, for the Fuse Perl module upon which this is based.
Dobrica Pavlinusic, for maintaining it.
Miklos Szeredi et al for the underlying FUSE itself.

=head1 SEE ALSO

L<Fuse>, by Mark Glines, E<lt>mark@glines.orgE<gt>

The FUSE documentation at L<http://fuse.sourceforge.net/>

L<http://noseynick.org/>

=head1 AUTHOR

"Nosey" Nick Waterman of Nilex



( run in 0.805 second using v1.01-cache-2.11-cpan-71847e10f99 )