rfuse 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,140 @@
1
+ #include "file_info.h"
2
+ #include <fuse.h>
3
+
4
+ //creates a FileInfo object from an already allocated ffi
5
+ VALUE wrap_file_info(struct fuse_context *ctx, struct fuse_file_info *ffi) {
6
+ VALUE rRFuse;
7
+ VALUE rFileInfo;
8
+
9
+ VALUE rffi;
10
+
11
+ VALUE open_files;
12
+ VALUE key;
13
+
14
+ rRFuse=rb_const_get(rb_cObject,rb_intern("RFuse"));
15
+ rFileInfo=rb_const_get(rRFuse,rb_intern("FileInfo"));
16
+
17
+ rffi = Data_Wrap_Struct(rFileInfo,0,0,ffi);
18
+
19
+ //store the wrapped ffi back into the struct so we don't have to keep wrapping it
20
+ ffi->fh = rffi;
21
+
22
+ //also store it in an open_files hash on the fuse_object
23
+ //so it doesn't get GC'd
24
+ open_files = rb_iv_get(ctx->private_data,"@open_files");
25
+ key = rb_funcall(rffi,rb_intern("object_id"),0);
26
+ rb_hash_aset(open_files,key,rffi);
27
+
28
+ return rffi;
29
+ };
30
+
31
+ //returns a previously wrapped ffi
32
+ VALUE get_file_info(struct fuse_file_info *ffi) {
33
+
34
+ if (TYPE(ffi->fh) == T_DATA )
35
+ return (VALUE) ffi->fh;
36
+ else
37
+ return Qnil;
38
+
39
+ };
40
+
41
+ //Allow the FileInfo object to be GC'd
42
+ VALUE release_file_info(struct fuse_context *ctx, struct fuse_file_info *ffi)
43
+ {
44
+
45
+ if (TYPE(ffi->fh) == T_DATA) {
46
+ VALUE rffi = ffi->fh;
47
+ VALUE fuse_object = ctx->private_data;
48
+ VALUE open_files = rb_iv_get(fuse_object,"@open_files");
49
+ VALUE key = rb_funcall(rffi,rb_intern("object_id"),0);
50
+ rb_hash_delete(open_files,key);
51
+ } else {
52
+ return Qnil;
53
+ }
54
+
55
+ }
56
+
57
+ VALUE file_info_initialize(VALUE self){
58
+ return self;
59
+ }
60
+
61
+ //TODO FT: test: this _should_not_ be called, an exception would do the trick :)
62
+ VALUE file_info_new(VALUE class){
63
+ rb_raise(rb_eNotImpError, "new() not implemented (it has no use), and should not be called");
64
+ return Qnil;
65
+ }
66
+
67
+ VALUE file_info_writepage(VALUE self) {
68
+ struct fuse_file_info *f;
69
+ Data_Get_Struct(self,struct fuse_file_info,f);
70
+ return INT2FIX(f->writepage);
71
+ }
72
+
73
+ VALUE file_info_flags(VALUE self) {
74
+ struct fuse_file_info *f;
75
+ Data_Get_Struct(self,struct fuse_file_info,f);
76
+ return INT2FIX(f->flags);
77
+ }
78
+
79
+ VALUE file_info_direct(VALUE self) {
80
+ struct fuse_file_info *f;
81
+ Data_Get_Struct(self,struct fuse_file_info,f);
82
+ if (TYPE(f->direct_io) != T_NONE) {
83
+ return (VALUE) f->direct_io;
84
+ } else {
85
+ return Qnil;
86
+ }
87
+ }
88
+
89
+ VALUE file_info_direct_assign(VALUE self,VALUE value) {
90
+ struct fuse_file_info *f;
91
+ Data_Get_Struct(self,struct fuse_file_info,f);
92
+ f->direct_io = value;
93
+ return value;
94
+ }
95
+
96
+ VALUE file_info_nonseekable(VALUE self) {
97
+ struct fuse_file_info *f;
98
+ Data_Get_Struct(self,struct fuse_file_info,f);
99
+ if (TYPE(f->nonseekable) != T_NONE) {
100
+ return (VALUE) f->nonseekable;
101
+ } else {
102
+ return Qnil;
103
+ }
104
+ }
105
+
106
+ VALUE file_info_nonseekable_assign(VALUE self,VALUE value) {
107
+ struct fuse_file_info *f;
108
+ Data_Get_Struct(self,struct fuse_file_info,f);
109
+ f->nonseekable = value;
110
+ return value;
111
+ }
112
+
113
+ /*
114
+ Document-class: RFuse::FileInfo
115
+
116
+ Represents an open file (or directory) that is reused
117
+ across multiple fuse operations
118
+
119
+ */
120
+ void file_info_init(VALUE module) {
121
+ #if 0
122
+ //Trick Yardoc
123
+ module = rb_define_module("RFuse");
124
+ #endif
125
+ VALUE cFileInfo=rb_define_class_under(module,"FileInfo",rb_cObject);
126
+ rb_define_alloc_func(cFileInfo,file_info_new);
127
+ rb_define_method(cFileInfo,"initialize",file_info_initialize,0);
128
+ rb_define_method(cFileInfo,"flags",file_info_flags,0);
129
+ rb_define_method(cFileInfo,"writepage",file_info_writepage,0);
130
+ rb_define_method(cFileInfo,"direct",file_info_direct,0);
131
+ rb_define_method(cFileInfo,"direct=",file_info_direct_assign,1);
132
+ rb_define_method(cFileInfo,"nonseekable",file_info_nonseekable,0);
133
+ rb_define_method(cFileInfo,"nonseekable=",file_info_nonseekable_assign,1);
134
+
135
+ /*
136
+ Filehandle - can be any ruby object
137
+ */
138
+ rb_define_attr(cFileInfo,"fh",1,1);
139
+ return cFileInfo;
140
+ }
@@ -0,0 +1,13 @@
1
+ #include <fuse.h>
2
+ #include <ruby.h>
3
+
4
+ VALUE wrap_file_info(struct fuse_context *ctx, struct fuse_file_info *ffi);
5
+ VALUE get_file_info(struct fuse_file_info *ffi);
6
+ VALUE release_file_info(struct fuse_context *ctx, struct fuse_file_info *ffi);
7
+
8
+ VALUE file_info_initialize(VALUE self);
9
+ VALUE file_info_new(VALUE class);
10
+ VALUE file_info_flags(VALUE self);
11
+ VALUE file_info_writepage(VALUE self);
12
+
13
+ void file_info_init(VALUE module);
@@ -0,0 +1,60 @@
1
+ #include "filler.h"
2
+ #include <fuse.h>
3
+ #include "helper.h"
4
+
5
+ VALUE rfiller_initialize(VALUE self){
6
+ return self;
7
+ }
8
+
9
+ /*
10
+ * @api private Never called
11
+ */
12
+ VALUE rfiller_new(VALUE class){
13
+ VALUE self;
14
+ struct filler_t *f;
15
+ self = Data_Make_Struct(class, struct filler_t, 0,free,f);
16
+ return self;
17
+ }
18
+
19
+ /*
20
+ * Add a value into the filler
21
+ * @param [String] name a file name
22
+ * @param [Stat] stat Stat info representing the file, may be nil
23
+ * @param [Integer] offset index of next entry, or zero
24
+ *
25
+ * @return self or nil if the buffer is full
26
+ *
27
+ */
28
+ VALUE rfiller_push(VALUE self, VALUE name, VALUE stat, VALUE offset) {
29
+ struct filler_t *f;
30
+ Data_Get_Struct(self,struct filler_t,f);
31
+ //Allow nil return instead of a stat
32
+
33
+ int result;
34
+
35
+ if (NIL_P(stat)) {
36
+ result = f->filler(f->buffer,STR2CSTR(name),NULL,NUM2LONG(offset));
37
+ } else {
38
+ struct stat st;
39
+ memset(&st, 0, sizeof(st));
40
+ rstat2stat(stat,&st);
41
+ result = f->filler(f->buffer,STR2CSTR(name),&st,NUM2LONG(offset));
42
+ }
43
+
44
+ return result ? Qnil : self;
45
+ }
46
+
47
+ /*
48
+ * Document-class: RFuse::Filler
49
+ * Used by {Fuse#readdir} to collect directory entries
50
+ */
51
+ void rfiller_init(VALUE module) {
52
+
53
+ #if 0
54
+ module = rb_define_module("RFuse");
55
+ #endif
56
+ VALUE cFiller=rb_define_class_under(module,"Filler",rb_cObject);
57
+ rb_define_alloc_func(cFiller,rfiller_new);
58
+ rb_define_method(cFiller,"initialize",rfiller_initialize,0);
59
+ rb_define_method(cFiller,"push",rfiller_push,3);
60
+ }
@@ -0,0 +1,15 @@
1
+ #include <fuse.h>
2
+ #include <ruby.h>
3
+
4
+ struct filler_t {
5
+ fuse_fill_dir_t filler;
6
+ void *buffer;
7
+ fuse_dirh_t dh;
8
+ fuse_dirfil_t df;
9
+ };
10
+
11
+ VALUE rfiller_initialize(VALUE self);
12
+ VALUE rfiller_new(VALUE class);
13
+ VALUE rfiller_push(VALUE self, VALUE name, VALUE stat, VALUE offset);
14
+
15
+ void rfiller_init(VALUE module);
@@ -0,0 +1,93 @@
1
+ #include "helper.h"
2
+
3
+ char*
4
+ rb_compat_str2cstr(VALUE x)
5
+ {
6
+ return StringValuePtr(x);
7
+ }
8
+
9
+ void rstat2stat(VALUE rstat, struct stat *statbuf)
10
+ {
11
+ statbuf->st_dev = FIX2ULONG(rb_funcall(rstat,rb_intern("dev"),0));
12
+ statbuf->st_ino = FIX2ULONG(rb_funcall(rstat,rb_intern("ino"),0));
13
+ statbuf->st_mode = FIX2UINT(rb_funcall(rstat,rb_intern("mode"),0));
14
+ statbuf->st_nlink = FIX2UINT(rb_funcall(rstat,rb_intern("nlink"),0));
15
+ statbuf->st_uid = FIX2UINT(rb_funcall(rstat,rb_intern("uid"),0));
16
+ statbuf->st_gid = FIX2UINT(rb_funcall(rstat,rb_intern("gid"),0));
17
+ statbuf->st_rdev = FIX2ULONG(rb_funcall(rstat,rb_intern("rdev"),0));
18
+ statbuf->st_size = FIX2ULONG(rb_funcall(rstat,rb_intern("size"),0));
19
+ statbuf->st_blksize = NUM2ULONG(rb_funcall(rstat,rb_intern("blksize"),0));
20
+ statbuf->st_blocks = NUM2ULONG(rb_funcall(rstat,rb_intern("blocks"),0));
21
+
22
+ VALUE r_atime = rb_funcall(rstat,rb_intern("atime"),0);
23
+ VALUE r_mtime = rb_funcall(rstat,rb_intern("mtime"),0);
24
+ VALUE r_ctime = rb_funcall(rstat,rb_intern("ctime"),0);
25
+
26
+ ID to_i = rb_intern("to_i");
27
+
28
+ statbuf->st_atime = NUM2ULONG(rb_funcall(r_atime,to_i,0));
29
+ statbuf->st_mtime = NUM2ULONG(rb_funcall(r_mtime,to_i,0));
30
+ statbuf->st_ctime = NUM2ULONG(rb_funcall(r_ctime,to_i,0));
31
+
32
+ //TODO: Find out the correct way to test for nano second resolution availability
33
+ #ifdef _STATBUF_ST_NSEC
34
+ ID nsec = rb_intern("nsec");
35
+
36
+ if (rb_respond_to(r_atime,nsec))
37
+ statbuf->st_atim.tv_nsec = NUM2ULONG(rb_funcall(r_atime,nsec,0));
38
+
39
+ if (rb_respond_to(r_mtime,nsec))
40
+ statbuf->st_mtim.tv_nsec = NUM2ULONG(rb_funcall(r_mtime,nsec,0));
41
+
42
+ if (rb_respond_to(r_ctime,nsec))
43
+ statbuf->st_ctim.tv_nsec = NUM2ULONG(rb_funcall(r_ctime,nsec,0));
44
+ #endif
45
+
46
+ }
47
+
48
+ void rstatvfs2statvfs(VALUE rstatvfs,struct statvfs *statvfsbuf) {
49
+ statvfsbuf->f_bsize = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_bsize"),0));
50
+ statvfsbuf->f_frsize = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_frsize"),0));
51
+ statvfsbuf->f_blocks = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_blocks"),0));
52
+ statvfsbuf->f_bfree = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_bfree"),0));
53
+ statvfsbuf->f_bavail = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_bavail"),0));
54
+ statvfsbuf->f_files = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_files"),0));
55
+ statvfsbuf->f_ffree = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_ffree"),0));
56
+ statvfsbuf->f_favail = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_favail"),0));
57
+ statvfsbuf->f_fsid = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_fsid"),0));
58
+ statvfsbuf->f_flag = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_flag"),0));
59
+ statvfsbuf->f_namemax = FIX2ULONG(rb_funcall(rstatvfs,rb_intern("f_namemax"),0));
60
+ }
61
+
62
+ void rfuseconninfo2fuseconninfo(VALUE rfuseconninfo,struct fuse_conn_info *fuseconninfo) {
63
+ fuseconninfo->proto_major = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("proto_major"),0));
64
+ fuseconninfo->proto_minor = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("proto_minor"),0));
65
+ fuseconninfo->async_read = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("async_read"),0));
66
+ fuseconninfo->max_write = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("max_write"),0));
67
+ fuseconninfo->max_readahead = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("max_readahead"),0));
68
+ fuseconninfo->capable = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("capable"),0));
69
+ fuseconninfo->want = FIX2UINT(rb_funcall(rfuseconninfo,rb_intern("want"),0));
70
+ }
71
+
72
+ struct fuse_args * rarray2fuseargs(VALUE rarray){
73
+
74
+ Check_Type(rarray, T_ARRAY);
75
+ struct fuse_args *args = malloc(sizeof(struct fuse_args));
76
+ args->argc = RARRAY_LEN(rarray) + 1;
77
+ args->argv = malloc((args->argc + 1) * sizeof(char *));
78
+ args->allocated = 1;
79
+
80
+ int i;
81
+ VALUE v;
82
+
83
+ args->argv[0] = strdup("");
84
+
85
+ for(i = 0; i < args->argc - 1; i++) {
86
+ v = RARRAY_PTR(rarray)[i];
87
+ Check_Type(v, T_STRING);
88
+ args->argv[i+1] = strdup(rb_string_value_ptr(&v)); //STR2CSTR(RSTRING(v));
89
+ }
90
+ args->argv[args->argc] = NULL;
91
+
92
+ return args;
93
+ }
@@ -0,0 +1,22 @@
1
+ #include <sys/stat.h>
2
+ #include <sys/statvfs.h>
3
+ #include <ruby.h>
4
+ #include <fuse.h>
5
+
6
+ #ifndef _RHUSE_HELPER_H
7
+ #define _RHUSE_HELPER_H
8
+
9
+ #define STR2CSTR(x) rb_compat_str2cstr(x)
10
+ char *rb_compat_str2cstr(VALUE);
11
+
12
+ void rstat2stat(VALUE rstat,struct stat *statbuf);
13
+ void rstatvfs2statvfs(VALUE rstatvfs,struct statvfs *statvfsbuf);
14
+ void rfuseconninfo2fuseconninfo(VALUE rfuseconninfo,struct fuse_conn_info *fuseconninfo);
15
+ struct fuse_args * rarray2fuseargs(VALUE rarray);
16
+
17
+ #if defined(RUBY_VERSION) && RUBY_VERSION >= 19
18
+ #define STR2CSTR(X) StringValuePtr(X)
19
+ #endif
20
+
21
+
22
+ #endif
@@ -0,0 +1,84 @@
1
+ #include "intern_rfuse.h"
2
+ #include <fuse/fuse_lowlevel.h>
3
+ #include <stdio.h>
4
+ #include <stdlib.h>
5
+ #include <string.h>
6
+
7
+ struct intern_fuse *intern_fuse_new() {
8
+ struct intern_fuse *inf;
9
+ inf = (struct intern_fuse *) malloc(sizeof(struct intern_fuse));
10
+ memset(inf, 0, sizeof(*inf));
11
+ memset(&inf->fuse_op, 0, sizeof(struct fuse_operations));
12
+ return inf;
13
+ }
14
+
15
+
16
+ int intern_fuse_destroy(struct intern_fuse *inf){
17
+ //you have to take care, that fuse is unmounted yourself!
18
+ if(inf->fuse)
19
+ fuse_destroy(inf->fuse);
20
+ if(inf->mountpoint)
21
+ free(inf->mountpoint);
22
+ free(inf);
23
+ return 0;
24
+ }
25
+
26
+ int intern_fuse_init(
27
+ struct intern_fuse *inf,
28
+ struct fuse_args *args,
29
+ void* user_data
30
+ )
31
+ {
32
+ struct fuse_chan* fc;
33
+ int res;
34
+
35
+ char* mountpoint;
36
+ mountpoint = inf->mountpoint;
37
+ fc = fuse_mount(mountpoint,args);
38
+
39
+ if (fc == NULL) {
40
+ return -1;
41
+ }
42
+
43
+ inf->fuse=fuse_new(fc, args, &(inf->fuse_op), sizeof(struct fuse_operations), user_data);
44
+ if (inf->fuse == NULL) {
45
+ fuse_unmount(inf->mountpoint, fc);
46
+ return -1;
47
+ }
48
+
49
+ inf->fc = fc;
50
+
51
+ return 0;
52
+ }
53
+
54
+ // Return the /dev/fuse file descriptor for use with IO.select
55
+ int intern_fuse_fd(struct intern_fuse *inf)
56
+ {
57
+ if (inf->fc == NULL) {
58
+ return -1;
59
+ }
60
+
61
+ struct fuse_chan *fc = inf->fc;
62
+ return fuse_chan_fd(fc);
63
+ }
64
+
65
+ //Process one fuse command (ie after IO.select)
66
+ int intern_fuse_process(struct intern_fuse *inf)
67
+ {
68
+ if (inf->fuse == NULL) {
69
+ return -1;
70
+ }
71
+
72
+ if (fuse_exited(inf->fuse)) {
73
+ return -1;
74
+ }
75
+
76
+ struct fuse_cmd *cmd;
77
+ cmd = fuse_read_cmd(inf->fuse);
78
+
79
+ if (cmd != NULL) {
80
+ fuse_process_cmd(inf->fuse, cmd);
81
+ }
82
+
83
+ return 0;
84
+ }
@@ -0,0 +1,22 @@
1
+ #include <fuse.h>
2
+
3
+ #define MOUNTNAME_MAX 1024
4
+
5
+ struct intern_fuse {
6
+ struct fuse_chan *fc;
7
+ struct fuse *fuse;
8
+ struct fuse_operations fuse_op;
9
+ char *mountpoint;
10
+ };
11
+
12
+ struct intern_fuse *intern_fuse_new();
13
+
14
+ int intern_fuse_init(
15
+ struct intern_fuse *inf,
16
+ struct fuse_args *args,
17
+ void *user_data
18
+ );
19
+
20
+ int intern_fuse_fd(struct intern_fuse *inf);
21
+ int intern_fuse_process(struct intern_fuse *inf);
22
+ int intern_fuse_destroy(struct intern_fuse *inf);
@@ -0,0 +1,54 @@
1
+ #include <ruby.h>
2
+ #include <fuse.h>
3
+
4
+ #include "pollhandle.h"
5
+
6
+ static int pollhandle_destroy(struct fuse_pollhandle *ph)
7
+ {
8
+ fuse_pollhandle_destroy(ph);
9
+ return 0;
10
+ }
11
+
12
+ VALUE pollhandle_new(VALUE class)
13
+ {
14
+ rb_raise(rb_eNotImpError, "new() not implemented (it has no use), and should not be called");
15
+ return Qnil;
16
+ }
17
+
18
+ VALUE pollhandle_initialize(VALUE self)
19
+ {
20
+ return self;
21
+ }
22
+
23
+ VALUE pollhandle_notify_poll(VALUE self)
24
+ {
25
+ struct fuse_pollhandle *ph;
26
+ Data_Get_Struct(self, struct fuse_pollhandle, ph);
27
+ return INT2FIX(fuse_notify_poll(ph));
28
+ }
29
+
30
+ VALUE wrap_pollhandle(struct fuse_pollhandle *ph)
31
+ {
32
+ VALUE rRFuse;
33
+ VALUE rPollHandle;
34
+
35
+ rRFuse = rb_const_get(rb_cObject,rb_intern("RFuse"));
36
+ rPollHandle = rb_const_get(rRFuse,rb_intern("PollHandle"));
37
+
38
+ // We need a mark function here to ensure the ph is not GC'd
39
+ // between poll and notify_poll
40
+ return Data_Wrap_Struct(rPollHandle, NULL, pollhandle_destroy, ph);
41
+
42
+ }
43
+
44
+ VALUE pollhandle_init(VALUE module)
45
+ {
46
+ VALUE cPollHandle = rb_define_class_under(module,"PollHandle",rb_cObject);
47
+
48
+ rb_define_alloc_func(cPollHandle,pollhandle_new);
49
+
50
+ rb_define_method(cPollHandle,"initialize",pollhandle_initialize,0);
51
+ rb_define_method(cPollHandle,"notifyPoll",pollhandle_notify_poll,0);
52
+
53
+ return cPollHandle;
54
+ }
@@ -0,0 +1,10 @@
1
+ #include <fuse.h>
2
+ #include <ruby.h>
3
+
4
+ VALUE wrap_pollhandle(struct fuse_pollhandle *ph);
5
+
6
+ VALUE pollhandle_new(VALUE class);
7
+ VALUE pollhandle_initialize(VALUE self);
8
+ VALUE pollhandle_notify_poll(VALUE self);
9
+
10
+ VALUE pollhandle_init(VALUE module);