From: Richard Dawe Date: Sun, 10 Apr 2005 13:30:11 +0000 (+0000) Subject: Add support for operations supported by FUSE 2.2.1 (flush, release, fsync, extended... X-Git-Tag: 0.06~3 X-Git-Url: http://git.rot13.org/?p=perl-fuse.git;a=commitdiff_plain;h=52fc7c9c1ef946d517bad3b510f9aa4aed75bfed Add support for operations supported by FUSE 2.2.1 (flush, release, fsync, extended attributes); bump version to 0.06. git-svn-id: svn+ssh://llin/home/dpavlin/private/svn/fuse/perl/trunk@14 6e4b0b00-1209-0410-87b2-b275959b5705 --- diff --git a/Changes b/Changes index 28f6ee8..01ac089 100644 --- a/Changes +++ b/Changes @@ -15,3 +15,6 @@ Revision history for Perl extension Fuse. - new maintainer, Dobrica Pavlinusic - 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 --- 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 . + return 1; +} + +sub XATTR_REPLACE { + # See . + 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, Emark@glines.orgE diff --git a/Fuse.xs b/Fuse.xs index adc63b7..9ead042 100644 --- 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