Filesys-Fuse3
view release on metacpan or search on metacpan
DEBUGf("rename begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
XPUSHs(sv_2mortal(newSVpv(new,0)));
PUTBACK;
rv = call_sv(MY_CXT.callback[CB_IDX_RENAME],G_SCALAR);
SPAGAIN;
rv = (rv ? POPi : 0);
FREETMPS;
LEAVE;
PUTBACK;
DEBUGf("rename end: %i\n",rv);
FUSE_CONTEXT_POST;
return rv;
}
int _PLfuse_link (const char *file, const char *new) {
int rv;
FUSE_CONTEXT_PRE;
DEBUGf("link begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
XPUSHs(sv_2mortal(newSVpv(new,0)));
PUTBACK;
rv = call_sv(MY_CXT.callback[CB_IDX_LINK],G_SCALAR);
SPAGAIN;
rv = (rv ? POPi : 0);
FREETMPS;
LEAVE;
PUTBACK;
DEBUGf("link end: %i\n",rv);
FUSE_CONTEXT_POST;
return rv;
}
int _PLfuse_chmod (const char *file, mode_t mode, struct fuse_file_info *fi) {
int rv;
FUSE_CONTEXT_PRE;
DEBUGf("chmod begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
XPUSHs(sv_2mortal(newSViv(mode)));
PUTBACK;
rv = call_sv(MY_CXT.callback[CB_IDX_CHMOD],G_SCALAR);
SPAGAIN;
rv = (rv ? POPi : 0);
FREETMPS;
LEAVE;
PUTBACK;
DEBUGf("chmod end: %i\n",rv);
FUSE_CONTEXT_POST;
return rv;
}
int _PLfuse_chown (const char *file, uid_t uid, gid_t gid, struct fuse_file_info *fi) {
int rv;
FUSE_CONTEXT_PRE;
DEBUGf("chown begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
XPUSHs(sv_2mortal(newSViv(uid)));
XPUSHs(sv_2mortal(newSViv(gid)));
PUTBACK;
rv = call_sv(MY_CXT.callback[CB_IDX_CHOWN],G_SCALAR);
SPAGAIN;
rv = (rv ? POPi : 0);
FREETMPS;
LEAVE;
PUTBACK;
DEBUGf("chown end: %i\n",rv);
FUSE_CONTEXT_POST;
return rv;
}
int _PLfuse_truncate (const char *file, off_t off, struct fuse_file_info *fi) {
int rv;
#ifndef PERL_HAS_64BITINT
char *temp;
#endif
FUSE_CONTEXT_PRE;
DEBUGf("truncate begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
#ifdef PERL_HAS_64BITINT
XPUSHs(sv_2mortal(newSViv(off)));
#else
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[CB_IDX_TRUNCATE],G_SCALAR);
SPAGAIN;
rv = (rv ? POPi : 0);
FREETMPS;
LEAVE;
PUTBACK;
DEBUGf("truncate end: %i\n",rv);
FUSE_CONTEXT_POST;
return rv;
}
int _PLfuse_open (const char *file, struct fuse_file_info *fi) {
int rv;
int flags = fi->flags;
HV *fihash;
FUSE_CONTEXT_PRE;
DEBUGf("open begin\n");
ENTER;
SAVETMPS;
PUSHMARK(SP);
XPUSHs(sv_2mortal(newSVpv(file,0)));
XPUSHs(sv_2mortal(newSViv(flags)));
/* Create a hashref containing the details from fi
* which we can look at or modify.
*/
fi->fh = 0; /* Ensure it starts with 0 - important if they don't set it */
fihash = newHV();
(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, "nonseekable", 11, newSViv(fi->nonseekable), 0);
XPUSHs(sv_2mortal(newRV_noinc((SV*) fihash)));
/* All hashref things done */
PUTBACK;
/* Open called with filename, flags */
rv = call_sv(MY_CXT.callback[CB_IDX_OPEN],G_ARRAY);
void
perl_fuse3_main(...)
PREINIT:
struct fuse_operations fops;
struct fuse *fuse_handle;
int i, debug;
char *mountpoint;
char *mountopts;
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
dMY_CXT;
INIT:
if(items != N_CALLBACKS + N_FLAGS) {
fprintf(stderr,"Perl<->C inconsistency or internal error\n");
XSRETURN_UNDEF;
}
memset(&fops, 0, sizeof(struct fuse_operations));
CODE:
debug = SvIV(ST(ARG_IDX_DEBUG));
MY_CXT.threaded = SvIV(ST(ARG_IDX_THREADED));
MY_CXT.handles = (HV*)(sv_2mortal((SV*)(newHV())));
if(MY_CXT.threaded) {
#ifdef FUSE_USE_ITHREADS
master_interp = aTHX;
MUTEX_INIT(&MY_CXT.mutex);
SvSHARE((SV*)(MY_CXT.handles));
#else
fprintf(stderr,"FUSE warning: Your script has requested multithreaded "
"mode, but your perl was not built with a supported "
"thread model. Threads are disabled.\n");
MY_CXT.threaded = 0;
#endif
}
mountpoint = SvPV_nolen(ST(ARG_IDX_MOUNTPOINT));
mountopts = SvPV_nolen(ST(ARG_IDX_MOUNTOPTS));
MY_CXT.nullpath_ok = SvIV(ST(ARG_IDX_NULLPATH_OK));
MY_CXT.utimens_as_array = SvIV(ST(ARG_IDX_UTIMENS_AS_ARRAY));
for(i=0;i<N_CALLBACKS;i++) {
SV *var = ST(i+N_FLAGS);
/* allow symbolic references, or real code references. */
if(SvOK(var) && (SvPOK(var) || (SvROK(var) && SvTYPE(SvRV(var)) == SVt_PVCV))) {
// register user callback. This is where a mismatch
// between Fuse.pm:@names list and callback_index enum
// will spoil your fun
MY_CXT.callback[i] = var;
// Map Perl @names index to the correct fuse_operations
// field, if the callback was defined by user.
switch(i) {
case CB_IDX_GETATTR : fops.getattr = _PLfuse_getattr; break;
case CB_IDX_READLINK : fops.readlink = _PLfuse_readlink; break;
case CB_IDX_MKNOD : fops.mknod = _PLfuse_mknod; break;
case CB_IDX_MKDIR : fops.mkdir = _PLfuse_mkdir; break;
case CB_IDX_UNLINK : fops.unlink = _PLfuse_unlink; break;
case CB_IDX_RMDIR : fops.rmdir = _PLfuse_rmdir; break;
case CB_IDX_SYMLINK : fops.symlink = _PLfuse_symlink; break;
case CB_IDX_RENAME : fops.rename = _PLfuse_rename; break;
case CB_IDX_LINK : fops.link = _PLfuse_link; break;
case CB_IDX_CHMOD : fops.chmod = _PLfuse_chmod; break;
case CB_IDX_CHOWN : fops.chown = _PLfuse_chown; break;
case CB_IDX_TRUNCATE : fops.truncate = _PLfuse_truncate; break;
case CB_IDX_OPEN : fops.open = _PLfuse_open; break;
case CB_IDX_READ : fops.read = _PLfuse_read; break;
case CB_IDX_WRITE : fops.write = _PLfuse_write; break;
case CB_IDX_STATFS : fops.statfs = _PLfuse_statfs; break;
case CB_IDX_FLUSH : fops.flush = _PLfuse_flush; break;
case CB_IDX_RELEASE : fops.release = _PLfuse_release; break;
case CB_IDX_FSYNC : fops.fsync = _PLfuse_fsync; break;
case CB_IDX_SETXATTR : fops.setxattr = _PLfuse_setxattr; break;
case CB_IDX_GETXATTR : fops.getxattr = _PLfuse_getxattr; break;
case CB_IDX_LISTXATTR : fops.listxattr = _PLfuse_listxattr; break;
case CB_IDX_REMOVEXATTR : fops.removexattr = _PLfuse_removexattr; break;
case CB_IDX_OPENDIR : fops.opendir = _PLfuse_opendir; break;
case CB_IDX_READDIR : fops.readdir = _PLfuse_readdir; break;
case CB_IDX_RELEASEDIR : fops.releasedir = _PLfuse_releasedir; break;
case CB_IDX_FSYNCDIR : fops.fsyncdir = _PLfuse_fsyncdir; break;
case CB_IDX_INIT : fops.init = _PLfuse_init; break;
case CB_IDX_DESTROY : fops.destroy = _PLfuse_destroy; break;
case CB_IDX_ACCESS : fops.access = _PLfuse_access; break;
case CB_IDX_CREATE : fops.create = _PLfuse_create; break;
case CB_IDX_LOCK : fops.lock = _PLfuse_lock; break;
case CB_IDX_UTIMENS : fops.utimens = _PLfuse_utimens; break;
case CB_IDX_BMAP : fops.bmap = _PLfuse_bmap; break;
case CB_IDX_IOCTL : fops.ioctl = _PLfuse_ioctl; break;
case CB_IDX_POLL : fops.poll = _PLfuse_poll; break;
case CB_IDX_WRITE_BUF : fops.write_buf = _PLfuse_write_buf; break;
case CB_IDX_READ_BUF : fops.read_buf = _PLfuse_read_buf; break;
case CB_IDX_FLOCK : fops.flock = _PLfuse_flock; break;
case CB_IDX_FALLOCATE : fops.fallocate = _PLfuse_fallocate; break;
default: break;
}
} else if(SvOK(var)) {
croak("invalid callback (%i) passed to perl_fuse_main "
"(%s is not a string, code ref, or undef).\n",
i+N_FLAGS,SvPVbyte_nolen(var));
} else {
MY_CXT.callback[i] = NULL;
}
}
/*
* XXX: What comes here is just a ridiculous use of the option parsing API
* 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 || 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");
}
if (debug && fuse_opt_add_arg(&args, "-d") == -1) {
fuse_opt_free_args(&args);
croak("out of memory\n");
}
fuse_handle = fuse_new(&args, &fops, sizeof(fops), NULL);
if (fuse_handle == NULL)
( run in 0.749 second using v1.01-cache-2.11-cpan-71847e10f99 )