Index: Fuse.pm
===================================================================
RCS file: /cvsroot/fuse/perl/Fuse.pm,v
retrieving revision 1.3
diff -p -u -r1.3 Fuse.pm
--- Fuse.pm	20 Mar 2005 01:41:27 -0000	1.3
+++ Fuse.pm	30 Mar 2005 13:05:55 -0000
@@ -28,7 +28,7 @@ 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()
@@ -65,9 +65,10 @@ sub AUTOLOAD {
 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=>"");
Index: Fuse.xs
===================================================================
RCS file: /cvsroot/fuse/perl/Fuse.xs,v
retrieving revision 1.4
diff -p -u -r1.4 Fuse.xs
--- Fuse.xs	8 Jan 2005 00:38:41 -0000	1.4
+++ Fuse.xs	30 Mar 2005 13:05:56 -0000
@@ -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,249 @@ int _PLfuse_statfs (const char *file, 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;
+		if(SvTYPE(mysv) == SVt_NV || SvTYPE(mysv) == SVt_IV)
+			rv = SvIV(mysv);
+		else {
+			if(SvPOK(mysv)) {
+				rv = SvCUR(mysv);
+			} else {
+				rv = 0;
+			}
+			if(rv > buflen)
+				rv = -ERANGE;
+			if(rv)
+				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 {
+		SV *mysv = POPs;
+		if(SvTYPE(mysv) == SVt_NV || SvTYPE(mysv) == SVt_IV)
+			rv = SvIV(mysv);
+		else
+			rv = -EPROTO;
+
+		if (rv >= 0) {
+			char *p = list;
+			int spc = size;
+			int total_len = 0;
+			int i;
+
+			for (i = 0, mysv = POPs; i < rv; i++, mysv = POPs)
+			{
+				if (SvPOK(mysv)) {
+					int s = SvCUR(mysv);
+					total_len += s + 1;
+
+					if (p && (size > 0))
+					{
+						memcpy(p,SvPV_nolen(mysv),s);
+						p += s;	
+						*p = '\0';
+						p++;
+						spc -= s + 1;
+					}
+				}
+
+			}
+
+			if (size)
+				rv = size - spc;
+			else
+				rv = total_len;
+		}
+	}
+	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 +762,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 +776,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: META.yml
===================================================================
RCS file: /cvsroot/fuse/perl/META.yml,v
retrieving revision 1.1
diff -p -u -r1.1 META.yml
--- META.yml	22 Mar 2005 11:21:12 -0000	1.1
+++ META.yml	30 Mar 2005 13:05:56 -0000
@@ -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:
Index: README
===================================================================
RCS file: /cvsroot/fuse/perl/README,v
retrieving revision 1.3
diff -p -u -r1.3 README
--- README	20 Mar 2005 01:41:27 -0000	1.3
+++ README	30 Mar 2005 13:05:56 -0000
@@ -67,4 +67,5 @@ While most things work, I do still have 
 * need to sort out cleaner mount semantics for the test framework
 * figure out how to un-linuxcentrify the statfs tests
 * test everything on other architectures and OS's
+* Switch from the FUSE 2.1 compatibility API to the 2.2 API?
 
Index: examples/loopback.pl
===================================================================
RCS file: /cvsroot/fuse/perl/examples/loopback.pl,v
retrieving revision 1.2
diff -p -u -r1.2 loopback.pl
--- examples/loopback.pl	20 Mar 2005 01:36:05 -0000	1.2
+++ examples/loopback.pl	30 Mar 2005 13:05:56 -0000
@@ -109,6 +109,26 @@ sub x_mknod {
 	return -$!;
 }
 
+sub x_setxattr
+{
+    my ($file, $name, $value) = @_;
+    $file = fixup($file);
+    $! = 0;
+#    syscall(&SYS_setxattr,$file,);
+}
+
+sub x_getxattr
+{
+}
+
+sub x_listxattr
+{
+}
+
+sub x_removexattr
+{
+}
+
 # kludge
 sub x_statfs {return 255,1000000,500000,1000000,500000,4096}
 my ($mountpoint) = "";
