Add support for operations supported by FUSE 2.2.1 (flush, release, fsync, extended...
authorRichard Dawe <rich@phekda.gotadsl.co.uk>
Sun, 10 Apr 2005 13:30:11 +0000 (13:30 +0000)
committerRichard Dawe <rich@phekda.gotadsl.co.uk>
Sun, 10 Apr 2005 13:30:11 +0000 (13:30 +0000)
git-svn-id: svn+ssh://llin/home/dpavlin/private/svn/fuse/perl/trunk@14 6e4b0b00-1209-0410-87b2-b275959b5705

Changes
Fuse.pm
Fuse.xs
META.yml

diff --git a/Changes b/Changes
index 28f6ee8..01ac089 100644 (file)
--- a/Changes
+++ b/Changes
@@ -15,3 +15,6 @@ Revision history for Perl extension Fuse.
     - new maintainer, Dobrica Pavlinusic <dpavlin@rot13.org>
     - updated to work with current CVS version of fuse
 
+0.06 Sun Apr 03 16:15:00 BST 2005
+    - Add support for operations supported by FUSE 2.2.1
+      (flush, release, fsync, extended attributes)
diff --git a/Fuse.pm b/Fuse.pm
index e7bf1e0..0173468 100644 (file)
--- a/Fuse.pm
+++ b/Fuse.pm
@@ -19,16 +19,18 @@ our @ISA = qw(Exporter DynaLoader);
 # This allows declaration      use Fuse ':all';
 # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
 # will save memory.
-our %EXPORT_TAGS = ( 'all' => [ qw(
-       FUSE_DEBUG
-) ] );
+our %EXPORT_TAGS = (
+                   'all' => [ qw(FUSE_DEBUG XATTR_CREATE XATTR_REPLACE) ],
+                   'debug' => [ qw(FUSE_DEBUG) ],
+                   'xattr' => [ qw(XATTR_CREATE XATTR_REPLACE) ]
+                   );
 
 our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
 
 our @EXPORT = qw(
        FUSE_DEBUG
 );
-our $VERSION = '0.05';
+our $VERSION = '0.06';
 
 sub AUTOLOAD {
     # This AUTOLOAD is used to 'autoload' constants from the constant()
@@ -62,12 +64,23 @@ sub AUTOLOAD {
     goto &$AUTOLOAD;
 }
 
+sub XATTR_CREATE {
+    # See <sys/xattr.h>.
+    return 1;
+}
+
+sub XATTR_REPLACE {
+    # See <sys/xattr.h>.
+    return 2;
+}
+
 bootstrap Fuse $VERSION;
 
 sub main {
-       my (@subs) = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+       my (@subs) = (0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
        my (@names) = qw(getattr readlink getdir mknod mkdir unlink rmdir symlink
-                        rename link chmod chown truncate utime open read write statfs);
+                        rename link chmod chown truncate utime open read write statfs
+                        flush release fsync setxattr getxattr listxattr removexattr);
        my ($tmp) = 0;
        my (%mapping) = map { $_ => $tmp++ } (@names);
        my (%otherargs) = (debug=>0, mountpoint=>"");
@@ -122,13 +135,17 @@ Every constant you need (file types, open() flags, error values,
 etc) can be imported either from POSIX or from Fcntl, often both.
 See their respective documentations, for more information.
 
-=head2 EXPORT
+=head2 EXPORTED SYMBOLS
+
+FUSE_DEBUG by default.
 
-None by default.
+You can request all exportable symbols by using the tag ":all".
 
-=head2 EXPORTABLE CONSTANTS
+You can request all debug symbols by using the tag ":debug".
+This will export FUSE_DEBUG.
 
-None.
+You can request the extended attribute symbols by using the tag ":xattr".
+This will export XATTR_CREATE and XATTR_REPLACE.
 
 =head2 FUNCTIONS
 
@@ -349,6 +366,70 @@ or
 
 -ENOANO(), $namelen, $files, $files_free, $blocks, $blocks_avail, $blocksize
 
+=head3 flush
+
+Arguments: Pathname
+Returns an errno or 0 on success.
+
+Called to synchronise any cached data. This is called before the file
+is closed. It may be called multiple times before a file is closed.
+
+=head3 release
+
+Arguments: Pathname, numeric flags passed to open
+Returns an errno or 0 on success.
+
+Called to indicate that there are no more references to the file. Called once
+for every file with the same pathname and flags as were passed to open.
+
+=head3 fsync
+
+Arguments: Pathname, numeric flags
+Returns an errno or 0 on success.
+
+Called to synchronise the file's contents. If flags is non-zero,
+only synchronise the user data. Otherwise synchronise the user and meta data.
+
+=head3 setxattr
+
+Arguments: Pathname, extended attribute's name, extended attribute's value, numeric flags (which is an OR-ing of XATTR_CREATE and XATTR_REPLACE 
+Returns an errno or 0 on success.
+
+Called to set the value of the named extended attribute.
+
+If you wish to reject setting of a particular form of extended attribute name
+(e.g.: regexps matching user\..* or security\..*), then return - EOPNOTSUPP.
+
+If flags is set to XATTR_CREATE and the extended attribute already exists,
+this should fail with - EEXIST. If flags is set to XATTR_REPLACE
+and the extended attribute doesn't exist, this should fail with - ENOATTR.
+
+XATTR_CREATE and XATTR_REPLACE are provided by this module, but not exported
+by default. To import them:
+
+    use Fuse ':xattr';
+
+or:
+
+    use Fuse ':all';
+
+=head3 getxattr
+
+Arguments: Pathname, extended attribute's name
+Returns an errno, 0 if there was no value, or the extended attribute's value.
+
+Called to get the value of the named extended attribute.
+
+=head3 listxattr
+
+Arguments: Pathname
+Returns a list: 0 or more text strings (the extended attribute names), followed by a numeric errno (usually 0).
+
+=head3 removexattr
+
+Arguments: Pathname, extended attribute's name
+Returns an errno or 0 on success.
+
 =head1 AUTHOR
 
 Mark Glines, E<lt>mark@glines.orgE<gt>
diff --git a/Fuse.xs b/Fuse.xs
index adc63b7..9ead042 100644 (file)
--- a/Fuse.xs
+++ b/Fuse.xs
@@ -11,7 +11,8 @@
 #define DEBUGf(a...)
 #endif
 
-SV *_PLfuse_callbacks[18];
+#define N_CALLBACKS 25
+SV *_PLfuse_callbacks[N_CALLBACKS];
 
 int _PLfuse_getattr(const char *file, struct stat *result) {
        dSP;
@@ -510,25 +511,261 @@ int _PLfuse_statfs (const char *file, struct statfs *st) {
        return rv;
 }
 
+int _PLfuse_flush (const char *file) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("flush begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[18],G_SCALAR);
+       SPAGAIN;
+       if(rv)
+               rv = POPi;
+       else
+               rv = 0;
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("flush end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_release (const char *file, int flags) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("release begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSViv(flags)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[19],G_SCALAR);
+       SPAGAIN;
+       if(rv)
+               rv = POPi;
+       else
+               rv = 0;
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("release end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_fsync (const char *file, int flags) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("fsync begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSViv(flags)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[20],G_SCALAR);
+       SPAGAIN;
+       if(rv)
+               rv = POPi;
+       else
+               rv = 0;
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("fsync end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_t buflen, int flags) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("setxattr begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSVpv(name,0)));
+       XPUSHs(sv_2mortal(newSVpvn(buf,buflen)));
+       XPUSHs(sv_2mortal(newSViv(flags)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[21],G_SCALAR);
+       SPAGAIN;
+       if(rv)
+               rv = POPi;
+       else
+               rv = 0;
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("setxattr end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_getxattr (const char *file, const char *name, char *buf, size_t buflen) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("getxattr begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSVpv(name,0)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[22],G_SCALAR);
+       SPAGAIN;
+       if(!rv)
+               rv = -ENOENT;
+       else {
+               SV *mysv = POPs;
+
+               rv = 0;
+               if(SvTYPE(mysv) == SVt_NV || SvTYPE(mysv) == SVt_IV)
+                       rv = SvIV(mysv);
+               else {
+                       if(SvPOK(mysv)) {
+                               rv = SvCUR(mysv);
+                       } else {
+                               rv = 0;
+                       }
+                       if ((rv > 0) && (buflen > 0))
+                       {
+                               if(rv > buflen)
+                                       rv = -ERANGE;
+                               else
+                                       memcpy(buf,SvPV_nolen(mysv),rv);
+                       }
+               }
+       }
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("getxattr end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_listxattr (const char *file, char *list, size_t size) {
+       int prv, rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("listxattr begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       PUTBACK;
+       prv = call_sv(_PLfuse_callbacks[23],G_ARRAY);
+       SPAGAIN;
+       if(!prv)
+               rv = -ENOENT;
+       else {
+
+               char *p = list;
+               int spc = size;
+               int total_len = 0;
+               int i;
+
+               rv = POPi;
+               prv--;
+
+               /* Always nul terminate */
+               if (list && (size > 0))
+                       list[0] = '\0';
+
+               while (prv > 0)
+               {
+                       SV *mysv = POPs;
+                       prv--;
+
+                       if (SvPOK(mysv)) {
+                               /* Copy nul too */
+                               int s = SvCUR(mysv) + 1;
+                               total_len += s;
+
+                               if (p && (size > 0) && (spc >= s))
+                               {
+                                       memcpy(p,SvPV_nolen(mysv),s);
+                                       p += s;
+                                       spc -= s;
+                               }
+                       }
+               }
+
+               /*
+                * If the Perl returned an error, return that.
+                * Otherwise check that the buffer was big enough.
+                */
+               if (rv == 0)
+               {
+                       rv = total_len;
+                       if ((size > 0) && (size < total_len))
+                               rv = -ERANGE;
+               }
+       }
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("listxattr end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
+int _PLfuse_removexattr (const char *file, const char *name) {
+       int rv;
+       char *rvstr;
+       dSP;
+       DEBUGf("removexattr begin: %i\n",sp-PL_stack_base);
+       ENTER;
+       SAVETMPS;
+       PUSHMARK(SP);
+       XPUSHs(sv_2mortal(newSVpv(file,0)));
+       XPUSHs(sv_2mortal(newSVpv(name,0)));
+       PUTBACK;
+       rv = call_sv(_PLfuse_callbacks[24],G_SCALAR);
+       SPAGAIN;
+       if(rv)
+               rv = POPi;
+       else
+               rv = 0;
+       FREETMPS;
+       LEAVE;
+       PUTBACK;
+       DEBUGf("removexattr end: %i\n",sp-PL_stack_base);
+       return rv;
+}
+
 struct fuse_operations _available_ops = {
-getattr:       _PLfuse_getattr,
-                       _PLfuse_readlink,
-                       _PLfuse_getdir,
-                       _PLfuse_mknod,
-                       _PLfuse_mkdir,
-                       _PLfuse_unlink,
-                       _PLfuse_rmdir,
-                       _PLfuse_symlink,
-                       _PLfuse_rename,
-                       _PLfuse_link,
-                       _PLfuse_chmod,
-                       _PLfuse_chown,
-                       _PLfuse_truncate,
-                       _PLfuse_utime,
-                       _PLfuse_open,
-                       _PLfuse_read,
-                       _PLfuse_write,
-                       _PLfuse_statfs
+getattr:               _PLfuse_getattr,
+readlink:              _PLfuse_readlink,
+getdir:                        _PLfuse_getdir,
+mknod:                 _PLfuse_mknod,
+mkdir:                 _PLfuse_mkdir,
+unlink:                        _PLfuse_unlink,
+rmdir:                 _PLfuse_rmdir,
+symlink:               _PLfuse_symlink,
+rename:                        _PLfuse_rename,
+link:                  _PLfuse_link,
+chmod:                 _PLfuse_chmod,
+chown:                 _PLfuse_chown,
+truncate:              _PLfuse_truncate,
+utime:                 _PLfuse_utime,
+open:                  _PLfuse_open,
+read:                  _PLfuse_read,
+write:                 _PLfuse_write,
+statfs:                        _PLfuse_statfs,
+flush:                 _PLfuse_flush,
+release:               _PLfuse_release,
+fsync:                 _PLfuse_fsync,
+setxattr:              _PLfuse_setxattr,
+getxattr:              _PLfuse_getxattr,
+listxattr:             _PLfuse_listxattr,
+removexattr:           _PLfuse_removexattr,
 };
 
 MODULE = Fuse          PACKAGE = Fuse
@@ -537,13 +774,13 @@ PROTOTYPES: DISABLE
 void
 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};
+       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};
        int i, fd, varnum = 0, debug, have_mnt;
        char *mountpoint;
        STRLEN n_a;
        STRLEN l;
        INIT:
-       if(items != 20) {
+       if(items != 27) {
                fprintf(stderr,"Perl<->C inconsistency or internal error\n");
                XSRETURN_UNDEF;
        }
@@ -551,7 +788,7 @@ perl_fuse_main(...)
        debug = SvIV(ST(0));
        mountpoint = SvPV_nolen(ST(1));
        /* FIXME: reevaluate multithreading support when perl6 arrives */
-       for(i=0;i<18;i++) {
+       for(i=0;i<N_CALLBACKS;i++) {
                SV *var = ST(i+2);
                if((var != &PL_sv_undef) && SvROK(var)) {
                        if(SvTYPE(SvRV(var)) == SVt_PVCV) {
index 0c643b9..7e01743 100644 (file)
--- a/META.yml
+++ b/META.yml
@@ -1,7 +1,7 @@
 # http://module-build.sourceforge.net/META-spec.html
 #XXXXXXX This is a prototype!!!  It will change in the future!!! XXXXX#
 name:         Fuse
-version:      0.05
+version:      0.06
 version_from: Fuse.pm
 installdirs:  site
 requires: