--- perl/trunk/Fuse.xs 2004/11/11 14:44:15 4 +++ perl/trunk/Fuse.xs 2005/04/10 13:30:11 14 @@ -2,7 +2,7 @@ #include "perl.h" #include "XSUB.h" -#include +#include #undef DEBUGf #if 0 @@ -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; @@ -32,14 +33,11 @@ else rv = -ENOENT; } else { + result->st_blocks = POPi; result->st_blksize = POPi; result->st_ctime = POPi; result->st_mtime = POPi; result->st_atime = POPi; - /* What the HELL? Perl says the blockcount is the last argument. - * Everything else says the blockcount is the last argument. So why - * was it folded into the middle of the list? */ - result->st_blocks = POPi; result->st_size = POPi; result->st_rdev = POPi; result->st_gid = POPi; @@ -513,25 +511,261 @@ 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 @@ -540,13 +774,13 @@ 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; } @@ -554,7 +788,7 @@ 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