X-Git-Url: http://git.rot13.org/?p=perl-fuse.git;a=blobdiff_plain;f=Fuse.xs;h=6cd7523e14157cc8cdffc8fb90550cb00bb301df;hp=11cfadf407d07553d8141ad32ef0baac07f4e275;hb=HEAD;hpb=bdcd0a693ecaf85db36f3611d50eaa38f95eed9b diff --git a/Fuse.xs b/Fuse.xs index 11cfadf..6cd7523 100755 --- a/Fuse.xs +++ b/Fuse.xs @@ -5,7 +5,7 @@ #include -#if (defined(__FreeBSD__) && __FreeBSD__ < 10) || defined(__NetBSD__) +#if (defined(__FreeBSD__) && !defined(__APPLE__)) || defined(__NetBSD__) # define XATTR_CREATE 1 # define XATTR_REPLACE 2 #else @@ -13,8 +13,10 @@ #endif #if defined(__linux__) +# define STAT_SEC(st, st_xtim) ((st)->st_xtim.tv_sec) # define STAT_NSEC(st, st_xtim) ((st)->st_xtim.tv_nsec) #else +# define STAT_SEC(st, st_xtim) ((st)->st_xtim##espec.tv_sec) # define STAT_NSEC(st, st_xtim) ((st)->st_xtim##espec.tv_nsec) #endif @@ -31,12 +33,12 @@ if (av_len(av) != 1) { \ Perl_croak_nocontext("Array of incorrect dimension"); \ } \ - (st)->st_xtim##e = SvIV(*(av_fetch(av, 0, FALSE))); \ + STAT_SEC(st, st_xtim) = 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_SEC(st, st_xtim) = (int)tm; \ STAT_NSEC(st, st_xtim) = (tm - (int)tm) * 1000000000; \ } \ else { \ @@ -66,14 +68,8 @@ #define MY_CXT_KEY "Fuse::_guts" XS_VERSION #if FUSE_VERSION >= 28 # define N_CALLBACKS 41 -#elif FUSE_VERSION >= 26 -# define N_CALLBACKS 38 -#elif FUSE_VERSION >= 25 -# define N_CALLBACKS 35 -#elif FUSE_VERSION >= 23 -# define N_CALLBACKS 31 #else -# define N_CALLBACKS 25 +# define N_CALLBACKS 38 #endif typedef struct { @@ -86,6 +82,7 @@ typedef struct { #ifdef USE_ITHREADS perl_mutex mutex; #endif + int utimens_as_array; } my_cxt_t; START_MY_CXT; @@ -324,7 +321,6 @@ int _PLfuse_mkdir (const char *file, mode_t mode) { return rv; } - int _PLfuse_unlink (const char *file) { int rv; FUSE_CONTEXT_PRE; @@ -540,10 +536,8 @@ 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); -#endif #if FUSE_VERSION >= 28 (void) hv_store(fihash, "nonseekable", 11, newSViv(fi->nonseekable), 0); #endif @@ -565,13 +559,11 @@ int _PLfuse_open (const char *file, struct fuse_file_info *fi) { if (rv == 0) { /* Success, so copy the file handle which they returned */ -#if FUSE_VERSION >= 24 SV **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 >= 28 if ((svp = hv_fetch(fihash, "nonseekable", 11, 0)) != NULL) fi->nonseekable = SvIV(*svp); @@ -782,7 +774,7 @@ int _PLfuse_fsync (const char *file, int datasync, struct fuse_file_info *fi) { return rv; } -#if __FreeBSD__ >= 10 +#ifdef __APPLE__ 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) { @@ -809,7 +801,7 @@ int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_ return rv; } -#if __FreeBSD__ >= 10 +#ifdef __APPLE__ 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) { @@ -941,7 +933,6 @@ int _PLfuse_removexattr (const char *file, const char *name) { return rv; } -#if FUSE_VERSION >= 23 int _PLfuse_opendir(const char *file, struct fuse_file_info *fi) { int rv; FUSE_CONTEXT_PRE; @@ -967,7 +958,6 @@ int _PLfuse_opendir(const char *file, struct fuse_file_info *fi) { DEBUGf("opendir end: %i\n",rv); FUSE_CONTEXT_POST; return rv; - } int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, @@ -1019,8 +1009,8 @@ int _PLfuse_readdir(const char *file, void *dirh, fuse_fill_dir_t dirfil, * enumeration process... */ svp = av_fetch(av, 2, FALSE); if (SvROK(*svp) && - SvTYPE(av2 = (AV *)SvRV(*svp)) == SVt_PVAV && - av_len(av2) == 12) { + SvTYPE(av2 = (AV *)SvRV(*svp)) == SVt_PVAV && + av_len(av2) == 12) { st.st_dev = SvIV(*(av_fetch(av2, 0, FALSE))); st.st_ino = SvIV(*(av_fetch(av2, 1, FALSE))); st.st_mode = SvIV(*(av_fetch(av2, 2, FALSE))); @@ -1111,11 +1101,7 @@ int _PLfuse_fsyncdir(const char *file, int datasync, return rv; } -#if FUSE_VERSION >= 26 void *_PLfuse_init(struct fuse_conn_info *fc) -#else /* FUSE_VERSION < 26 */ -void *_PLfuse_init(void) -#endif /* FUSE_VERSION >= 26 */ { void *rv = NULL; int prv; @@ -1160,9 +1146,7 @@ void _PLfuse_destroy(void *private_data) { DEBUGf("init end\n"); FUSE_CONTEXT_POST; } -#endif /* FUSE_VERSION >= 23 */ -#if FUSE_VERSION >= 25 int _PLfuse_access(const char *file, int mask) { int rv; FUSE_CONTEXT_PRE; @@ -1317,9 +1301,7 @@ int _PLfuse_fgetattr(const char *file, struct stat *result, FUSE_CONTEXT_POST; return rv; } -#endif /* FUSE_VERSION >= 25 */ -#if FUSE_VERSION >= 26 int _PLfuse_lock(const char *file, struct fuse_file_info *fi, int cmd, struct flock *lockinfo) { int rv; @@ -1397,8 +1379,30 @@ int _PLfuse_utimens(const char *file, const struct timespec tv[2]) { SAVETMPS; PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); - XPUSHs(tv ? sv_2mortal(newSVnv(tv[0].tv_sec + (tv[0].tv_nsec / 1000000000.0))) : &PL_sv_undef); - XPUSHs(tv ? sv_2mortal(newSVnv(tv[1].tv_sec + (tv[1].tv_nsec / 1000000000.0))) : &PL_sv_undef); + if (MY_CXT.utimens_as_array) { + /* Pushing timespecs as 2-element arrays (if tv is present). */ + AV *av; + if (tv) { + av = newAV(); + av_push(av, newSViv(tv[0].tv_sec)); + av_push(av, newSViv(tv[0].tv_nsec)); + XPUSHs(sv_2mortal(newRV_noinc((SV *)av))); + av = newAV(); + av_push(av, newSViv(tv[1].tv_sec)); + av_push(av, newSViv(tv[1].tv_nsec)); + XPUSHs(sv_2mortal(newRV_noinc((SV *)av))); + } + else { + XPUSHs(&PL_sv_undef); + XPUSHs(&PL_sv_undef); + } + + } + else { + /* Pushing timespecs as floating point (double) values. */ + XPUSHs(tv ? sv_2mortal(newSVnv(tv[0].tv_sec + (tv[0].tv_nsec / 1000000000.0))) : &PL_sv_undef); + XPUSHs(tv ? sv_2mortal(newSVnv(tv[1].tv_sec + (tv[1].tv_nsec / 1000000000.0))) : &PL_sv_undef); + } PUTBACK; rv = call_sv(MY_CXT.callback[36],G_SCALAR); SPAGAIN; @@ -1450,9 +1454,13 @@ int _PLfuse_bmap(const char *file, size_t blocksize, uint64_t *idx) { FUSE_CONTEXT_POST; return rv; } -#endif /* FUSE_VERSION >= 26 */ #if FUSE_VERSION >= 28 + +# ifndef __linux__ +# define _IOC_SIZE(n) IOCPARM_LEN(n) +# endif + int _PLfuse_ioctl(const char *file, int cmd, void *arg, struct fuse_file_info *fi, unsigned int flags, void *data) { int rv; @@ -1466,9 +1474,9 @@ int _PLfuse_ioctl(const char *file, int cmd, void *arg, /* 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(newSVuv((unsigned int)cmd))); XPUSHs(sv_2mortal(newSViv(flags))); - if (_IOC_DIR(cmd) & _IOC_WRITE) + if (cmd & IOC_IN) XPUSHs(sv_2mortal(newSVpvn(data, _IOC_SIZE(cmd)))); else XPUSHs(&PL_sv_undef); @@ -1476,7 +1484,7 @@ 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_READ) && (rv == 2)) { + if ((cmd & IOC_OUT) && (rv == 2)) { sv = POPs; rv--; } @@ -1484,7 +1492,7 @@ int _PLfuse_ioctl(const char *file, int cmd, void *arg, if (rv > 0) rv = POPi; - if ((_IOC_DIR(cmd) & _IOC_READ) && !rv) { + if ((cmd & IOC_OUT) && !rv) { if (sv) { size_t len; char *rdata = SvPV(sv, len); @@ -1522,9 +1530,9 @@ int _PLfuse_poll(const char *file, struct fuse_file_info *fi, PUSHMARK(SP); XPUSHs(sv_2mortal(newSVpv(file,0))); if (ph) { - /* Still gotta figure out how to do this right... */ + /* Still gotta figure out how to do this right... */ sv = newSViv(PTR2IV(ph)); - SvREADONLY_on(sv); + SvREADONLY_on(sv); SvSHARE(sv); XPUSHs(sv); } @@ -1537,8 +1545,8 @@ int _PLfuse_poll(const char *file, struct fuse_file_info *fi, SPAGAIN; if (rv > 1) { *reventsp = POPi; - rv--; - } + rv--; + } rv = (rv ? POPi : 0); FREETMPS; LEAVE; @@ -1550,53 +1558,47 @@ int _PLfuse_poll(const char *file, struct fuse_file_info *fi, #endif /* FUSE_VERSION >= 28 */ struct fuse_operations _available_ops = { -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, -#if FUSE_VERSION >= 23 -opendir: _PLfuse_opendir, -readdir: _PLfuse_readdir, -releasedir: _PLfuse_releasedir, -fsyncdir: _PLfuse_fsyncdir, -init: _PLfuse_init, -destroy: _PLfuse_destroy, -#endif /* FUSE_VERSION >= 23 */ -#if FUSE_VERSION >= 25 -access: _PLfuse_access, -create: _PLfuse_create, -ftruncate: _PLfuse_ftruncate, -fgetattr: _PLfuse_fgetattr, -#endif /* FUSE_VERSION >= 25 */ -#if FUSE_VERSION >= 26 -lock: _PLfuse_lock, -utimens: _PLfuse_utimens, -bmap: _PLfuse_bmap, -#endif /* FUSE_VERSION >= 26 */ +.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, +.opendir = _PLfuse_opendir, +.readdir = _PLfuse_readdir, +.releasedir = _PLfuse_releasedir, +.fsyncdir = _PLfuse_fsyncdir, +.init = _PLfuse_init, +.destroy = _PLfuse_destroy, +.access = _PLfuse_access, +.create = _PLfuse_create, +.ftruncate = _PLfuse_ftruncate, +.fgetattr = _PLfuse_fgetattr, +.lock = _PLfuse_lock, +.utimens = _PLfuse_utimens, +.bmap = _PLfuse_bmap, #if FUSE_VERSION >= 28 -ioctl: _PLfuse_ioctl, -poll: _PLfuse_poll, +.ioctl = _PLfuse_ioctl, +.poll = _PLfuse_poll, #endif /* FUSE_VERSION >= 28 */ }; @@ -1706,7 +1708,7 @@ perl_fuse_main(...) struct fuse_chan *fc; dMY_CXT; INIT: - if(items != N_CALLBACKS + 5) { + if(items != N_CALLBACKS + 6) { fprintf(stderr,"Perl<->C inconsistency or internal error\n"); XSRETURN_UNDEF; } @@ -1732,8 +1734,9 @@ perl_fuse_main(...) #if FUSE_VERSION >= 28 fops.flag_nullpath_ok = SvIV(ST(4)); #endif /* FUSE_VERSION >= 28 */ + MY_CXT.utimens_as_array = SvIV(ST(5)); for(i=0;i