Added support for 'nullpath_ok' option to fuse_main().
authorDerrik Pates <demon@now.ai>
Wed, 18 May 2011 15:53:28 +0000 (09:53 -0600)
committerDerrik Pates <demon@now.ai>
Wed, 18 May 2011 15:53:28 +0000 (09:53 -0600)
Fuse.pm
Fuse.xs

diff --git a/Fuse.pm b/Fuse.pm
index dbe77ba..0d7b474 100755 (executable)
--- a/Fuse.pm
+++ b/Fuse.pm
@@ -81,8 +81,14 @@ sub main {
        my @subs = map {undef} @names;
        my $tmp = 0;
        my %mapping = map { $_ => $tmp++ } @names;
-       my @otherargs = qw(debug threaded mountpoint mountopts);
-       my %otherargs = (debug=>0, threaded=>0, mountpoint=>"", mountopts=>"");
+       my @otherargs = qw(debug threaded mountpoint mountopts nullpath_ok);
+       my %otherargs = (
+                         debug         => 0,
+                         threaded      => 0,
+                         mountpoint    => "",
+                         mountopts     => "",
+                         nullpath_ok   => 0,
+                       );
        while(my $name = shift) {
                my ($subref) = shift;
                if(exists($otherargs{$name})) {
@@ -228,6 +234,19 @@ threads::shared.)
 
 =back
 
+nullpath_ok => boolean
+
+=over 1
+
+This flag tells Fuse to not pass paths for functions that operate on file
+or directory handles. This will yield empty path parameters for functions
+including read, write, flush, release, fsync, readdir, releasedir,
+fsyncdir, truncate, fgetattr and lock. If you use this, you must return
+file/directory handles from open, opendir and create. Default is 0 (off).
+Only effective on Fuse 2.8 and up; with earlier versions, this does nothing.
+
+=back
+
 =head3 Fuse::fuse_get_context
  
  use Fuse "fuse_get_context";
diff --git a/Fuse.xs b/Fuse.xs
index b235f17..38fa85d 100755 (executable)
--- a/Fuse.xs
+++ b/Fuse.xs
@@ -1074,7 +1074,7 @@ perl_fuse_main(...)
        struct fuse_chan *fc;
        dMY_CXT;
        INIT:
-       if(items != 4+N_CALLBACKS) {
+       if(items != N_CALLBACKS + 5) {
                fprintf(stderr,"Perl<->C inconsistency or internal error\n");
                XSRETURN_UNDEF;
        }
@@ -1096,11 +1096,20 @@ perl_fuse_main(...)
        }
        mountpoint = SvPV_nolen(ST(2));
        mountopts = SvPV_nolen(ST(3));
+#if FUSE_VERSION >= 28
+       fops.flag_nullpath_ok = SvIV(ST(4));
+#endif /* FUSE_VERSION >= 28 */
        for(i=0;i<N_CALLBACKS;i++) {
-               SV *var = ST(i+4);
+               SV *var = ST(i+5);
                /* allow symbolic references, or real code references. */
                if(SvOK(var) && (SvPOK(var) || (SvROK(var) && SvTYPE(SvRV(var)) == SVt_PVCV))) {
                        void **tmp1 = (void**)&_available_ops, **tmp2 = (void**)&fops;
+                       /* Dirty hack, to keep anything from overwriting the
+                        * flag area with a pointer. There should never be
+                        * anything passed as 'junk', but this prevents
+                        * someone from doing it and screwing things up... */
+                       if (i == 38)
+                               continue;
                        tmp2[i] = tmp1[i];
                        MY_CXT.callback[i] = var;
                } else if(SvOK(var)) {