rfuse 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/CHANGES.md +40 -0
- data/Gemfile +4 -0
- data/LICENSE +340 -0
- data/README.md +61 -0
- data/Rakefile +12 -0
- data/ext/.gitignore +2 -0
- data/ext/rfuse/bufferwrapper.c +48 -0
- data/ext/rfuse/bufferwrapper.h +10 -0
- data/ext/rfuse/context.c +70 -0
- data/ext/rfuse/context.h +5 -0
- data/ext/rfuse/extconf.rb +12 -0
- data/ext/rfuse/file_info.c +140 -0
- data/ext/rfuse/file_info.h +13 -0
- data/ext/rfuse/filler.c +60 -0
- data/ext/rfuse/filler.h +15 -0
- data/ext/rfuse/helper.c +93 -0
- data/ext/rfuse/helper.h +22 -0
- data/ext/rfuse/intern_rfuse.c +84 -0
- data/ext/rfuse/intern_rfuse.h +22 -0
- data/ext/rfuse/pollhandle.c +54 -0
- data/ext/rfuse/pollhandle.h +10 -0
- data/ext/rfuse/rfuse.c +2045 -0
- data/ext/rfuse/rfuse.h +3 -0
- data/ext/rfuse/rfuse_mod.c +12 -0
- data/lib/rfuse/version.rb +3 -0
- data/lib/rfuse-ng.rb +1 -0
- data/lib/rfuse.rb +211 -0
- data/lib/rfuse_ng.rb +3 -0
- data/rfuse.gemspec +26 -0
- data/sample/test-ruby.rb +339 -0
- data/spec/basic_spec.rb +176 -0
- data/spec/fuse_file_info_spec.rb +46 -0
- data/spec/ruby_loop_spec.rb +65 -0
- data/spec/spec_helper.rb +51 -0
- data/spec/xattr_spec.rb +39 -0
- metadata +164 -0
@@ -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);
|
data/ext/rfuse/filler.c
ADDED
@@ -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
|
+
}
|
data/ext/rfuse/filler.h
ADDED
@@ -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);
|
data/ext/rfuse/helper.c
ADDED
@@ -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
|
+
}
|
data/ext/rfuse/helper.h
ADDED
@@ -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
|
+
}
|