Filesys-Fuse3

 view release on metacpan or  search on metacpan

Fuse3.xs  view on Meta::CPAN

	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);

Fuse3.xs  view on Meta::CPAN


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 )