rfuse 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|
+
}
|