X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=Fuse.xs;h=11cfadf407d07553d8141ad32ef0baac07f4e275;hb=edb5c38bcf65f8176b6886ad705d02ac7ba9b8c6;hp=cf644bd527ce38bc987d919e18b2c56a7848d5f3;hpb=6a04a4eafea76ab317e06591371aeec8f5bcdeeb;p=perl-fuse.git diff --git a/Fuse.xs b/Fuse.xs index cf644bd..11cfadf 100755 --- a/Fuse.xs +++ b/Fuse.xs @@ -5,10 +5,57 @@ #include +#if (defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__NetBSD__) +# define XATTR_CREATE 1 +# define XATTR_REPLACE 2 +#else +# include +#endif + +#if defined(__linux__) +# define STAT_NSEC(st, st_xtim) ((st)->st_xtim.tv_nsec) +#else +# define STAT_NSEC(st, st_xtim) ((st)->st_xtim##espec.tv_nsec) +#endif + +/* Implement a macro to handle multiple formats (integer, float, and array + * containing seconds and nanoseconds). */ +#define PULL_TIME(st, st_xtim, svp) \ +{ \ + SV *sv = svp; \ + if (SvROK(sv)) { \ + AV *av = (AV *)SvRV(sv); \ + if (SvTYPE((SV *)av) != SVt_PVAV) { \ + Perl_croak_nocontext("Reference was not array ref"); \ + } \ + if (av_len(av) != 1) { \ + Perl_croak_nocontext("Array of incorrect dimension"); \ + } \ + (st)->st_xtim##e = SvIV(*(av_fetch(av, 0, FALSE))); \ + STAT_NSEC(st, st_xtim) = SvIV(*(av_fetch(av, 1, FALSE))); \ + } \ + else if (SvNOK(sv) || SvIOK(sv)) { \ + double tm = SvNV(sv); \ + (st)->st_xtim##e = (int)tm; \ + STAT_NSEC(st, st_xtim) = (tm - (int)tm) * 1000000000; \ + } \ + else { \ + Perl_croak_nocontext("Invalid data type passed"); \ + } \ +} + /* Determine if threads support should be included */ #ifdef USE_ITHREADS # ifdef I_PTHREAD # define FUSE_USE_ITHREADS +# if (PERL_VERSION < 8) || (PERL_VERSION == 8 && PERL_SUBVERSION < 9) +# define tTHX PerlInterpreter* +# define STR_WITH_LEN(s) ("" s ""), (sizeof(s)-1) +# define hv_fetchs(hv,key,lval) Perl_hv_fetch(aTHX_ hv, STR_WITH_LEN(key), lval) +# define dMY_CXT_INTERP(interp) \ + SV *my_cxt_sv = *hv_fetchs(interp->Imodglobal, MY_CXT_KEY, TRUE); \ + my_cxt_t *my_cxtp = INT2PTR(my_cxt_t*, SvUV(my_cxt_sv)) +# endif # else # warning "Sorry, I don't know how to handle ithreads on this architecture. Building non-threaded version" # endif @@ -17,9 +64,9 @@ /* Global Data */ #define MY_CXT_KEY "Fuse::_guts" XS_VERSION -/* #if FUSE_VERSION >= 28 -# define N_CALLBACKS 41 */ -#if FUSE_VERSION >= 26 +#if FUSE_VERSION >= 28 +# define N_CALLBACKS 41 +#elif FUSE_VERSION >= 26 # define N_CALLBACKS 38 #elif FUSE_VERSION >= 25 # define N_CALLBACKS 35 @@ -32,9 +79,13 @@ typedef struct { SV *callback[N_CALLBACKS]; HV *handles; +#ifdef USE_ITHREADS tTHX self; +#endif int threaded; +#ifdef USE_ITHREADS perl_mutex mutex; +#endif } my_cxt_t; START_MY_CXT; @@ -43,6 +94,9 @@ tTHX master_interp = NULL; #define CLONE_INTERP(parent) S_clone_interp(parent) tTHX S_clone_interp(tTHX parent) { +# if (PERL_VERSION < 10) + tTHX my_perl = parent; +#endif dMY_CXT_INTERP(parent); if(MY_CXT.threaded) { MUTEX_LOCK(&MY_CXT.mutex); @@ -107,8 +161,10 @@ void S_fh_store_handle(pTHX_ pMY_CXT_ struct fuse_file_info *fi, SV *sv) { SvSHARE(sv); } #endif - MAGIC *mg = (SvTYPE(sv) == SVt_PVMG) ? mg_find(sv, PERL_MAGIC_shared_scalar) : NULL; - fi->fh = mg ? PTR2IV(mg->mg_ptr) : PTR2IV(sv); + /* This seems to be screwing things up... */ + // MAGIC *mg = (SvTYPE(sv) == SVt_PVMG) ? mg_find(sv, PERL_MAGIC_shared_scalar) : NULL; + // fi->fh = mg ? PTR2IV(mg->mg_ptr) : PTR2IV(sv); + fi->fh = PTR2IV(sv); if(hv_store_ent(MY_CXT.handles, FH_KEY(fi), SvREFCNT_inc(sv), 0) == NULL) { SvREFCNT_dec(sv); } @@ -138,9 +194,9 @@ int _PLfuse_getattr(const char *file, struct stat *result) { } else { result->st_blocks = POPi; result->st_blksize = POPi; - result->st_ctime = POPi; - result->st_mtime = POPi; - result->st_atime = POPi; + PULL_TIME(result, st_ctim, POPs); + PULL_TIME(result, st_mtim, POPs); + PULL_TIME(result, st_atim, POPs); result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit) result->st_rdev = POPi; result->st_gid = POPi; @@ -238,10 +294,7 @@ int _PLfuse_mknod (const char *file, mode_t mode, dev_t dev) { PUTBACK; rv = call_sv(MY_CXT.callback[3],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -262,10 +315,7 @@ int _PLfuse_mkdir (const char *file, mode_t mode) { PUTBACK; rv = call_sv(MY_CXT.callback[4],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -286,10 +336,7 @@ int _PLfuse_unlink (const char *file) { PUTBACK; rv = call_sv(MY_CXT.callback[5],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -309,10 +356,7 @@ int _PLfuse_rmdir (const char *file) { PUTBACK; rv = call_sv(MY_CXT.callback[6],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -333,10 +377,7 @@ int _PLfuse_symlink (const char *file, const char *new) { PUTBACK; rv = call_sv(MY_CXT.callback[7],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -357,10 +398,7 @@ int _PLfuse_rename (const char *file, const char *new) { PUTBACK; rv = call_sv(MY_CXT.callback[8],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -381,10 +419,7 @@ int _PLfuse_link (const char *file, const char *new) { PUTBACK; rv = call_sv(MY_CXT.callback[9],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -405,10 +440,7 @@ int _PLfuse_chmod (const char *file, mode_t mode) { PUTBACK; rv = call_sv(MY_CXT.callback[10],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -430,10 +462,7 @@ int _PLfuse_chown (const char *file, uid_t uid, gid_t gid) { PUTBACK; rv = call_sv(MY_CXT.callback[11],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -456,17 +485,15 @@ int _PLfuse_truncate (const char *file, off_t off) { #ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); #else - asprintf(&temp, "%llu", off); + if (asprintf(&temp, "%llu", off) == -1) + croak("Memory allocation failure!"); XPUSHs(sv_2mortal(newSVpv(temp, 0))); free(temp); #endif PUTBACK; rv = call_sv(MY_CXT.callback[12],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -488,10 +515,7 @@ int _PLfuse_utime (const char *file, struct utimbuf *uti) { PUTBACK; rv = call_sv(MY_CXT.callback[13],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -517,10 +541,10 @@ int _PLfuse_open (const char *file, struct fuse_file_info *fi) { fi->fh = 0; /* Ensure it starts with 0 - important if they don't set it */ fihash = newHV(); #if FUSE_VERSION >= 24 - (void) hv_store(fihash, "direct_io", 9, newSViv(fi->direct_io), 0); - (void) hv_store(fihash, "keep_cache", 10, newSViv(fi->keep_cache), 0); + (void) hv_store(fihash, "direct_io", 9, newSViv(fi->direct_io), 0); + (void) hv_store(fihash, "keep_cache", 10, newSViv(fi->keep_cache), 0); #endif -#if FUSE_VERSION >= 29 +#if FUSE_VERSION >= 28 (void) hv_store(fihash, "nonseekable", 11, newSViv(fi->nonseekable), 0); #endif XPUSHs(sv_2mortal(newRV_noinc((SV*) fihash))); @@ -543,23 +567,14 @@ int _PLfuse_open (const char *file, struct fuse_file_info *fi) { /* Success, so copy the file handle which they returned */ #if FUSE_VERSION >= 24 SV **svp; - svp = hv_fetch(fihash, "direct_io", 9, 0); - if (svp != NULL) - { - fi->direct_io = SvIV(*svp); - } - svp = hv_fetch(fihash, "keep_cache", 10, 0); - if (svp != NULL) - { - fi->keep_cache = SvIV(*svp); - } + if ((svp = hv_fetch(fihash, "direct_io", 9, 0)) != NULL) + fi->direct_io = SvIV(*svp); + if ((svp = hv_fetch(fihash, "keep_cache", 10, 0)) != NULL) + fi->keep_cache = SvIV(*svp); #endif -#if FUSE_VERSION >= 29 - svp = hv_fetch(fihash, "nonseekable", 11, 0); - if (svp != NULL) - { - fi->nonseekable = SvIV(*svp); - } +#if FUSE_VERSION >= 28 + if ((svp = hv_fetch(fihash, "nonseekable", 11, 0)) != NULL) + fi->nonseekable = SvIV(*svp); #endif } FREETMPS; @@ -570,7 +585,8 @@ int _PLfuse_open (const char *file, struct fuse_file_info *fi) { return rv; } -int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct fuse_file_info *fi) { +int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, + struct fuse_file_info *fi) { int rv; #ifndef PERL_HAS_64BITINT char *temp; @@ -580,12 +596,13 @@ int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off, struct ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(file,0))); + XPUSHs(file ? sv_2mortal(newSVpv(file,0)) : &PL_sv_undef); XPUSHs(sv_2mortal(newSViv(buflen))); #ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); #else - asprintf(&temp, "%llu", off); + if (asprintf(&temp, "%llu", off) == -1) + croak("Memory allocation failure!"); XPUSHs(sv_2mortal(newSVpv(temp, 0))); free(temp); #endif @@ -629,12 +646,13 @@ int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off, ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(file,0))); + XPUSHs(file ? sv_2mortal(newSVpv(file,0)) : &PL_sv_undef); XPUSHs(sv_2mortal(newSVpvn(buf,buflen))); #ifdef PERL_HAS_64BITINT XPUSHs(sv_2mortal(newSViv(off))); #else - asprintf(&temp, "%llu", off); + if (asprintf(&temp, "%llu", off) == -1) + croak("Memory allocation failure!"); XPUSHs(sv_2mortal(newSVpv(temp, 0))); free(temp); #endif @@ -642,10 +660,7 @@ int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off, PUTBACK; rv = call_sv(MY_CXT.callback[16],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -706,15 +721,12 @@ int _PLfuse_flush (const char *file, struct fuse_file_info *fi) { ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(file,0))); + XPUSHs(file ? sv_2mortal(newSVpv(file,0)) : &PL_sv_undef); XPUSHs(FH_GETHANDLE(fi)); PUTBACK; rv = call_sv(MY_CXT.callback[18],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -731,16 +743,13 @@ int _PLfuse_release (const char *file, struct fuse_file_info *fi) { ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(file,0))); + XPUSHs(file ? sv_2mortal(newSVpv(file,0)) : &PL_sv_undef); XPUSHs(sv_2mortal(newSViv(flags))); XPUSHs(FH_GETHANDLE(fi)); PUTBACK; rv = call_sv(MY_CXT.callback[19],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FH_RELEASEHANDLE(fi); FREETMPS; LEAVE; @@ -758,16 +767,13 @@ int _PLfuse_fsync (const char *file, int datasync, struct fuse_file_info *fi) { ENTER; SAVETMPS; PUSHMARK(SP); - XPUSHs(sv_2mortal(newSVpv(file,0))); + XPUSHs(file ? sv_2mortal(newSVpv(file,0)) : &PL_sv_undef); XPUSHs(sv_2mortal(newSViv(flags))); XPUSHs(FH_GETHANDLE(fi)); PUTBACK; rv = call_sv(MY_CXT.callback[20],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -776,7 +782,11 @@ int _PLfuse_fsync (const char *file, int datasync, struct fuse_file_info *fi) { return rv; } +#if __FreeBSD__ >= 10 +int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_t buflen, int flags, uint32_t position) { +#else int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_t buflen, int flags) { +#endif int rv; FUSE_CONTEXT_PRE; DEBUGf("setxattr begin\n"); @@ -790,10 +800,7 @@ int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_ PUTBACK; rv = call_sv(MY_CXT.callback[21],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -802,7 +809,11 @@ int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_ return rv; } +#if __FreeBSD__ >= 10 +int _PLfuse_getxattr (const char *file, const char *name, char *buf, size_t buflen, uint32_t position) { +#else int _PLfuse_getxattr (const char *file, const char *name, char *buf, size_t buflen) { +#endif int rv; FUSE_CONTEXT_PRE; DEBUGf("getxattr begin\n"); @@ -921,10 +932,7 @@ int _PLfuse_removexattr (const char *file, const char *name) { PUTBACK; rv = call_sv(MY_CXT.callback[24],G_SCALAR); SPAGAIN; - if(rv) - rv = POPi; - else - rv = 0; + rv = (rv ? POPi : 0); FREETMPS; LEAVE; PUTBACK; @@ -948,7 +956,7 @@ int _PLfuse_opendir(const char *file, struct fuse_file_info *fi) { SPAGAIN; if (rv) { if (rv > 1) { - FH_STOREHANDLE(fi, POPs); + FH_STOREHANDLE(fi, POPs); } rv = POPi; } else @@ -1021,9 +1029,9 @@ int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, st.st_gid = SvIV(*(av_fetch(av2, 5, FALSE))); st.st_rdev = SvIV(*(av_fetch(av2, 6, FALSE))); st.st_size = SvNV(*(av_fetch(av2, 7, FALSE))); - st.st_atime = SvIV(*(av_fetch(av2, 8, FALSE))); - st.st_mtime = SvIV(*(av_fetch(av2, 9, FALSE))); - st.st_ctime = SvIV(*(av_fetch(av2, 10, FALSE))); + PULL_TIME(&st, st_atim, *(av_fetch(av2, 8, FALSE))); + PULL_TIME(&st, st_mtim, *(av_fetch(av2, 9, FALSE))); + PULL_TIME(&st, st_ctim, *(av_fetch(av2, 10, FALSE))); st.st_blksize = SvIV(*(av_fetch(av2, 11, FALSE))); st.st_blocks = SvIV(*(av_fetch(av2, 12, FALSE))); st_filled = 1; @@ -1192,11 +1200,9 @@ int _PLfuse_create(const char *file, mode_t mode, struct fuse_file_info *fi) { * which we can look at or modify. */ fihash = newHV(); -#if FUSE_VERSION >= 24 - (void) hv_store(fihash, "direct_io", 9, newSViv(fi->direct_io), 0); - (void) hv_store(fihash, "keep_cache", 10, newSViv(fi->keep_cache), 0); -#endif -#if FUSE_VERSION >= 29 + (void) hv_store(fihash, "direct_io", 9, newSViv(fi->direct_io), 0); + (void) hv_store(fihash, "keep_cache", 10, newSViv(fi->keep_cache), 0); +#if FUSE_VERSION >= 28 (void) hv_store(fihash, "nonseekable", 11, newSViv(fi->nonseekable), 0); #endif XPUSHs(sv_2mortal(newRV_noinc((SV*) fihash))); @@ -1217,18 +1223,13 @@ int _PLfuse_create(const char *file, mode_t mode, struct fuse_file_info *fi) { } if (rv == 0) { /* Success, so copy the file handle which they returned */ -#if FUSE_VERSION >= 24 SV **svp; - svp = hv_fetch(fihash, "direct_io", 9, 0); - if (svp != NULL) - fi->direct_io = SvIV(*svp); - svp = hv_fetch(fihash, "keep_cache", 10, 0); - if (svp != NULL) - fi->keep_cache = SvIV(*svp); -#endif -#if FUSE_VERSION >= 29 - svp = hv_fetch(fihash, "nonseekable", 11, 0); - if (svp != NULL) + if ((svp = hv_fetch(fihash, "direct_io", 9, 0)) != NULL) + fi->direct_io = SvIV(*svp); + if ((svp = hv_fetch(fihash, "keep_cache", 10, 0)) != NULL) + fi->keep_cache = SvIV(*svp); +#if FUSE_VERSION >= 28 + if ((svp = hv_fetch(fihash, "nonseekable", 11, 0)) != NULL) fi->nonseekable = SvIV(*svp); #endif } @@ -1296,9 +1297,9 @@ int _PLfuse_fgetattr(const char *file, struct stat *result, } else { result->st_blocks = POPi; result->st_blksize = POPi; - result->st_ctime = POPi; - result->st_mtime = POPi; - result->st_atime = POPi; + PULL_TIME(result, st_ctim, POPs); + PULL_TIME(result, st_mtim, POPs); + PULL_TIME(result, st_atim, POPs); result->st_size = POPn; // we pop double here to support files larger than 4Gb (long limit) result->st_rdev = POPi; result->st_gid = POPi; @@ -1369,15 +1370,15 @@ int _PLfuse_lock(const char *file, struct fuse_file_info *fi, int cmd, /* Need to copy back any altered values from the hash into * the struct... */ SV **svp; - if ((svp = hv_fetch(lihash, "l_type", 6, 0))) + if ((svp = hv_fetch(lihash, "l_type", 6, 0)) != NULL) lockinfo->l_type = SvIV(*svp); - if ((svp = hv_fetch(lihash, "l_whence", 8, 0))) + if ((svp = hv_fetch(lihash, "l_whence", 8, 0)) != NULL) lockinfo->l_whence = SvIV(*svp); - if ((svp = hv_fetch(lihash, "l_start", 7, 0))) + if ((svp = hv_fetch(lihash, "l_start", 7, 0)) != NULL) lockinfo->l_start = SvNV(*svp); - if ((svp = hv_fetch(lihash, "l_len", 5, 0))) + if ((svp = hv_fetch(lihash, "l_len", 5, 0)) != NULL) lockinfo->l_len = SvNV(*svp); - if ((svp = hv_fetch(lihash, "l_pid", 5, 0))) + if ((svp = hv_fetch(lihash, "l_pid", 5, 0)) != NULL) lockinfo->l_pid = SvIV(*svp); } FREETMPS; @@ -1451,20 +1452,23 @@ int _PLfuse_bmap(const char *file, size_t blocksize, uint64_t *idx) { } #endif /* FUSE_VERSION >= 26 */ -#if 0 #if FUSE_VERSION >= 28 int _PLfuse_ioctl(const char *file, int cmd, void *arg, struct fuse_file_info *fi, unsigned int flags, void *data) { int rv; + SV *sv = NULL; FUSE_CONTEXT_PRE; DEBUGf("ioctl begin\n"); ENTER; SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); - XPUSHs(sv_2mortal(newSViv(cmd))); + /* I don't know why cmd is a signed int in the first place; + * casting as unsigned so stupid tricks don't have to be done on + * the perl side */ + XPUSHs(sv_2mortal(newSViv((unsigned int)cmd))); XPUSHs(sv_2mortal(newSViv(flags))); - if (_IOC_DIR(cmd) & _IOC_READ) + if (_IOC_DIR(cmd) & _IOC_WRITE) XPUSHs(sv_2mortal(newSVpvn(data, _IOC_SIZE(cmd)))); else XPUSHs(&PL_sv_undef); @@ -1472,11 +1476,19 @@ int _PLfuse_ioctl(const char *file, int cmd, void *arg, PUTBACK; rv = call_sv(MY_CXT.callback[39],G_ARRAY); SPAGAIN; - if (_IOC_DIR(cmd) & _IOC_WRITE) { - if (rv == 2) { - SV *sv = POPs; - unsigned int len; + if ((_IOC_DIR(cmd) & _IOC_READ) && (rv == 2)) { + sv = POPs; + rv--; + } + + if (rv > 0) + rv = POPi; + + if ((_IOC_DIR(cmd) & _IOC_READ) && !rv) { + if (sv) { + size_t len; char *rdata = SvPV(sv, len); + if (len > _IOC_SIZE(cmd)) { fprintf(stderr, "ioctl(): returned data was too large for data area\n"); rv = -EFBIG; @@ -1485,16 +1497,12 @@ int _PLfuse_ioctl(const char *file, int cmd, void *arg, memset(data, 0, _IOC_SIZE(cmd)); memcpy(data, rdata, len); } - - rv--; } else { - fprintf(stderr, "ioctl(): ioctl was a write op, but no data was returned from call?\n"); + fprintf(stderr, "ioctl(): ioctl was a read op, but no data was returned from call?\n"); rv = -EFAULT; } } - if (rv > 0) - rv = POPi; FREETMPS; LEAVE; PUTBACK; @@ -1505,10 +1513,41 @@ int _PLfuse_ioctl(const char *file, int cmd, void *arg, int _PLfuse_poll(const char *file, struct fuse_file_info *fi, struct fuse_pollhandle *ph, unsigned *reventsp) { - + int rv; + SV *sv = NULL; + FUSE_CONTEXT_PRE; + DEBUGf("poll begin\n"); + ENTER; + SAVETMPS; + PUSHMARK(SP); + XPUSHs(sv_2mortal(newSVpv(file,0))); + if (ph) { + /* Still gotta figure out how to do this right... */ + sv = newSViv(PTR2IV(ph)); + SvREADONLY_on(sv); + SvSHARE(sv); + XPUSHs(sv); + } + else + XPUSHs(&PL_sv_undef); + XPUSHs(sv_2mortal(newSViv(*reventsp))); + XPUSHs(FH_GETHANDLE(fi)); + PUTBACK; + rv = call_sv(MY_CXT.callback[40],G_ARRAY); + SPAGAIN; + if (rv > 1) { + *reventsp = POPi; + rv--; + } + rv = (rv ? POPi : 0); + FREETMPS; + LEAVE; + PUTBACK; + DEBUGf("poll end: %i\n", rv); + FUSE_CONTEXT_POST; + return rv; } #endif /* FUSE_VERSION >= 28 */ -#endif struct fuse_operations _available_ops = { getattr: _PLfuse_getattr, @@ -1518,6 +1557,7 @@ mknod: _PLfuse_mknod, mkdir: _PLfuse_mkdir, unlink: _PLfuse_unlink, rmdir: _PLfuse_rmdir, +symlink: _PLfuse_symlink, rename: _PLfuse_rename, link: _PLfuse_link, chmod: _PLfuse_chmod, @@ -1554,12 +1594,10 @@ lock: _PLfuse_lock, utimens: _PLfuse_utimens, bmap: _PLfuse_bmap, #endif /* FUSE_VERSION >= 26 */ -#if 0 #if FUSE_VERSION >= 28 ioctl: _PLfuse_ioctl, poll: _PLfuse_poll, #endif /* FUSE_VERSION >= 28 */ -#endif }; MODULE = Fuse PACKAGE = Fuse @@ -1567,14 +1605,19 @@ PROTOTYPES: DISABLE BOOT: MY_CXT_INIT; +#ifdef USE_ITHREADS MY_CXT.self = aTHX; +#endif void CLONE(...) PREINIT: +#ifdef USE_ITHREADS int i; dTHX; +#endif CODE: +#ifdef USE_ITHREADS MY_CXT_CLONE; tTHX parent = MY_CXT.self; MY_CXT.self = my_perl; @@ -1590,7 +1633,7 @@ CLONE(...) { CLONE_PARAMS *clone_param; #if (PERL_VERSION > 13) || (PERL_VERSION == 13 && PERL_SUBVERSION >= 2) - clone_param = clone_params_new(parent, aTHX); + clone_param = Perl_clone_params_new(parent, aTHX); #else CLONE_PARAMS raw_param; raw_param.flags = 0; @@ -1603,9 +1646,10 @@ CLONE(...) } MY_CXT.handles = (HV*)sv_dup((SV*)MY_CXT.handles, clone_param); #if (PERL_VERSION > 13) || (PERL_VERSION == 13 && PERL_SUBVERSION >= 2) - clone_params_del(clone_param); + Perl_clone_params_del(clone_param); #endif } +#endif SV* fuse_get_context() @@ -1615,15 +1659,14 @@ fuse_get_context() fc = fuse_get_context(); if(fc) { HV *hash = newHV(); - (void) hv_store(hash, "uid", 3, newSViv(fc->uid), 0); - (void) hv_store(hash, "gid", 3, newSViv(fc->gid), 0); - (void) hv_store(hash, "pid", 3, newSViv(fc->pid), 0); + (void) hv_store(hash, "uid", 3, newSViv(fc->uid), 0); + (void) hv_store(hash, "gid", 3, newSViv(fc->gid), 0); + (void) hv_store(hash, "pid", 3, newSViv(fc->pid), 0); if (fc->private_data) (void) hv_store(hash, "private", 7, fc->private_data, 0); #if FUSE_VERSION >= 28 (void) hv_store(hash, "umask", 5, newSViv(fc->umask), 0); #endif /* FUSE_VERSION >= 28 */ - RETVAL = newRV_noinc((SV*)hash); } else { XSRETURN_UNDEF; @@ -1638,6 +1681,20 @@ fuse_version() OUTPUT: RETVAL +SV * +XATTR_CREATE() + CODE: + RETVAL = newSViv(XATTR_CREATE); + OUTPUT: + RETVAL + +SV * +XATTR_REPLACE() + CODE: + RETVAL = newSViv(XATTR_REPLACE); + OUTPUT: + RETVAL + void perl_fuse_main(...) PREINIT: @@ -1691,7 +1748,7 @@ perl_fuse_main(...) } else if(SvOK(var)) { croak("invalid callback (%i) passed to perl_fuse_main " "(%s is not a string, code ref, or undef).\n", - i+4,SvPVbyte_nolen(var)); + i+5,SvPVbyte_nolen(var)); } else { MY_CXT.callback[i] = NULL; } @@ -1701,9 +1758,12 @@ perl_fuse_main(...) * to hack on compatibility with other parts of the new API. First and * foremost, real C argc/argv would be good to get at... */ - if (mountopts && - (fuse_opt_add_arg(&args, "") == -1 || - fuse_opt_add_arg(&args, "-o") == -1 || + if ((mountopts || debug) && fuse_opt_add_arg(&args, "") == -1) { + fuse_opt_free_args(&args); + croak("out of memory\n"); + } + if (mountopts && strcmp("", mountopts) && + (fuse_opt_add_arg(&args, "-o") == -1 || fuse_opt_add_arg(&args, mountopts) == -1)) { fuse_opt_free_args(&args); croak("out of memory\n"); @@ -1723,3 +1783,35 @@ perl_fuse_main(...) fuse_loop(fuse_new(fc,&args,&fops,sizeof(fops),NULL)); fuse_unmount(mountpoint,fc); fuse_opt_free_args(&args); + +#if FUSE_VERSION >= 28 + +void +pollhandle_destroy(...) + PREINIT: + struct fuse_pollhandle *ph; + INIT: + if (items != 1) { + fprintf(stderr, "No pollhandle passed?\n"); + XSRETURN_UNDEF; + } + CODE: + ph = INT2PTR(struct fuse_pollhandle*, SvIV(ST(0))); + fuse_pollhandle_destroy(ph); + +int +notify_poll(...) + PREINIT: + struct fuse_pollhandle *ph; + INIT: + if (items != 1) { + fprintf(stderr, "No pollhandle passed?\n"); + XSRETURN_UNDEF; + } + CODE: + ph = INT2PTR(struct fuse_pollhandle*, SvIV(ST(0))); + RETVAL = fuse_notify_poll(ph); + OUTPUT: + RETVAL + +#endif