9 #define DEBUGf(f, a...) fprintf(stderr, "%s:%d (%i): " f,__BASE_FILE__,__LINE__,PL_stack_sp-PL_stack_base ,##a )
14 #define N_CALLBACKS 25
15 SV *_PLfuse_callbacks[N_CALLBACKS];
17 int _PLfuse_getattr(const char *file, struct stat *result) {
23 XPUSHs(sv_2mortal(newSVpv(file,strlen(file))));
25 rv = call_sv(_PLfuse_callbacks[0],G_ARRAY);
29 fprintf(stderr,"inappropriate number of returned values from getattr\n");
36 result->st_blocks = POPi;
37 result->st_blksize = POPi;
38 result->st_ctime = POPi;
39 result->st_mtime = POPi;
40 result->st_atime = POPi;
41 result->st_size = POPi;
42 result->st_rdev = POPi;
43 result->st_gid = POPi;
44 result->st_uid = POPi;
45 result->st_nlink = POPi;
46 result->st_mode = POPi;
47 /*result->st_ino =*/ POPi;
48 result->st_dev = POPi;
57 int _PLfuse_readlink(const char *file,char *buf,size_t buflen) {
67 XPUSHs(sv_2mortal(newSVpv(file,0)));
69 rv = call_sv(_PLfuse_callbacks[1],G_SCALAR);
75 if(SvTYPE(mysv) == SVt_IV || SvTYPE(mysv) == SVt_NV)
78 strncpy(buf,SvPV_nolen(mysv),buflen);
89 int _PLfuse_getdir(const char *file, fuse_dirh_t dirh, fuse_dirfil_t dirfil) {
95 XPUSHs(sv_2mortal(newSVpv(file,0)));
97 prv = call_sv(_PLfuse_callbacks[2],G_ARRAY);
104 fprintf(stderr,"getdir() handler returned nothing!\n");
113 int _PLfuse_mknod (const char *file, mode_t mode, dev_t dev) {
121 XPUSHs(sv_2mortal(newSVpv(file,0)));
122 XPUSHs(sv_2mortal(newSViv(mode)));
123 XPUSHs(sv_2mortal(newSViv(dev)));
125 rv = call_sv(_PLfuse_callbacks[3],G_SCALAR);
137 int _PLfuse_mkdir (const char *file, mode_t mode) {
142 DEBUGf("mkdir begin: %i\n",sp-PL_stack_base);
146 XPUSHs(sv_2mortal(newSVpv(file,0)));
147 XPUSHs(sv_2mortal(newSViv(mode)));
149 rv = call_sv(_PLfuse_callbacks[4],G_SCALAR);
158 DEBUGf("mkdir end: %i %i\n",sp-PL_stack_base,rv);
163 int _PLfuse_unlink (const char *file) {
168 DEBUGf("unlink begin: %i\n",sp-PL_stack_base);
172 XPUSHs(sv_2mortal(newSVpv(file,0)));
174 rv = call_sv(_PLfuse_callbacks[5],G_SCALAR);
183 DEBUGf("unlink end: %i\n",sp-PL_stack_base);
187 int _PLfuse_rmdir (const char *file) {
192 DEBUGf("rmdir begin: %i\n",sp-PL_stack_base);
196 XPUSHs(sv_2mortal(newSVpv(file,0)));
198 rv = call_sv(_PLfuse_callbacks[6],G_SCALAR);
207 DEBUGf("rmdir end: %i %i\n",sp-PL_stack_base,rv);
211 int _PLfuse_symlink (const char *file, const char *new) {
216 DEBUGf("symlink begin: %i\n",sp-PL_stack_base);
220 XPUSHs(sv_2mortal(newSVpv(file,0)));
221 XPUSHs(sv_2mortal(newSVpv(new,0)));
223 rv = call_sv(_PLfuse_callbacks[7],G_SCALAR);
232 DEBUGf("symlink end: %i\n",sp-PL_stack_base);
236 int _PLfuse_rename (const char *file, const char *new) {
241 DEBUGf("rename begin: %i\n",sp-PL_stack_base);
245 XPUSHs(sv_2mortal(newSVpv(file,0)));
246 XPUSHs(sv_2mortal(newSVpv(new,0)));
248 rv = call_sv(_PLfuse_callbacks[8],G_SCALAR);
257 DEBUGf("rename end: %i\n",sp-PL_stack_base);
261 int _PLfuse_link (const char *file, const char *new) {
266 DEBUGf("link begin: %i\n",sp-PL_stack_base);
270 XPUSHs(sv_2mortal(newSVpv(file,0)));
271 XPUSHs(sv_2mortal(newSVpv(new,0)));
273 rv = call_sv(_PLfuse_callbacks[9],G_SCALAR);
282 DEBUGf("link end: %i\n",sp-PL_stack_base);
286 int _PLfuse_chmod (const char *file, mode_t mode) {
291 DEBUGf("chmod begin: %i\n",sp-PL_stack_base);
295 XPUSHs(sv_2mortal(newSVpv(file,0)));
296 XPUSHs(sv_2mortal(newSViv(mode)));
298 rv = call_sv(_PLfuse_callbacks[10],G_SCALAR);
307 DEBUGf("chmod end: %i\n",sp-PL_stack_base);
311 int _PLfuse_chown (const char *file, uid_t uid, gid_t gid) {
316 DEBUGf("chown begin: %i\n",sp-PL_stack_base);
320 XPUSHs(sv_2mortal(newSVpv(file,0)));
321 XPUSHs(sv_2mortal(newSViv(uid)));
322 XPUSHs(sv_2mortal(newSViv(gid)));
324 rv = call_sv(_PLfuse_callbacks[11],G_SCALAR);
333 DEBUGf("chown end: %i\n",sp-PL_stack_base);
337 int _PLfuse_truncate (const char *file, off_t off) {
342 DEBUGf("truncate begin: %i\n",sp-PL_stack_base);
346 XPUSHs(sv_2mortal(newSVpv(file,0)));
347 XPUSHs(sv_2mortal(newSViv(off)));
349 rv = call_sv(_PLfuse_callbacks[12],G_SCALAR);
358 DEBUGf("truncate end: %i\n",sp-PL_stack_base);
362 int _PLfuse_utime (const char *file, struct utimbuf *uti) {
367 DEBUGf("utime begin: %i\n",sp-PL_stack_base);
371 XPUSHs(sv_2mortal(newSVpv(file,0)));
372 XPUSHs(sv_2mortal(newSViv(uti->actime)));
373 XPUSHs(sv_2mortal(newSViv(uti->modtime)));
375 rv = call_sv(_PLfuse_callbacks[13],G_SCALAR);
384 DEBUGf("utime end: %i\n",sp-PL_stack_base);
388 int _PLfuse_open (const char *file, int flags) {
393 DEBUGf("open begin: %i\n",sp-PL_stack_base);
397 XPUSHs(sv_2mortal(newSVpv(file,0)));
398 XPUSHs(sv_2mortal(newSViv(flags)));
400 rv = call_sv(_PLfuse_callbacks[14],G_SCALAR);
409 DEBUGf("open end: %i %i\n",sp-PL_stack_base,rv);
413 int _PLfuse_read (const char *file, char *buf, size_t buflen, off_t off) {
417 DEBUGf("read begin: %i\n",sp-PL_stack_base);
421 XPUSHs(sv_2mortal(newSVpv(file,0)));
422 XPUSHs(sv_2mortal(newSViv(buflen)));
423 XPUSHs(sv_2mortal(newSViv(off)));
425 rv = call_sv(_PLfuse_callbacks[15],G_SCALAR);
431 if(SvTYPE(mysv) == SVt_NV || SvTYPE(mysv) == SVt_IV)
440 croak("read() handler returned more than buflen! (%i > %i)",rv,buflen);
442 memcpy(buf,SvPV_nolen(mysv),rv);
448 DEBUGf("read end: %i %i\n",sp-PL_stack_base,rv);
452 int _PLfuse_write (const char *file, const char *buf, size_t buflen, off_t off) {
456 DEBUGf("write begin: %i\n",sp-PL_stack_base);
460 XPUSHs(sv_2mortal(newSVpv(file,0)));
461 XPUSHs(sv_2mortal(newSVpvn(buf,buflen)));
462 XPUSHs(sv_2mortal(newSViv(off)));
464 rv = call_sv(_PLfuse_callbacks[16],G_SCALAR);
473 DEBUGf("write end: %i\n",sp-PL_stack_base);
477 int _PLfuse_statfs (const char *file, struct statfs *st) {
481 DEBUGf("statfs begin: %i\n",sp-PL_stack_base);
486 rv = call_sv(_PLfuse_callbacks[17],G_ARRAY);
494 st->f_namelen = POPi;
501 croak("inappropriate number of returned values from statfs");
510 DEBUGf("statfs end: %i\n",sp-PL_stack_base);
514 int _PLfuse_flush (const char *file) {
518 DEBUGf("flush begin: %i\n",sp-PL_stack_base);
522 XPUSHs(sv_2mortal(newSVpv(file,0)));
524 rv = call_sv(_PLfuse_callbacks[18],G_SCALAR);
533 DEBUGf("flush end: %i\n",sp-PL_stack_base);
537 int _PLfuse_release (const char *file, int flags) {
541 DEBUGf("release begin: %i\n",sp-PL_stack_base);
545 XPUSHs(sv_2mortal(newSVpv(file,0)));
546 XPUSHs(sv_2mortal(newSViv(flags)));
548 rv = call_sv(_PLfuse_callbacks[19],G_SCALAR);
557 DEBUGf("release end: %i\n",sp-PL_stack_base);
561 int _PLfuse_fsync (const char *file, int flags) {
565 DEBUGf("fsync begin: %i\n",sp-PL_stack_base);
569 XPUSHs(sv_2mortal(newSVpv(file,0)));
570 XPUSHs(sv_2mortal(newSViv(flags)));
572 rv = call_sv(_PLfuse_callbacks[20],G_SCALAR);
581 DEBUGf("fsync end: %i\n",sp-PL_stack_base);
585 int _PLfuse_setxattr (const char *file, const char *name, const char *buf, size_t buflen, int flags) {
589 DEBUGf("setxattr begin: %i\n",sp-PL_stack_base);
593 XPUSHs(sv_2mortal(newSVpv(file,0)));
594 XPUSHs(sv_2mortal(newSVpv(name,0)));
595 XPUSHs(sv_2mortal(newSVpvn(buf,buflen)));
596 XPUSHs(sv_2mortal(newSViv(flags)));
598 rv = call_sv(_PLfuse_callbacks[21],G_SCALAR);
607 DEBUGf("setxattr end: %i\n",sp-PL_stack_base);
611 int _PLfuse_getxattr (const char *file, const char *name, char *buf, size_t buflen) {
615 DEBUGf("getxattr begin: %i\n",sp-PL_stack_base);
619 XPUSHs(sv_2mortal(newSVpv(file,0)));
620 XPUSHs(sv_2mortal(newSVpv(name,0)));
622 rv = call_sv(_PLfuse_callbacks[22],G_SCALAR);
630 if(SvTYPE(mysv) == SVt_NV || SvTYPE(mysv) == SVt_IV)
638 if ((rv > 0) && (buflen > 0))
643 memcpy(buf,SvPV_nolen(mysv),rv);
650 DEBUGf("getxattr end: %i\n",sp-PL_stack_base);
654 int _PLfuse_listxattr (const char *file, char *list, size_t size) {
658 DEBUGf("listxattr begin: %i\n",sp-PL_stack_base);
662 XPUSHs(sv_2mortal(newSVpv(file,0)));
664 prv = call_sv(_PLfuse_callbacks[23],G_ARRAY);
678 /* Always nul terminate */
679 if (list && (size > 0))
689 int s = SvCUR(mysv) + 1;
692 if (p && (size > 0) && (spc >= s))
694 memcpy(p,SvPV_nolen(mysv),s);
702 * If the Perl returned an error, return that.
703 * Otherwise check that the buffer was big enough.
708 if ((size > 0) && (size < total_len))
715 DEBUGf("listxattr end: %i\n",sp-PL_stack_base);
719 int _PLfuse_removexattr (const char *file, const char *name) {
723 DEBUGf("removexattr begin: %i\n",sp-PL_stack_base);
727 XPUSHs(sv_2mortal(newSVpv(file,0)));
728 XPUSHs(sv_2mortal(newSVpv(name,0)));
730 rv = call_sv(_PLfuse_callbacks[24],G_SCALAR);
739 DEBUGf("removexattr end: %i\n",sp-PL_stack_base);
743 struct fuse_operations _available_ops = {
744 getattr: _PLfuse_getattr,
745 readlink: _PLfuse_readlink,
746 getdir: _PLfuse_getdir,
747 mknod: _PLfuse_mknod,
748 mkdir: _PLfuse_mkdir,
749 unlink: _PLfuse_unlink,
750 rmdir: _PLfuse_rmdir,
751 symlink: _PLfuse_symlink,
752 rename: _PLfuse_rename,
754 chmod: _PLfuse_chmod,
755 chown: _PLfuse_chown,
756 truncate: _PLfuse_truncate,
757 utime: _PLfuse_utime,
760 write: _PLfuse_write,
761 statfs: _PLfuse_statfs,
762 flush: _PLfuse_flush,
763 release: _PLfuse_release,
764 fsync: _PLfuse_fsync,
765 setxattr: _PLfuse_setxattr,
766 getxattr: _PLfuse_getxattr,
767 listxattr: _PLfuse_listxattr,
768 removexattr: _PLfuse_removexattr,
771 MODULE = Fuse PACKAGE = Fuse
777 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};
778 int i, fd, varnum = 0, debug, have_mnt;
785 fprintf(stderr,"Perl<->C inconsistency or internal error\n");
790 mountpoint = SvPV_nolen(ST(1));
791 mountopts = SvPV_nolen(ST(2));
792 /* FIXME: reevaluate multithreading support when perl6 arrives */
793 for(i=0;i<N_CALLBACKS;i++) {
795 if((var != &PL_sv_undef) && SvROK(var)) {
796 if(SvTYPE(SvRV(var)) == SVt_PVCV) {
797 void **tmp1 = (void**)&_available_ops, **tmp2 = (void**)&fops;
799 _PLfuse_callbacks[i] = var;
801 croak("arg is not a code reference!");
804 /* FIXME: need to pass fusermount arguments */
805 fd = fuse_mount(mountpoint,mountopts);
807 croak("could not mount fuse filesystem!");
808 fuse_loop(fuse_new(fd,debug ? "debug" : NULL,&fops));