P
Peter Schrammel
Hi,
I try to implement an interface for fuse with ruby but fail to a strange
error.
You probably won't try this code because you'd have to install fuse to
test it so I give some comments:
I'd like to implement this as an extension so the testcode should look
like this:
#!/usr/bin/ruby
require("RFuse")
class RFuse
def getdir(path,filler)
Dir.foreach(path) {|x| filler.push(x,8)}
end
def getattr(path)
end
end
fo=RFuse.new
begin
fo.main
rescue
f=File.new("/tmp/error","w+")
f.puts "Error:" + $!
f.close
end
The user should just extend the class with some methods which will be
called back by fuse. So I have to wrap the callbacks. The interesting
line is at ***.
#ifdef linux
/* For pread()/pwrite() */
#define _XOPEN_SOURCE 500
#endif
//FOR LINUX ONLY
#include <linux/stat.h>
#include <ruby.h>
#include <fuse.h>
#include <errno.h>
#include <sys/statfs.h>
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
//This is a wrapper around the filler callback function
struct fill_t {
fuse_dirfil_t filler;
fuse_dirh_t handler;
};
static VALUE rfill_new(VALUE class){
VALUE self;
struct fill_t *filler;
self = Data_Make_Struct(class, struct fill_t, 0,free,filler);
return self;
}
static VALUE rfill_push(VALUE self,VALUE name, VALUE type) {
struct fill_t *fill;
Data_Get_Struct(self,struct fill_t,fill);
fill->filler(fill->handler,STR2CSTR(name),NUM2INT(type));
return self;
}
//------------------
static VALUE global_self; //TODO: have to avoid global vars
//call getdir with that an RFiller object
static int rf_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t f)
{
VALUE rfiller_class;
VALUE rfiller_instance;
struct fill_t *fillerc;
rfiller_class=rb_const_get(rb_cObject,rb_intern("RFiller"));
//***the following line seems to be the problem. If I comment everything
out between here and "return 0" it runs okay... though nothing happens.
rfiller_instance=rb_funcall(rfiller_class,rb_intern("new"),0);
//BTW: I can't do the rb_class_new_instance here STRANGE!
//***commenting out from here gives me strange errors (see bellow)
rb_gc_register_address(&rfiller_instance);//Do I need this?
Data_Get_Struct(rfiller_instance,struct fill_t,fillerc);
fillerc->filler=f;//Init the filler by hand....not nice...
fillerc->handler=h;
rb_funcall(global_self,rb_intern("getdir"),2,rb_str_new2(path),rfiller_instance);
//destroy the filler...
rb_gc_unregister_address(&rfiller_instance);
return 0;
}
//calls getattr with path and expects a File::Stat back
static int rf_getattr(const char *path, struct stat *stbuf)
{
int res; //For testing only
res = lstat(path, stbuf);
return 0;
}
static VALUE rf_main(VALUE self){
char* argv[2];
int ret;
argv[0]="test-rfuse";
argv[1]="/tmp/fuse";
struct fuse_operations *fuseop;
Data_Get_Struct(self,struct fuse_operations,fuseop);
ret = fuse_main(2,argv,fuseop);
return Qnil;
}
static VALUE rf_init(VALUE self){
return self;
}
static VALUE rf_new(VALUE class){
VALUE self;
struct fuse_operations *fuseop;
self = Data_Make_Struct(class, struct fuse_operations, 0,free,fuseop);
fuseop->getattr=rf_getattr;
fuseop->getdir=rf_getdir;
rb_obj_call_init(self,0,0);
global_self=self; //TODO: hide this...
return self;
}
void Init_RFuse() {
VALUE cRFuse=rb_define_class("RFuse",rb_cObject);
rb_define_singleton_method(cRFuse,"new",rf_new,0);
rb_define_method(cRFuse,"initialize",rf_init,0);
rb_define_method(cRFuse,"main",rf_main,0);
VALUE cRFiller=rb_define_class("RFiller",rb_cObject);
rb_define_singleton_method(cRFiller,"new",rfill_new,0);
//rb_define_method(cRFiller,"initialize",rfill_init,0);
rb_define_method(cRFiller,"push",rfill_push,2);
// rb_define_method(cRFiller,"test",rfill_test,0);
}
After starting the progam and doing some (=up to 25) "ls /tmp/fuse" the
programm crashes
cat /tmp/error says:
Error:stack level too deep
I think that I missed some cleanupcode...
Help I very much appreciated (my C isn't the best).
The interface of fuse is at:
http://cvs.sourceforge.net/viewcvs.py/fuse/fuse/include/fuse.h?rev=1.61&view=auto
Bye
Peter
I try to implement an interface for fuse with ruby but fail to a strange
error.
You probably won't try this code because you'd have to install fuse to
test it so I give some comments:
I'd like to implement this as an extension so the testcode should look
like this:
#!/usr/bin/ruby
require("RFuse")
class RFuse
def getdir(path,filler)
Dir.foreach(path) {|x| filler.push(x,8)}
end
def getattr(path)
end
end
fo=RFuse.new
begin
fo.main
rescue
f=File.new("/tmp/error","w+")
f.puts "Error:" + $!
f.close
end
The user should just extend the class with some methods which will be
called back by fuse. So I have to wrap the callbacks. The interesting
line is at ***.
#ifdef linux
/* For pread()/pwrite() */
#define _XOPEN_SOURCE 500
#endif
//FOR LINUX ONLY
#include <linux/stat.h>
#include <ruby.h>
#include <fuse.h>
#include <errno.h>
#include <sys/statfs.h>
#ifdef HAVE_SETXATTR
#include <sys/xattr.h>
#endif
//This is a wrapper around the filler callback function
struct fill_t {
fuse_dirfil_t filler;
fuse_dirh_t handler;
};
static VALUE rfill_new(VALUE class){
VALUE self;
struct fill_t *filler;
self = Data_Make_Struct(class, struct fill_t, 0,free,filler);
return self;
}
static VALUE rfill_push(VALUE self,VALUE name, VALUE type) {
struct fill_t *fill;
Data_Get_Struct(self,struct fill_t,fill);
fill->filler(fill->handler,STR2CSTR(name),NUM2INT(type));
return self;
}
//------------------
static VALUE global_self; //TODO: have to avoid global vars
//call getdir with that an RFiller object
static int rf_getdir(const char *path, fuse_dirh_t h, fuse_dirfil_t f)
{
VALUE rfiller_class;
VALUE rfiller_instance;
struct fill_t *fillerc;
rfiller_class=rb_const_get(rb_cObject,rb_intern("RFiller"));
//***the following line seems to be the problem. If I comment everything
out between here and "return 0" it runs okay... though nothing happens.
rfiller_instance=rb_funcall(rfiller_class,rb_intern("new"),0);
//BTW: I can't do the rb_class_new_instance here STRANGE!
//***commenting out from here gives me strange errors (see bellow)
rb_gc_register_address(&rfiller_instance);//Do I need this?
Data_Get_Struct(rfiller_instance,struct fill_t,fillerc);
fillerc->filler=f;//Init the filler by hand....not nice...
fillerc->handler=h;
rb_funcall(global_self,rb_intern("getdir"),2,rb_str_new2(path),rfiller_instance);
//destroy the filler...
rb_gc_unregister_address(&rfiller_instance);
return 0;
}
//calls getattr with path and expects a File::Stat back
static int rf_getattr(const char *path, struct stat *stbuf)
{
int res; //For testing only
res = lstat(path, stbuf);
return 0;
}
static VALUE rf_main(VALUE self){
char* argv[2];
int ret;
argv[0]="test-rfuse";
argv[1]="/tmp/fuse";
struct fuse_operations *fuseop;
Data_Get_Struct(self,struct fuse_operations,fuseop);
ret = fuse_main(2,argv,fuseop);
return Qnil;
}
static VALUE rf_init(VALUE self){
return self;
}
static VALUE rf_new(VALUE class){
VALUE self;
struct fuse_operations *fuseop;
self = Data_Make_Struct(class, struct fuse_operations, 0,free,fuseop);
fuseop->getattr=rf_getattr;
fuseop->getdir=rf_getdir;
rb_obj_call_init(self,0,0);
global_self=self; //TODO: hide this...
return self;
}
void Init_RFuse() {
VALUE cRFuse=rb_define_class("RFuse",rb_cObject);
rb_define_singleton_method(cRFuse,"new",rf_new,0);
rb_define_method(cRFuse,"initialize",rf_init,0);
rb_define_method(cRFuse,"main",rf_main,0);
VALUE cRFiller=rb_define_class("RFiller",rb_cObject);
rb_define_singleton_method(cRFiller,"new",rfill_new,0);
//rb_define_method(cRFiller,"initialize",rfill_init,0);
rb_define_method(cRFiller,"push",rfill_push,2);
// rb_define_method(cRFiller,"test",rfill_test,0);
}
After starting the progam and doing some (=up to 25) "ls /tmp/fuse" the
programm crashes
cat /tmp/error says:
Error:stack level too deep
I think that I missed some cleanupcode...
Help I very much appreciated (my C isn't the best).
The interface of fuse is at:
http://cvs.sourceforge.net/viewcvs.py/fuse/fuse/include/fuse.h?rev=1.61&view=auto
Bye
Peter