Merge branch 'rt-55953-readdir' into master
authorDaniel Frett <daniel.frett@ccci.org>
Fri, 25 Feb 2011 05:04:25 +0000 (00:04 -0500)
committerDaniel Frett <daniel.frett@ccci.org>
Fri, 25 Feb 2011 05:07:28 +0000 (00:07 -0500)
Conflicts:
AUTHORS
Fuse.xs

1  2 
AUTHORS
Fuse.pm
Fuse.xs

diff --cc AUTHORS
+++ b/AUTHORS
@@@ -9,8 -9,4 +9,9 @@@ Csaba Henk <csaba.henk@creo.hu> - updat
  Vladimir V. Kolpakov <w@sfgate.com> - contributed cleanup for warnings
  Andrew Chadwick <andrewc@cpan.org> - fixes for Ubuntu and dh-make-perl (fakeroot)
  Chris Dolan <cdolan@cpan.org> - fixes for MacFuse 1.1.0
 +Reuben Thomas <rrt@sc3d.org> - contributed examples/filter_attr_fs.pl
 +jaslong from CPAN::Forum - documentation patch for fuse_get_context
 +Justin Fletcher <gerph@gerph.org> - added file handles on open files
 +Derrik Pates <demon@now.ai> - added 64-bit support and fuse 2.6 binding
 +Daniel Frett <daniel.frett@ccci.org> - make static callbacks thread-safe
+ Alex Sudakov <cygakob@gmail.com> - fixes for readdir support
diff --cc Fuse.pm
index 8530154,255bb69..436d998
mode 100755,100644..100755
+++ b/Fuse.pm
@@@ -77,10 -77,12 +77,10 @@@ bootstrap Fuse $VERSION
  sub main {
        my @names = qw(getattr readlink getdir mknod mkdir unlink rmdir symlink
                        rename link chmod chown truncate utime open read write statfs
-                       flush release fsync setxattr getxattr listxattr removexattr);
+                       flush release fsync setxattr getxattr listxattr removexattr opendir readdir releasedir fsyncdir);
        my @subs = map {undef} @names;
 -      my @validOpts = qw(ro allow_other default_permissions fsname use_ino nonempty);
        my $tmp = 0;
        my %mapping = map { $_ => $tmp++ } @names;
 -      my %optmap  = map { $_ => 1 } @validOpts;
        my @otherargs = qw(debug threaded mountpoint mountopts);
        my %otherargs = (debug=>0, threaded=>0, mountpoint=>"", mountopts=>"");
        while(my $name = shift) {
diff --cc Fuse.xs
index 9b6e4b5,92b9510..04c9543
mode 100755,100644..100755
+++ b/Fuse.xs
@@@ -3,60 -2,32 +3,60 @@@
  #include "perl.h"
  #include "XSUB.h"
  
 +#include <fuse.h>
 +
 +/* Determine if threads support should be included */
  #ifdef USE_ITHREADS
  # ifdef I_PTHREAD
 -/* perl implements threads with pthread.  So, we use the pthread API for
 - * handling thread-local storage. */
 -#  include <pthread.h>
 -PerlInterpreter *master_interp = NULL;
 -static inline void create_perl_context() {
 -      if(master_interp) {
 -              PerlInterpreter *me = PERL_GET_CONTEXT;
 -              if(!me) {
 -                      PERL_SET_CONTEXT(master_interp);
 -                      me = perl_clone(master_interp, CLONEf_CLONE_HOST);
 -              }
 -      }
 -}
 -#  define FUSE_CONTEXT_PRE create_perl_context(); { dSP
 -#  define FUSE_CONTEXT_POST }
  #  define FUSE_USE_ITHREADS
  # else
 -#  error "Sorry, I don't know how to handle ithreads on this architecture."
 +#  warning "Sorry, I don't know how to handle ithreads on this architecture. Building non-threaded version"
  # endif
- #define N_CALLBACKS 25
 +#endif
 +
 +/* Global Data */
 +
 +#define MY_CXT_KEY "Fuse::_guts" XS_VERSION
++#define N_CALLBACKS 29
 +
 +typedef struct {
 +      SV *callback[N_CALLBACKS];
 +      HV *handles;
 +      tTHX self;
 +      int threaded;
 +      perl_mutex mutex;
 +} my_cxt_t;
 +START_MY_CXT;
 +
 +#ifdef FUSE_USE_ITHREADS
 +tTHX master_interp = NULL;
 +
 +#define CLONE_INTERP(parent) S_clone_interp(parent)
 +tTHX S_clone_interp(tTHX parent) {
 +      dMY_CXT_INTERP(parent);
 +      if(MY_CXT.threaded) {
 +              MUTEX_LOCK(&MY_CXT.mutex);
 +              PERL_SET_CONTEXT(parent);
 +              dTHX;
 +#if (PERL_VERSION > 10) || (PERL_VERSION == 10 && PERL_SUBVERSION >= 1)
 +              tTHX child = perl_clone(parent, CLONEf_CLONE_HOST);
 +#else
 +              tTHX child = perl_clone(parent, CLONEf_CLONE_HOST | CLONEf_KEEP_PTR_TABLE);
 +              ptr_table_free(PL_ptr_table);
 +              PL_ptr_table = NULL;
 +#endif
 +              MUTEX_UNLOCK(&MY_CXT.mutex);
 +              return child;
 +      }
 +      return NULL;
 +}
 +
 +# define FUSE_CONTEXT_PRE dTHX; if(!aTHX) aTHX = CLONE_INTERP(master_interp); { dMY_CXT; dSP;
 +# define FUSE_CONTEXT_POST }
  #else
 -# define FUSE_CONTEXT_PRE dSP
 +# define FUSE_CONTEXT_PRE dTHX; dMY_CXT; dSP;
  # define FUSE_CONTEXT_POST
  #endif
 -#include <fuse.h>
  
  #undef DEBUGf
  #if 0
@@@ -180,13 -115,47 +180,47 @@@ int _PLfuse_readlink(const char *file,c
        return rv;
  }
  
- #if 0
- /*
-  * This doesn't yet work... we alwas get ENOSYS when trying to use readdir().
-  * Well, of course, getdir() is fine as well.
-  */
-  int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, off_t off, struct fuse_file_info *fi) {
- #endif
+ int _PLfuse_opendir(const char *file, struct fuse_file_info *info) {
+     croak("opendir NOT IMPLEMENTED");
+ }
+ int _PLfuse_releasedir(const char *file, struct fuse_file_info *info) {
+     croak("releasedir NOT IMPLEMENTED");
+ }
+ int _PLfuse_fsyncdir(const char *file, struct fuse_file_info *info) {
+     croak("fsyncdir NOT IMPLEMENTED");
+ }
+ int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, off_t off, struct fuse_file_info *fi) {
+       int prv, rv, offset;
+     SV *entry;
+       FUSE_CONTEXT_PRE;
+       DEBUGf("readdir begin\n");
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSViv(off)));
+       PUTBACK;
 -      prv = call_sv(_PLfuse_callbacks[26],G_ARRAY);
++      prv = call_sv(MY_CXT.callback[26],G_ARRAY);
+       SPAGAIN;
+       if(3 == prv) {
+         rv      = POPi;
+         offset  = POPi;
+         entry   = POPs;
+         if(SvOK(entry))
+             dirfil(dirh,SvPV_nolen(entry),NULL,offset);
+       } else {
+               fprintf(stderr,"readdir() handler didn't return 2 values!\n");
+               rv = -ENOSYS;
+       }
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("readdir end: %i\n",rv);
+       FUSE_CONTEXT_POST;
+       return rv;
+ }
  int _PLfuse_getdir(const char *file, fuse_dirh_t dirh, fuse_dirfil_t dirfil) {
        int prv, rv;
        FUSE_CONTEXT_PRE;
@@@ -1021,16 -871,14 +1056,16 @@@ perl_fuse_main(...
        PREINIT:
        struct fuse_operations fops = 
                {NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,
-                NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
+                NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL};
 -      int i, fd, debug, threaded;
 +      int i, debug;
        char *mountpoint;
        char *mountopts;
        struct fuse_args margs = FUSE_ARGS_INIT(0, NULL);
        struct fuse_args fargs = FUSE_ARGS_INIT(0, NULL);
 +      struct fuse_chan *fc;
 +      dMY_CXT;
        INIT:
-       if(items != 29) {
+       if(items != 4+N_CALLBACKS) {
                fprintf(stderr,"Perl<->C inconsistency or internal error\n");
                XSRETURN_UNDEF;
        }