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
data/ext/rfuse/rfuse.c
ADDED
@@ -0,0 +1,2045 @@
|
|
1
|
+
#ifdef linux
|
2
|
+
/* For pread()/pwrite() */
|
3
|
+
#define _XOPEN_SOURCE 500
|
4
|
+
#endif
|
5
|
+
//FOR LINUX ONLY
|
6
|
+
#include <linux/stat.h>
|
7
|
+
#include <linux/kdev_t.h>
|
8
|
+
|
9
|
+
#include <ruby.h>
|
10
|
+
#include <fuse.h>
|
11
|
+
#include <errno.h>
|
12
|
+
#include <sys/statfs.h>
|
13
|
+
//#ifdef HAVE_SETXATTR
|
14
|
+
#include <sys/xattr.h>
|
15
|
+
//#endif
|
16
|
+
|
17
|
+
#include <ruby/encoding.h>
|
18
|
+
#include "helper.h"
|
19
|
+
#include "intern_rfuse.h"
|
20
|
+
#include "filler.h"
|
21
|
+
#include "context.h"
|
22
|
+
|
23
|
+
#include "file_info.h"
|
24
|
+
#include "pollhandle.h"
|
25
|
+
#include "bufferwrapper.h"
|
26
|
+
|
27
|
+
|
28
|
+
static VALUE mRFuse;
|
29
|
+
static VALUE eRFuse_Error;
|
30
|
+
|
31
|
+
static int unsafe_return_error(VALUE *args)
|
32
|
+
{
|
33
|
+
|
34
|
+
if (rb_respond_to(rb_errinfo(),rb_intern("errno"))) {
|
35
|
+
//We expect these and they get passed on the fuse so be quiet...
|
36
|
+
return rb_funcall(rb_errinfo(),rb_intern("errno"),0);
|
37
|
+
} else {
|
38
|
+
VALUE info;
|
39
|
+
info = rb_inspect(rb_errinfo());
|
40
|
+
printf ("ERROR: Exception %s not an Errno:: !respond_to?(:errno) \n",STR2CSTR(info));
|
41
|
+
//We need the ruby_errinfo backtrace not fuse.loop ... rb_backtrace();
|
42
|
+
VALUE bt_ary = rb_funcall(rb_errinfo(), rb_intern("backtrace"),0);
|
43
|
+
int c;
|
44
|
+
for (c=0;c<RARRAY_LEN(bt_ary);c++) {
|
45
|
+
printf("%s\n",RSTRING_PTR(RARRAY_PTR(bt_ary)[c]));
|
46
|
+
}
|
47
|
+
return Qnil;
|
48
|
+
}
|
49
|
+
}
|
50
|
+
|
51
|
+
static int return_error(int def_error)
|
52
|
+
{
|
53
|
+
/*if the raised error has a method errno the return that value else
|
54
|
+
return def(ault)_error */
|
55
|
+
VALUE res;
|
56
|
+
int error = 0;
|
57
|
+
res=rb_protect((VALUE (*)())unsafe_return_error,Qnil,&error);
|
58
|
+
if (error)
|
59
|
+
{
|
60
|
+
//something went wrong resolving the exception
|
61
|
+
printf ("ERROR: Exception in exception!\n");
|
62
|
+
return def_error;
|
63
|
+
}
|
64
|
+
else
|
65
|
+
{
|
66
|
+
return NIL_P(res) ? def_error : FIX2INT(res);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
//Every call needs this stuff
|
71
|
+
static void init_context_path_args(VALUE *args,struct fuse_context *ctx,const char *path)
|
72
|
+
{
|
73
|
+
args[0] = ctx->private_data;
|
74
|
+
args[1] = wrap_context(ctx);
|
75
|
+
args[2] = rb_str_new2(path);
|
76
|
+
rb_enc_associate(args[2],rb_filesystem_encoding());
|
77
|
+
}
|
78
|
+
/*
|
79
|
+
@overload readdir(context,path,filler,offset,ffi)
|
80
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#0f634deda31d1e1c42664585ae820076 readdir}
|
81
|
+
|
82
|
+
List contents of a directory
|
83
|
+
|
84
|
+
@param [Context] context
|
85
|
+
@param [String] path
|
86
|
+
@param [Filler] filler
|
87
|
+
@param [Fixnum] offset
|
88
|
+
@param [FileInfo] ffi
|
89
|
+
|
90
|
+
@return [void]
|
91
|
+
@raise [Errno]
|
92
|
+
*/
|
93
|
+
static VALUE unsafe_readdir(VALUE *args)
|
94
|
+
{
|
95
|
+
return rb_funcall3(args[0],rb_intern("readdir"),5,&args[1]);
|
96
|
+
}
|
97
|
+
|
98
|
+
static int rf_readdir(const char *path, void *buf,
|
99
|
+
fuse_fill_dir_t filler, off_t offset,struct fuse_file_info *ffi)
|
100
|
+
{
|
101
|
+
VALUE fuse_module;
|
102
|
+
VALUE rfiller_class;
|
103
|
+
VALUE rfiller_instance;
|
104
|
+
struct filler_t *fillerc;
|
105
|
+
VALUE args[6];
|
106
|
+
VALUE res;
|
107
|
+
int error = 0;
|
108
|
+
|
109
|
+
struct fuse_context *ctx=fuse_get_context();
|
110
|
+
init_context_path_args(args,ctx,path);
|
111
|
+
|
112
|
+
//create a filler object
|
113
|
+
fuse_module = rb_const_get(rb_cObject, rb_intern("RFuse"));
|
114
|
+
rfiller_class=rb_const_get(fuse_module,rb_intern("Filler"));
|
115
|
+
rfiller_instance=rb_funcall(rfiller_class,rb_intern("new"),0);
|
116
|
+
Data_Get_Struct(rfiller_instance,struct filler_t,fillerc);
|
117
|
+
|
118
|
+
fillerc->filler=filler;//Init the filler by hand.... TODO: cleaner
|
119
|
+
fillerc->buffer=buf;
|
120
|
+
args[3]=rfiller_instance;
|
121
|
+
args[4]=INT2NUM(offset);
|
122
|
+
args[5]=get_file_info(ffi);
|
123
|
+
|
124
|
+
res=rb_protect((VALUE (*)())unsafe_readdir,(VALUE)args,&error);
|
125
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
126
|
+
}
|
127
|
+
|
128
|
+
/*
|
129
|
+
Resolve target of symbolic link
|
130
|
+
@overload readlink(context,path,size)
|
131
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#b4ce6e6d69dfde3ec550f22d932c5633 readlink}
|
132
|
+
@param [Context] context
|
133
|
+
@param [String] path
|
134
|
+
@param [Integer] size if the resolved path is greater than this size it should be truncated
|
135
|
+
|
136
|
+
@return [String] the resolved link path
|
137
|
+
@raise [Errno]
|
138
|
+
*/
|
139
|
+
static VALUE unsafe_readlink(VALUE *args)
|
140
|
+
{
|
141
|
+
return rb_funcall3(args[0],rb_intern("readlink"),3,&args[1]);
|
142
|
+
}
|
143
|
+
|
144
|
+
static int rf_readlink(const char *path, char *buf, size_t size)
|
145
|
+
{
|
146
|
+
VALUE args[4];
|
147
|
+
VALUE res;
|
148
|
+
int error = 0;
|
149
|
+
|
150
|
+
struct fuse_context *ctx=fuse_get_context();
|
151
|
+
init_context_path_args(args,ctx,path);
|
152
|
+
|
153
|
+
args[3]=INT2NUM(size);
|
154
|
+
char *rbuf;
|
155
|
+
res=rb_protect((VALUE (*)())unsafe_readlink,(VALUE)args,&error);
|
156
|
+
if (error)
|
157
|
+
{
|
158
|
+
return -(return_error(ENOENT));
|
159
|
+
}
|
160
|
+
else
|
161
|
+
{
|
162
|
+
rbuf=STR2CSTR(res);
|
163
|
+
strncpy(buf,rbuf,size);
|
164
|
+
return 0;
|
165
|
+
}
|
166
|
+
}
|
167
|
+
|
168
|
+
/*
|
169
|
+
@deprecated see {#readdir}
|
170
|
+
@abstract Fuse operation getdir
|
171
|
+
*/
|
172
|
+
static VALUE unsafe_getdir(VALUE *args)
|
173
|
+
{
|
174
|
+
return rb_funcall3(args[0],rb_intern("getdir"),3,&args[1]);
|
175
|
+
}
|
176
|
+
|
177
|
+
//call getdir with an Filler object
|
178
|
+
static int rf_getdir(const char *path, fuse_dirh_t dh, fuse_dirfil_t df)
|
179
|
+
{
|
180
|
+
VALUE fuse_module;
|
181
|
+
VALUE rfiller_class;
|
182
|
+
VALUE rfiller_instance;
|
183
|
+
VALUE args[4];
|
184
|
+
VALUE res;
|
185
|
+
struct filler_t *fillerc;
|
186
|
+
int error = 0;
|
187
|
+
|
188
|
+
struct fuse_context *ctx=fuse_get_context();
|
189
|
+
init_context_path_args(args,ctx,path);
|
190
|
+
|
191
|
+
//create a filler object
|
192
|
+
fuse_module = rb_const_get(rb_cObject, rb_intern("RFuse"));
|
193
|
+
rfiller_class = rb_const_get(fuse_module,rb_intern("Filler"));
|
194
|
+
rfiller_instance = rb_funcall(rfiller_class,rb_intern("new"),0);
|
195
|
+
|
196
|
+
Data_Get_Struct(rfiller_instance,struct filler_t,fillerc);
|
197
|
+
|
198
|
+
fillerc->df = df;
|
199
|
+
fillerc->dh = dh;
|
200
|
+
|
201
|
+
args[3]=rfiller_instance;
|
202
|
+
|
203
|
+
res = rb_protect((VALUE (*)())unsafe_getdir, (VALUE)args, &error);
|
204
|
+
|
205
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
206
|
+
}
|
207
|
+
|
208
|
+
/*
|
209
|
+
Create a file node
|
210
|
+
@overload mknod(context,path,mode,major,minor)
|
211
|
+
@abstract Fuse Operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#1465eb2268cec2bb5ed11cb09bbda42f mknod}
|
212
|
+
|
213
|
+
@param [Context] context
|
214
|
+
@param [String] path
|
215
|
+
@param [Integer] mode type & permissions
|
216
|
+
@param [Integer] major
|
217
|
+
@param [Integer] minor
|
218
|
+
|
219
|
+
@return[void]
|
220
|
+
|
221
|
+
This is called for creation of all non-directory, non-symlink nodes. If the filesystem defines {#create}, then for regular files that will be called instead.
|
222
|
+
|
223
|
+
*/
|
224
|
+
static VALUE unsafe_mknod(VALUE *args)
|
225
|
+
{
|
226
|
+
return rb_funcall3(args[0],rb_intern("mknod"),5,&args[1]);
|
227
|
+
}
|
228
|
+
|
229
|
+
static int rf_mknod(const char *path, mode_t mode,dev_t dev)
|
230
|
+
{
|
231
|
+
VALUE args[6];
|
232
|
+
VALUE res;
|
233
|
+
int error = 0;
|
234
|
+
struct fuse_context *ctx=fuse_get_context();
|
235
|
+
init_context_path_args(args,ctx,path);
|
236
|
+
|
237
|
+
int major;
|
238
|
+
int minor;
|
239
|
+
|
240
|
+
major = MAJOR(dev);
|
241
|
+
minor = MINOR(dev);
|
242
|
+
|
243
|
+
args[3]=INT2FIX(mode);
|
244
|
+
args[4]=INT2FIX(major);
|
245
|
+
args[5]=INT2FIX(minor);
|
246
|
+
res=rb_protect((VALUE (*)())unsafe_mknod,(VALUE) args,&error);
|
247
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
248
|
+
}
|
249
|
+
|
250
|
+
/*
|
251
|
+
Get file attributes.
|
252
|
+
@overload getattr(context,path)
|
253
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#7a4c5d8eaf7179d819618c0cf3f73724 getattr}
|
254
|
+
@param [Context] context
|
255
|
+
@param [String] path
|
256
|
+
|
257
|
+
@return [Stat] or something that quacks like a stat, or nil if the path does not exist
|
258
|
+
@raise [Errno]
|
259
|
+
|
260
|
+
Similar to stat(). The 'st_dev' and 'st_blksize' fields are ignored. The 'st_ino' field is ignored except if the 'use_ino' mount option is given.
|
261
|
+
*/
|
262
|
+
static VALUE unsafe_getattr(VALUE *args)
|
263
|
+
{
|
264
|
+
return rb_funcall3(args[0],rb_intern("getattr"),2,&args[1]);
|
265
|
+
}
|
266
|
+
|
267
|
+
//calls getattr with path and expects something like FuseStat back
|
268
|
+
static int rf_getattr(const char *path, struct stat *stbuf)
|
269
|
+
{
|
270
|
+
VALUE args[3];
|
271
|
+
VALUE res;
|
272
|
+
int error = 0;
|
273
|
+
struct fuse_context *ctx=fuse_get_context();
|
274
|
+
init_context_path_args(args,ctx,path);
|
275
|
+
|
276
|
+
res=rb_protect((VALUE (*)())unsafe_getattr,(VALUE) args,&error);
|
277
|
+
|
278
|
+
if (res == Qnil) {
|
279
|
+
return -ENOENT;
|
280
|
+
}
|
281
|
+
if (error)
|
282
|
+
{
|
283
|
+
return -(return_error(ENOENT));
|
284
|
+
}
|
285
|
+
else
|
286
|
+
{
|
287
|
+
rstat2stat(res,stbuf);
|
288
|
+
return 0;
|
289
|
+
}
|
290
|
+
}
|
291
|
+
|
292
|
+
/*
|
293
|
+
Create a directory
|
294
|
+
|
295
|
+
@overload mkdir(context,path,mode)
|
296
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#0a38aa6ca60e945772d5d21b0c1c8916 mkdir}
|
297
|
+
|
298
|
+
@param [Context] context
|
299
|
+
@param [String] path
|
300
|
+
@param [Integer] mode to obtain correct directory permissions use mode | {Stat.S_IFDIR}
|
301
|
+
|
302
|
+
@return [void]
|
303
|
+
@raise [Errno]
|
304
|
+
|
305
|
+
*/
|
306
|
+
static VALUE unsafe_mkdir(VALUE *args)
|
307
|
+
{
|
308
|
+
return rb_funcall3(args[0],rb_intern("mkdir"),3,&args[1]);
|
309
|
+
}
|
310
|
+
|
311
|
+
static int rf_mkdir(const char *path, mode_t mode)
|
312
|
+
{
|
313
|
+
VALUE args[4];
|
314
|
+
VALUE res;
|
315
|
+
int error = 0;
|
316
|
+
|
317
|
+
struct fuse_context *ctx=fuse_get_context();
|
318
|
+
init_context_path_args(args,ctx,path);
|
319
|
+
|
320
|
+
args[3]=INT2FIX(mode);
|
321
|
+
res=rb_protect((VALUE (*)())unsafe_mkdir,(VALUE) args,&error);
|
322
|
+
|
323
|
+
if (error)
|
324
|
+
{
|
325
|
+
return -(return_error(ENOENT));
|
326
|
+
}
|
327
|
+
else
|
328
|
+
{
|
329
|
+
return 0;
|
330
|
+
}
|
331
|
+
}
|
332
|
+
|
333
|
+
/*
|
334
|
+
File open operation
|
335
|
+
|
336
|
+
@overload open(context,path,ffi)
|
337
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#14b98c3f7ab97cc2ef8f9b1d9dc0709d open}
|
338
|
+
@param [Context] context
|
339
|
+
@param [String] path
|
340
|
+
@param [FileInfo] ffi
|
341
|
+
file open flags etc.
|
342
|
+
The fh attribute may be used to store an arbitrary filehandle object which will be passed to all subsequent operations on this file
|
343
|
+
|
344
|
+
@raise [Errno::ENOPERM] if user is not permitted to open the file
|
345
|
+
@raise [Errno] for other errors
|
346
|
+
|
347
|
+
@return [void]
|
348
|
+
*/
|
349
|
+
static VALUE unsafe_open(VALUE *args)
|
350
|
+
{
|
351
|
+
return rb_funcall3(args[0],rb_intern("open"),3,&args[1]);
|
352
|
+
}
|
353
|
+
|
354
|
+
static int rf_open(const char *path,struct fuse_file_info *ffi)
|
355
|
+
{
|
356
|
+
VALUE args[4];
|
357
|
+
VALUE res;
|
358
|
+
int error = 0;
|
359
|
+
|
360
|
+
struct fuse_context *ctx=fuse_get_context();
|
361
|
+
init_context_path_args(args,ctx,path);
|
362
|
+
|
363
|
+
args[3]=wrap_file_info(ctx,ffi);
|
364
|
+
|
365
|
+
res=rb_protect((VALUE (*)())unsafe_open,(VALUE) args,&error);
|
366
|
+
if (error)
|
367
|
+
{
|
368
|
+
return -(return_error(ENOENT));
|
369
|
+
}
|
370
|
+
else
|
371
|
+
{
|
372
|
+
return 0;
|
373
|
+
}
|
374
|
+
}
|
375
|
+
|
376
|
+
//This method is registered as a default for release in the case when
|
377
|
+
//open/create are defined, but a specific release method is not.
|
378
|
+
//similarly for opendir/releasedir
|
379
|
+
static int rf_release_ffi(const char *path, struct fuse_file_info *ffi)
|
380
|
+
{
|
381
|
+
struct fuse_context *ctx=fuse_get_context();
|
382
|
+
|
383
|
+
release_file_info(ctx,ffi);
|
384
|
+
|
385
|
+
}
|
386
|
+
|
387
|
+
/*
|
388
|
+
Release an open file
|
389
|
+
|
390
|
+
@overload release(context,path,ffi)
|
391
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#bac8718cdfc1ee273a44831a27393419 release}
|
392
|
+
@param [Context] context
|
393
|
+
@param [String] path
|
394
|
+
@param [FileInfo] ffi
|
395
|
+
|
396
|
+
@return [void]
|
397
|
+
|
398
|
+
Release is called when there are no more references to an open file: all file descriptors are closed and all memory mappings are unmapped.
|
399
|
+
|
400
|
+
For every {#open} call there will be exactly one {#release} call with the same flags and file descriptor. It is possible to have a file opened more than once, in which case only the last release will mean, that no more reads/writes will happen on the file.
|
401
|
+
*/
|
402
|
+
static VALUE unsafe_release(VALUE *args)
|
403
|
+
{
|
404
|
+
return rb_funcall3(args[0],rb_intern("release"),3,&args[1]);
|
405
|
+
}
|
406
|
+
|
407
|
+
static int rf_release(const char *path, struct fuse_file_info *ffi)
|
408
|
+
{
|
409
|
+
VALUE args[4];
|
410
|
+
VALUE res;
|
411
|
+
int error = 0;
|
412
|
+
|
413
|
+
struct fuse_context *ctx=fuse_get_context();
|
414
|
+
init_context_path_args(args,ctx,path);
|
415
|
+
|
416
|
+
args[3]=release_file_info(ctx,ffi);
|
417
|
+
|
418
|
+
res=rb_protect((VALUE (*)())unsafe_release,(VALUE) args,&error);
|
419
|
+
|
420
|
+
if (error)
|
421
|
+
{
|
422
|
+
return -(return_error(ENOENT));
|
423
|
+
}
|
424
|
+
else
|
425
|
+
{
|
426
|
+
return 0;
|
427
|
+
}
|
428
|
+
}
|
429
|
+
|
430
|
+
/*
|
431
|
+
Synchronize file contents
|
432
|
+
|
433
|
+
@overload fsync(context,path,datasync,ffi)
|
434
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#92bdd6f43ba390a54ac360541c56b528 fsync}
|
435
|
+
|
436
|
+
@param [Context] context
|
437
|
+
@param [String] path
|
438
|
+
@param [Integer] datasync if non-zero, then only user data should be flushed, not the metadata
|
439
|
+
@param [FileInfo] ffi
|
440
|
+
|
441
|
+
@return [void]
|
442
|
+
@raise [Errno]
|
443
|
+
*/
|
444
|
+
static VALUE unsafe_fsync(VALUE *args) {
|
445
|
+
return rb_funcall3(args[0],rb_intern("fsync"),4,&args[1]);
|
446
|
+
}
|
447
|
+
|
448
|
+
static int rf_fsync(const char *path, int datasync, struct fuse_file_info *ffi)
|
449
|
+
{
|
450
|
+
VALUE args[5];
|
451
|
+
VALUE res;
|
452
|
+
int error = 0;
|
453
|
+
|
454
|
+
struct fuse_context *ctx=fuse_get_context();
|
455
|
+
init_context_path_args(args,ctx,path);
|
456
|
+
|
457
|
+
args[3] = INT2NUM(datasync);
|
458
|
+
args[4] = get_file_info(ffi);
|
459
|
+
|
460
|
+
res = rb_protect((VALUE (*)())unsafe_fsync,(VALUE) args,&error);
|
461
|
+
|
462
|
+
if (error)
|
463
|
+
{
|
464
|
+
return -(return_error(ENOENT));
|
465
|
+
}
|
466
|
+
else
|
467
|
+
{
|
468
|
+
return 0;
|
469
|
+
}
|
470
|
+
}
|
471
|
+
|
472
|
+
|
473
|
+
|
474
|
+
/*
|
475
|
+
Possibly flush cached data
|
476
|
+
|
477
|
+
@overload flush(context,path,ffi)
|
478
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#d4ec9c309072a92dd82ddb20efa4ab14 flush}
|
479
|
+
|
480
|
+
@param [Context] context
|
481
|
+
@param [String] path
|
482
|
+
@param [FileInfo] ffi
|
483
|
+
|
484
|
+
@return [void]
|
485
|
+
@raise [Errno]
|
486
|
+
|
487
|
+
BIG NOTE: This is not equivalent to fsync(). It's not a request to sync dirty data.
|
488
|
+
|
489
|
+
Flush is called on each close() of a file descriptor. So if a filesystem wants to return write errors in close() and the file has cached dirty data, this is a good place to write back data and return any errors. Since many applications ignore close() errors this is not always useful.
|
490
|
+
|
491
|
+
NOTE: The flush() method may be called more than once for each open(). This happens if more than one file descriptor refers to an opened file due to dup(), dup2() or fork() calls. It is not possible to determine if a flush is final, so each flush should be treated equally. Multiple write-flush sequences are relatively rare, so this shouldn't be a problem.
|
492
|
+
|
493
|
+
Filesystems shouldn't assume that flush will always be called after some writes, or that if will be called at all.
|
494
|
+
*/
|
495
|
+
static VALUE unsafe_flush(VALUE *args)
|
496
|
+
{
|
497
|
+
return rb_funcall3(args[0],rb_intern("flush"),3,&args[1]);
|
498
|
+
}
|
499
|
+
|
500
|
+
static int rf_flush(const char *path,struct fuse_file_info *ffi)
|
501
|
+
{
|
502
|
+
VALUE args[4];
|
503
|
+
VALUE res;
|
504
|
+
int error = 0;
|
505
|
+
struct fuse_context *ctx=fuse_get_context();
|
506
|
+
init_context_path_args(args,ctx,path);
|
507
|
+
args[3]=get_file_info(ffi);
|
508
|
+
res=rb_protect((VALUE (*)())unsafe_flush,(VALUE) args,&error);
|
509
|
+
|
510
|
+
return error ? -(return_error(ENOENT)) : 0;
|
511
|
+
}
|
512
|
+
|
513
|
+
/*
|
514
|
+
Change the size of a file
|
515
|
+
|
516
|
+
@overload truncate(context,path,offset)
|
517
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#8efb50b9cd975ba8c4c450248caff6ed truncate}
|
518
|
+
|
519
|
+
@param [Context] context
|
520
|
+
@param [String] path
|
521
|
+
@param [Integer] offset
|
522
|
+
|
523
|
+
@return [void]
|
524
|
+
@raise [Errno]
|
525
|
+
*/
|
526
|
+
static VALUE unsafe_truncate(VALUE *args)
|
527
|
+
{
|
528
|
+
return rb_funcall3(args[0],rb_intern("truncate"),3,&args[1]);
|
529
|
+
}
|
530
|
+
|
531
|
+
static int rf_truncate(const char *path,off_t offset)
|
532
|
+
{
|
533
|
+
VALUE args[4];
|
534
|
+
VALUE res;
|
535
|
+
int error = 0;
|
536
|
+
struct fuse_context *ctx=fuse_get_context();
|
537
|
+
init_context_path_args(args,ctx,path);
|
538
|
+
args[3]=INT2FIX(offset);
|
539
|
+
res=rb_protect((VALUE (*)())unsafe_truncate,(VALUE) args,&error);
|
540
|
+
|
541
|
+
return error ? -(return_error(ENOENT)) : 0;
|
542
|
+
}
|
543
|
+
|
544
|
+
|
545
|
+
/*
|
546
|
+
Change access/modification times of a file
|
547
|
+
|
548
|
+
@overload utime(context,path,actime,modtime)
|
549
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#cb7452acad1002d418409892b6e54c2e utime}
|
550
|
+
@deprecated See {#utimens}
|
551
|
+
|
552
|
+
@param [Context] context
|
553
|
+
@param [String] path
|
554
|
+
@param [Integer] actime access time
|
555
|
+
@param [Integer] modtime modification time
|
556
|
+
|
557
|
+
@return [void]
|
558
|
+
@raise [Errno]
|
559
|
+
*/
|
560
|
+
static VALUE unsafe_utime(VALUE *args)
|
561
|
+
{
|
562
|
+
return rb_funcall3(args[0],rb_intern("utime"),4,&args[1]);
|
563
|
+
}
|
564
|
+
|
565
|
+
static int rf_utime(const char *path,struct utimbuf *utim)
|
566
|
+
{
|
567
|
+
VALUE args[5];
|
568
|
+
VALUE res;
|
569
|
+
int error = 0;
|
570
|
+
|
571
|
+
struct fuse_context *ctx=fuse_get_context();
|
572
|
+
init_context_path_args(args,ctx,path);
|
573
|
+
|
574
|
+
args[3]=INT2NUM(utim->actime);
|
575
|
+
args[4]=INT2NUM(utim->modtime);
|
576
|
+
res=rb_protect((VALUE (*)())unsafe_utime,(VALUE) args,&error);
|
577
|
+
|
578
|
+
return error ? -(return_error(ENOENT)) : 0;
|
579
|
+
}
|
580
|
+
|
581
|
+
/*
|
582
|
+
Change file ownership
|
583
|
+
|
584
|
+
@overload chown(context,path,uid,gid)
|
585
|
+
|
586
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#40421f8a43e903582c49897894f4692d chown}
|
587
|
+
|
588
|
+
@param [Context] context
|
589
|
+
@param [String] path
|
590
|
+
@param [Integer] uid new user id
|
591
|
+
@param [Integer] gid new group id
|
592
|
+
|
593
|
+
@return [void]
|
594
|
+
@raise [Errno]
|
595
|
+
*/
|
596
|
+
static VALUE unsafe_chown(VALUE *args)
|
597
|
+
{
|
598
|
+
return rb_funcall3(args[0],rb_intern("chown"),4,&args[1]);
|
599
|
+
}
|
600
|
+
|
601
|
+
static int rf_chown(const char *path,uid_t uid,gid_t gid)
|
602
|
+
{
|
603
|
+
VALUE args[5];
|
604
|
+
VALUE res;
|
605
|
+
int error = 0;
|
606
|
+
struct fuse_context *ctx=fuse_get_context();
|
607
|
+
init_context_path_args(args,ctx,path);
|
608
|
+
args[3]=INT2FIX(uid);
|
609
|
+
args[4]=INT2FIX(gid);
|
610
|
+
res=rb_protect((VALUE (*)())unsafe_chown,(VALUE) args,&error);
|
611
|
+
|
612
|
+
return error ? -(return_error(ENOENT)) : 0;
|
613
|
+
}
|
614
|
+
|
615
|
+
/*
|
616
|
+
Change file permissions
|
617
|
+
|
618
|
+
@overload chmod(context,path,mode)
|
619
|
+
|
620
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#7e75d299efe3a401e8473af7028e5cc5 chmod}
|
621
|
+
|
622
|
+
@param [Context] context
|
623
|
+
@param [String] path
|
624
|
+
@param [Integer] mode
|
625
|
+
|
626
|
+
@return [void]
|
627
|
+
@raise [Errno]
|
628
|
+
*/
|
629
|
+
static VALUE unsafe_chmod(VALUE *args)
|
630
|
+
{
|
631
|
+
return rb_funcall3(args[0],rb_intern("chmod"),3,&args[1]);
|
632
|
+
}
|
633
|
+
|
634
|
+
static int rf_chmod(const char *path,mode_t mode)
|
635
|
+
{
|
636
|
+
VALUE args[4];
|
637
|
+
VALUE res;
|
638
|
+
int error = 0;
|
639
|
+
struct fuse_context *ctx=fuse_get_context();
|
640
|
+
init_context_path_args(args,ctx,path);
|
641
|
+
args[3]=INT2FIX(mode);
|
642
|
+
res=rb_protect((VALUE (*)())unsafe_chmod,(VALUE) args,&error);
|
643
|
+
|
644
|
+
return error ? -(return_error(ENOENT)) : 0;
|
645
|
+
}
|
646
|
+
|
647
|
+
/*
|
648
|
+
Remove a file
|
649
|
+
|
650
|
+
@overload unlink(context,path)
|
651
|
+
|
652
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#8bf63301a9d6e94311fa10480993801e unlink}
|
653
|
+
|
654
|
+
@param [Context] context
|
655
|
+
@param [String] path
|
656
|
+
|
657
|
+
@return [void]
|
658
|
+
@raise [Errno]
|
659
|
+
*/
|
660
|
+
static VALUE unsafe_unlink(VALUE *args)
|
661
|
+
{
|
662
|
+
return rb_funcall3(args[0],rb_intern("unlink"),2,&args[1]);
|
663
|
+
}
|
664
|
+
|
665
|
+
static int rf_unlink(const char *path)
|
666
|
+
{
|
667
|
+
VALUE args[3];
|
668
|
+
VALUE res;
|
669
|
+
int error = 0;
|
670
|
+
struct fuse_context *ctx=fuse_get_context();
|
671
|
+
init_context_path_args(args,ctx,path);
|
672
|
+
res=rb_protect((VALUE (*)())unsafe_unlink,(VALUE) args,&error);
|
673
|
+
|
674
|
+
return error ? -(return_error(ENOENT)) : 0;
|
675
|
+
}
|
676
|
+
|
677
|
+
/*
|
678
|
+
Remove a directory
|
679
|
+
|
680
|
+
@overload rmdir(context,path)
|
681
|
+
|
682
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#c59578d18db12f0142ae1ab6e8812d55 rmdir}
|
683
|
+
|
684
|
+
@param [Context] context
|
685
|
+
@param [String] path
|
686
|
+
|
687
|
+
@return [void]
|
688
|
+
@raise [Errno]
|
689
|
+
*/
|
690
|
+
static VALUE unsafe_rmdir(VALUE *args)
|
691
|
+
{
|
692
|
+
return rb_funcall3(args[0],rb_intern("rmdir"),2,&args[1]);
|
693
|
+
}
|
694
|
+
|
695
|
+
static int rf_rmdir(const char *path)
|
696
|
+
{
|
697
|
+
VALUE args[3];
|
698
|
+
VALUE res;
|
699
|
+
int error = 0;
|
700
|
+
struct fuse_context *ctx=fuse_get_context();
|
701
|
+
init_context_path_args(args,ctx,path);
|
702
|
+
res = rb_protect((VALUE (*)())unsafe_rmdir, (VALUE) args ,&error);
|
703
|
+
|
704
|
+
return error ? -(return_error(ENOENT)) : 0;
|
705
|
+
}
|
706
|
+
|
707
|
+
/*
|
708
|
+
Create a symbolic link
|
709
|
+
|
710
|
+
@overload symlink(context,to,from)
|
711
|
+
|
712
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#b86022391e56a8ad3211cf754b5b5ebe symlink}
|
713
|
+
|
714
|
+
@param [Context] context
|
715
|
+
@param [String] to
|
716
|
+
@param [String] from
|
717
|
+
|
718
|
+
@return [void]
|
719
|
+
@raise [Errno]
|
720
|
+
|
721
|
+
Create a symbolic link named "from" which, when evaluated, will lead to "to".
|
722
|
+
*/
|
723
|
+
static VALUE unsafe_symlink(VALUE *args){
|
724
|
+
return rb_funcall3(args[0],rb_intern("symlink"),3,&args[1]);
|
725
|
+
}
|
726
|
+
|
727
|
+
static int rf_symlink(const char *path,const char *as)
|
728
|
+
{
|
729
|
+
VALUE args[4];
|
730
|
+
VALUE res;
|
731
|
+
int error = 0;
|
732
|
+
struct fuse_context *ctx=fuse_get_context();
|
733
|
+
init_context_path_args(args,ctx,path);
|
734
|
+
|
735
|
+
args[3]=rb_str_new2(as);
|
736
|
+
rb_enc_associate(args[3],rb_filesystem_encoding());
|
737
|
+
|
738
|
+
res=rb_protect((VALUE (*)())unsafe_symlink,(VALUE) args,&error);
|
739
|
+
|
740
|
+
return error ? -(return_error(ENOENT)) : 0;
|
741
|
+
}
|
742
|
+
|
743
|
+
/*
|
744
|
+
@overload rename(context,from,to)
|
745
|
+
|
746
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#a777cbddc91887b117ac414e9a2d3cb5 rename}
|
747
|
+
|
748
|
+
@param [Context] context
|
749
|
+
@param [String] from
|
750
|
+
@param [String] to
|
751
|
+
|
752
|
+
@return [void]
|
753
|
+
@raise [Errno]
|
754
|
+
|
755
|
+
Rename the file, directory, or other object "from" to the target "to". Note that the source and target don't have to be in the same directory, so it may be necessary to move the source to an entirely new directory. See rename(2) for full details.
|
756
|
+
*/
|
757
|
+
static VALUE unsafe_rename(VALUE *args)
|
758
|
+
{
|
759
|
+
return rb_funcall3(args[0],rb_intern("rename"),3,&args[1]);
|
760
|
+
}
|
761
|
+
|
762
|
+
static int rf_rename(const char *path,const char *as)
|
763
|
+
{
|
764
|
+
VALUE args[4];
|
765
|
+
VALUE res;
|
766
|
+
int error = 0;
|
767
|
+
struct fuse_context *ctx=fuse_get_context();
|
768
|
+
init_context_path_args(args,ctx,path);
|
769
|
+
|
770
|
+
args[3]=rb_str_new2(as);
|
771
|
+
rb_enc_associate(args[3],rb_filesystem_encoding());
|
772
|
+
|
773
|
+
res=rb_protect((VALUE (*)())unsafe_rename,(VALUE) args,&error);
|
774
|
+
|
775
|
+
return error ? -(return_error(ENOENT)) : 0;
|
776
|
+
}
|
777
|
+
|
778
|
+
|
779
|
+
/*
|
780
|
+
Create a hard link to file
|
781
|
+
@overload link(context,from,to)
|
782
|
+
|
783
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#1b234c43e826c6a690d80ea895a17f61 link}
|
784
|
+
|
785
|
+
@param [Context] context
|
786
|
+
@param [String] from
|
787
|
+
@param [String] to
|
788
|
+
|
789
|
+
@return [void]
|
790
|
+
@raise [Errno]
|
791
|
+
*/
|
792
|
+
static VALUE unsafe_link(VALUE *args)
|
793
|
+
{
|
794
|
+
return rb_funcall3(args[0],rb_intern("link"),3,&args[1]);
|
795
|
+
}
|
796
|
+
|
797
|
+
static int rf_link(const char *path,const char * as)
|
798
|
+
{
|
799
|
+
VALUE args[4];
|
800
|
+
VALUE res;
|
801
|
+
int error = 0;
|
802
|
+
struct fuse_context *ctx=fuse_get_context();
|
803
|
+
init_context_path_args(args,ctx,path);
|
804
|
+
args[3]=rb_str_new2(as);
|
805
|
+
rb_enc_associate(args[3],rb_filesystem_encoding());
|
806
|
+
res=rb_protect((VALUE (*)())unsafe_link,(VALUE) args,&error);
|
807
|
+
|
808
|
+
return error ? -(return_error(ENOENT)) : 0;
|
809
|
+
}
|
810
|
+
|
811
|
+
|
812
|
+
/*
|
813
|
+
Read data from an open file
|
814
|
+
|
815
|
+
@overload read(context,path,size,offset,ffi)
|
816
|
+
|
817
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#2a1c6b4ce1845de56863f8b7939501b5 read}
|
818
|
+
|
819
|
+
@param [Context] context
|
820
|
+
@param [String] path
|
821
|
+
@param [Integer] size
|
822
|
+
@param [Integer] offset
|
823
|
+
@param [FileInfo] ffi
|
824
|
+
|
825
|
+
@return [String] should be exactly the number of bytes requested, or empty string on EOF
|
826
|
+
@raise [Errno]
|
827
|
+
*/
|
828
|
+
static VALUE unsafe_read(VALUE *args)
|
829
|
+
{
|
830
|
+
VALUE res;
|
831
|
+
|
832
|
+
res = rb_funcall3(args[0],rb_intern("read"),5,&args[1]);
|
833
|
+
|
834
|
+
return StringValue(res);
|
835
|
+
}
|
836
|
+
|
837
|
+
|
838
|
+
long rb_strcpy(VALUE str, char *buf, size_t size)
|
839
|
+
{
|
840
|
+
long length;
|
841
|
+
|
842
|
+
length = RSTRING_LEN(str);
|
843
|
+
if (length <= (long) size)
|
844
|
+
{
|
845
|
+
memcpy(buf,RSTRING_PTR(str),length);
|
846
|
+
}
|
847
|
+
|
848
|
+
return length;
|
849
|
+
}
|
850
|
+
|
851
|
+
static int rf_read(const char *path,char * buf, size_t size,off_t offset,struct fuse_file_info *ffi)
|
852
|
+
{
|
853
|
+
VALUE args[6];
|
854
|
+
VALUE res;
|
855
|
+
int error = 0;
|
856
|
+
long length=0;
|
857
|
+
char* rbuf;
|
858
|
+
|
859
|
+
struct fuse_context *ctx=fuse_get_context();
|
860
|
+
init_context_path_args(args,ctx,path);
|
861
|
+
|
862
|
+
args[3]=INT2NUM(size);
|
863
|
+
args[4]=INT2NUM(offset);
|
864
|
+
args[5]=get_file_info(ffi);
|
865
|
+
|
866
|
+
res=rb_protect((VALUE (*)())unsafe_read,(VALUE) args,&error);
|
867
|
+
|
868
|
+
if (error)
|
869
|
+
{
|
870
|
+
return -(return_error(ENOENT));
|
871
|
+
}
|
872
|
+
else
|
873
|
+
{
|
874
|
+
|
875
|
+
length = rb_strcpy(res,buf,size);
|
876
|
+
|
877
|
+
if (length <= (long) size) {
|
878
|
+
return length;
|
879
|
+
} else {
|
880
|
+
//This cannot happen => IO error.
|
881
|
+
return -(return_error(ENOENT));
|
882
|
+
}
|
883
|
+
|
884
|
+
}
|
885
|
+
}
|
886
|
+
|
887
|
+
|
888
|
+
/*
|
889
|
+
Write data to an open file
|
890
|
+
|
891
|
+
@overload write(context,path,size,offset,ffi)
|
892
|
+
|
893
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#897d1ece4b8b04c92d97b97b2dbf9768 write}
|
894
|
+
|
895
|
+
@param [Context] context
|
896
|
+
@param [String] path
|
897
|
+
@param [String] data
|
898
|
+
@param [Integer] offset
|
899
|
+
@param [FileInfo] ffi
|
900
|
+
|
901
|
+
@return [Integer] exactly the number of bytes written except on error
|
902
|
+
@raise [Errno]
|
903
|
+
*/
|
904
|
+
static VALUE unsafe_write(VALUE *args)
|
905
|
+
{
|
906
|
+
return rb_funcall3(args[0],rb_intern("write"),5,&args[1]);
|
907
|
+
}
|
908
|
+
|
909
|
+
static int rf_write(const char *path,const char *buf,size_t size,
|
910
|
+
off_t offset,struct fuse_file_info *ffi)
|
911
|
+
{
|
912
|
+
VALUE args[6];
|
913
|
+
VALUE res;
|
914
|
+
int error = 0;
|
915
|
+
struct fuse_context *ctx=fuse_get_context();
|
916
|
+
init_context_path_args(args,ctx,path);
|
917
|
+
|
918
|
+
args[3]=rb_str_new(buf, size);
|
919
|
+
args[4]=INT2NUM(offset);
|
920
|
+
args[5]=get_file_info(ffi);
|
921
|
+
|
922
|
+
res = rb_protect((VALUE (*)())unsafe_write,(VALUE) args, &error);
|
923
|
+
|
924
|
+
if (error)
|
925
|
+
{
|
926
|
+
return -(return_error(ENOENT));
|
927
|
+
}
|
928
|
+
else
|
929
|
+
{
|
930
|
+
return NUM2INT(res);
|
931
|
+
}
|
932
|
+
}
|
933
|
+
|
934
|
+
/*
|
935
|
+
Get file system statistics
|
936
|
+
|
937
|
+
@overload statfs(context,path)
|
938
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#4e765e29122e7b6b533dc99849a52655 statfs}
|
939
|
+
@param [Context] context
|
940
|
+
@param [String] path
|
941
|
+
|
942
|
+
@return [StatVfs] or something that quacks like a statVfs
|
943
|
+
@raise [Errno]
|
944
|
+
|
945
|
+
The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored
|
946
|
+
|
947
|
+
*/
|
948
|
+
static VALUE unsafe_statfs(VALUE *args)
|
949
|
+
{
|
950
|
+
return rb_funcall3(args[0],rb_intern("statfs"),2,&args[1]);
|
951
|
+
}
|
952
|
+
|
953
|
+
static int rf_statfs(const char * path, struct statvfs * vfsinfo)
|
954
|
+
{
|
955
|
+
VALUE args[1];
|
956
|
+
VALUE res;
|
957
|
+
int error = 0;
|
958
|
+
|
959
|
+
struct fuse_context *ctx=fuse_get_context();
|
960
|
+
init_context_path_args(args,ctx,path);
|
961
|
+
|
962
|
+
res = rb_protect((VALUE (*)())unsafe_statfs,(VALUE) args,&error);
|
963
|
+
|
964
|
+
if (error || (res == Qnil))
|
965
|
+
{
|
966
|
+
return -(return_error(ENOENT));
|
967
|
+
}
|
968
|
+
else
|
969
|
+
{
|
970
|
+
rstatvfs2statvfs(res,vfsinfo);
|
971
|
+
return 0;
|
972
|
+
}
|
973
|
+
}
|
974
|
+
|
975
|
+
|
976
|
+
/*
|
977
|
+
Set extended attributes
|
978
|
+
|
979
|
+
@overload setxattr(context,path,name,data,flags)
|
980
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#988ced7091c2821daa208e6c96d8b598 setxattr}
|
981
|
+
@param [Context] context
|
982
|
+
@param [String] path
|
983
|
+
@param [String] name
|
984
|
+
@param [String] data
|
985
|
+
@param [Integer] flags
|
986
|
+
|
987
|
+
@return [void]
|
988
|
+
@raise [Errno]
|
989
|
+
|
990
|
+
*/
|
991
|
+
static VALUE unsafe_setxattr(VALUE *args)
|
992
|
+
{
|
993
|
+
return rb_funcall3(args[0],rb_intern("setxattr"),5,&args[1]);
|
994
|
+
}
|
995
|
+
|
996
|
+
static int rf_setxattr(const char *path,const char *name,
|
997
|
+
const char *value, size_t size, int flags)
|
998
|
+
{
|
999
|
+
VALUE args[6];
|
1000
|
+
VALUE res;
|
1001
|
+
int error = 0;
|
1002
|
+
|
1003
|
+
struct fuse_context *ctx=fuse_get_context();
|
1004
|
+
init_context_path_args(args,ctx,path);
|
1005
|
+
|
1006
|
+
args[3]=rb_str_new2(name);
|
1007
|
+
args[4]=rb_str_new(value,size);
|
1008
|
+
args[5]=INT2NUM(flags);
|
1009
|
+
|
1010
|
+
res=rb_protect((VALUE (*)())unsafe_setxattr,(VALUE) args,&error);
|
1011
|
+
|
1012
|
+
return error ? -(return_error(ENOENT)) : 0;
|
1013
|
+
}
|
1014
|
+
|
1015
|
+
|
1016
|
+
/*
|
1017
|
+
Get extended attribute
|
1018
|
+
|
1019
|
+
@overload getxattr(context,path,name)
|
1020
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#e21503c64fe2990c8a599f5ba339a8f2 getxattr}
|
1021
|
+
@param [Context] context
|
1022
|
+
@param [String] path
|
1023
|
+
@param [String] name
|
1024
|
+
|
1025
|
+
@return [String] attribute value
|
1026
|
+
@raise [Errno]
|
1027
|
+
|
1028
|
+
*/
|
1029
|
+
static VALUE unsafe_getxattr(VALUE *args)
|
1030
|
+
{
|
1031
|
+
VALUE res;
|
1032
|
+
res = rb_funcall3(args[0],rb_intern("getxattr"),3,&args[1]);
|
1033
|
+
|
1034
|
+
return StringValue(res);
|
1035
|
+
}
|
1036
|
+
|
1037
|
+
static int rf_getxattr(const char *path,const char *name,char *buf,
|
1038
|
+
size_t size)
|
1039
|
+
{
|
1040
|
+
VALUE args[4];
|
1041
|
+
VALUE res;
|
1042
|
+
char *rbuf;
|
1043
|
+
long length = 0;
|
1044
|
+
int error = 0;
|
1045
|
+
|
1046
|
+
struct fuse_context *ctx=fuse_get_context();
|
1047
|
+
init_context_path_args(args,ctx,path);
|
1048
|
+
|
1049
|
+
args[3]=rb_str_new2(name);
|
1050
|
+
res=rb_protect((VALUE (*)())unsafe_getxattr,(VALUE) args,&error);
|
1051
|
+
|
1052
|
+
if (error)
|
1053
|
+
{
|
1054
|
+
return -(return_error(ENOENT));
|
1055
|
+
}
|
1056
|
+
else
|
1057
|
+
{
|
1058
|
+
return rb_strcpy(res,buf,size);
|
1059
|
+
}
|
1060
|
+
}
|
1061
|
+
|
1062
|
+
/*
|
1063
|
+
List extended attributes
|
1064
|
+
|
1065
|
+
@overload listxattr(context,path)
|
1066
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#b4a9c361ce48406f07d5a08ab03f5de8 listxattr}
|
1067
|
+
@param [Context] context
|
1068
|
+
@param [String] path
|
1069
|
+
|
1070
|
+
@return [Array<String>] list of attribute names
|
1071
|
+
@raise [Errno]
|
1072
|
+
*/
|
1073
|
+
static VALUE unsafe_listxattr(VALUE *args)
|
1074
|
+
{
|
1075
|
+
VALUE res;
|
1076
|
+
res = rb_funcall3(args[0],rb_intern("listxattr"),2,&args[1]);
|
1077
|
+
|
1078
|
+
//We'll let Ruby do the hard work of creating a String
|
1079
|
+
//separated by NULLs
|
1080
|
+
return rb_funcall(mRFuse,rb_intern("packxattr"),1,res);
|
1081
|
+
}
|
1082
|
+
|
1083
|
+
static int rf_listxattr(const char *path,char *buf, size_t size)
|
1084
|
+
{
|
1085
|
+
VALUE args[3];
|
1086
|
+
VALUE res;
|
1087
|
+
char *rbuf;
|
1088
|
+
size_t length =0;
|
1089
|
+
int error = 0;
|
1090
|
+
|
1091
|
+
struct fuse_context *ctx=fuse_get_context();
|
1092
|
+
init_context_path_args(args,ctx,path);
|
1093
|
+
|
1094
|
+
res=rb_protect((VALUE (*)())unsafe_listxattr,(VALUE) args,&error);
|
1095
|
+
|
1096
|
+
if (error)
|
1097
|
+
{
|
1098
|
+
return -(return_error(ENOENT));
|
1099
|
+
}
|
1100
|
+
else {
|
1101
|
+
return rb_strcpy(res,buf,size);
|
1102
|
+
}
|
1103
|
+
}
|
1104
|
+
|
1105
|
+
|
1106
|
+
/*
|
1107
|
+
Remove extended attribute
|
1108
|
+
|
1109
|
+
@overload removexattr(context,path,name)
|
1110
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#5e54de801a0e0d7019e4579112ecc477 removexattr}
|
1111
|
+
@param [Context] context
|
1112
|
+
@param [String] path
|
1113
|
+
@param [String] name attribute to remove
|
1114
|
+
|
1115
|
+
@return [void]
|
1116
|
+
@raise [Errno]
|
1117
|
+
*/
|
1118
|
+
static VALUE unsafe_removexattr(VALUE *args)
|
1119
|
+
{
|
1120
|
+
return rb_funcall3(args[0],rb_intern("removexattr"),3,&args[1]);
|
1121
|
+
}
|
1122
|
+
|
1123
|
+
static int rf_removexattr(const char *path,const char *name)
|
1124
|
+
{
|
1125
|
+
VALUE args[4];
|
1126
|
+
VALUE res;
|
1127
|
+
int error = 0;
|
1128
|
+
struct fuse_context *ctx=fuse_get_context();
|
1129
|
+
init_context_path_args(args,ctx,path);
|
1130
|
+
args[3]=rb_str_new2(name);
|
1131
|
+
res=rb_protect((VALUE (*)())unsafe_removexattr,(VALUE) args,&error);
|
1132
|
+
|
1133
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1134
|
+
}
|
1135
|
+
|
1136
|
+
|
1137
|
+
/*
|
1138
|
+
Open directory
|
1139
|
+
|
1140
|
+
@overload opendir(context,path,name)
|
1141
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#1813889bc5e6e0087a936b7abe8b923f opendir}
|
1142
|
+
@param [Context] context
|
1143
|
+
@param [String] path
|
1144
|
+
@param [FileInfo] ffi
|
1145
|
+
|
1146
|
+
@return [void]
|
1147
|
+
@raise [Errno]
|
1148
|
+
|
1149
|
+
|
1150
|
+
Unless the 'default_permissions' mount option is given, this method should check if opendir is permitted for this directory. Optionally opendir may also return an arbitrary filehandle in the fuse_file_info structure, which will be available to {#readdir}, {#fsyncdir}, {#releasedir}.
|
1151
|
+
|
1152
|
+
*/
|
1153
|
+
static VALUE unsafe_opendir(VALUE *args)
|
1154
|
+
{
|
1155
|
+
return rb_funcall3(args[0],rb_intern("opendir"),3,&args[1]);
|
1156
|
+
}
|
1157
|
+
|
1158
|
+
static int rf_opendir(const char *path,struct fuse_file_info *ffi)
|
1159
|
+
{
|
1160
|
+
VALUE args[4];
|
1161
|
+
VALUE res;
|
1162
|
+
int error = 0;
|
1163
|
+
struct fuse_context *ctx=fuse_get_context();
|
1164
|
+
init_context_path_args(args,ctx,path);
|
1165
|
+
|
1166
|
+
args[3]=wrap_file_info(ctx,ffi);
|
1167
|
+
|
1168
|
+
res=rb_protect((VALUE (*)())unsafe_opendir,(VALUE) args,&error);
|
1169
|
+
|
1170
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1171
|
+
}
|
1172
|
+
|
1173
|
+
/*
|
1174
|
+
Release directory
|
1175
|
+
|
1176
|
+
@overload releasedir(context,path,ffi)
|
1177
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#729e53d36acc05a7a8985a1a3bbfac1e releasedir}
|
1178
|
+
@param [Context] context
|
1179
|
+
@param [String] path
|
1180
|
+
@param [FileInfo] ffi
|
1181
|
+
|
1182
|
+
@return [void]
|
1183
|
+
@raise [Errno]
|
1184
|
+
*/
|
1185
|
+
static VALUE unsafe_releasedir(VALUE *args)
|
1186
|
+
{
|
1187
|
+
|
1188
|
+
return rb_funcall(args[0],rb_intern("releasedir"),3,&args[1]);
|
1189
|
+
}
|
1190
|
+
|
1191
|
+
static int rf_releasedir(const char *path,struct fuse_file_info *ffi)
|
1192
|
+
{
|
1193
|
+
VALUE args[4];
|
1194
|
+
VALUE res;
|
1195
|
+
int error = 0;
|
1196
|
+
|
1197
|
+
struct fuse_context *ctx=fuse_get_context();
|
1198
|
+
init_context_path_args(args,ctx,path);
|
1199
|
+
args[3]=release_file_info(ctx,ffi);
|
1200
|
+
|
1201
|
+
res=rb_protect((VALUE (*)())unsafe_releasedir,(VALUE) args,&error);
|
1202
|
+
|
1203
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1204
|
+
}
|
1205
|
+
|
1206
|
+
|
1207
|
+
/*
|
1208
|
+
Sync directory
|
1209
|
+
|
1210
|
+
@overload fsyncdir(context,path,datasync,ffi)
|
1211
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#ba5cc1fe9a63ec152ceb19656f243256 fsyncdir}
|
1212
|
+
@param [Context] context
|
1213
|
+
@param [String] path
|
1214
|
+
@param [Integer] datasync if nonzero sync only data, not metadata
|
1215
|
+
@param [FileInfo] ffi
|
1216
|
+
|
1217
|
+
@return [void]
|
1218
|
+
@raise [Errno]
|
1219
|
+
|
1220
|
+
*/
|
1221
|
+
static VALUE unsafe_fsyncdir(VALUE *args)
|
1222
|
+
{
|
1223
|
+
return rb_funcall(args[0],rb_intern("fsyncdir"),4,&args[1]);
|
1224
|
+
}
|
1225
|
+
|
1226
|
+
static int rf_fsyncdir(const char *path,int meta,struct fuse_file_info *ffi)
|
1227
|
+
{
|
1228
|
+
VALUE args[5];
|
1229
|
+
VALUE res;
|
1230
|
+
int error = 0;
|
1231
|
+
struct fuse_context *ctx=fuse_get_context();
|
1232
|
+
init_context_path_args(args,ctx,path);
|
1233
|
+
args[3]=INT2NUM(meta);
|
1234
|
+
args[4]=get_file_info(ffi);
|
1235
|
+
res=rb_protect((VALUE (*)())unsafe_fsyncdir,(VALUE) args,&error);
|
1236
|
+
|
1237
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1238
|
+
}
|
1239
|
+
|
1240
|
+
/*
|
1241
|
+
Called when filesystem is initialised
|
1242
|
+
|
1243
|
+
@overload init(info)
|
1244
|
+
@abstract Fuse Operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#dc6dc71274f185de72217e38d62142c4 init}
|
1245
|
+
|
1246
|
+
@param [Context] context
|
1247
|
+
@param [Struct] info connection information
|
1248
|
+
|
1249
|
+
@return [void]
|
1250
|
+
*/
|
1251
|
+
static VALUE unsafe_init(VALUE* args)
|
1252
|
+
{
|
1253
|
+
return rb_funcall3(args[0],rb_intern("init"),2,&args[1]);
|
1254
|
+
}
|
1255
|
+
|
1256
|
+
static void *rf_init(struct fuse_conn_info *conn)
|
1257
|
+
{
|
1258
|
+
VALUE args[3];
|
1259
|
+
VALUE res;
|
1260
|
+
int error = 0;
|
1261
|
+
|
1262
|
+
struct fuse_context *ctx = fuse_get_context();
|
1263
|
+
|
1264
|
+
VALUE self = ctx->private_data;
|
1265
|
+
|
1266
|
+
args[0] = self;
|
1267
|
+
args[1] = wrap_context(ctx);
|
1268
|
+
|
1269
|
+
//Create a struct for the conn_info
|
1270
|
+
//TODO - some of these are writable!
|
1271
|
+
VALUE s = rb_const_get(rb_cObject,rb_intern("Struct"));
|
1272
|
+
VALUE fci = rb_funcall(s,rb_intern("new"),7,
|
1273
|
+
ID2SYM(rb_intern("proto_major")),
|
1274
|
+
ID2SYM(rb_intern("proto_minor")),
|
1275
|
+
ID2SYM(rb_intern("async_read")),
|
1276
|
+
ID2SYM(rb_intern("max_write")),
|
1277
|
+
ID2SYM(rb_intern("max_readahead")),
|
1278
|
+
ID2SYM(rb_intern("capable")),
|
1279
|
+
ID2SYM(rb_intern("want"))
|
1280
|
+
);
|
1281
|
+
|
1282
|
+
VALUE fcio = rb_funcall(fci,rb_intern("new"),7,
|
1283
|
+
UINT2NUM(conn->proto_major),
|
1284
|
+
UINT2NUM(conn->proto_minor),
|
1285
|
+
UINT2NUM(conn->async_read),
|
1286
|
+
UINT2NUM(conn->max_write),
|
1287
|
+
UINT2NUM(conn->max_readahead),
|
1288
|
+
UINT2NUM(conn->capable),
|
1289
|
+
UINT2NUM(conn->want)
|
1290
|
+
);
|
1291
|
+
|
1292
|
+
args[2] = fcio;
|
1293
|
+
|
1294
|
+
res = rb_protect((VALUE (*)())unsafe_init,(VALUE) args,&error);
|
1295
|
+
|
1296
|
+
if (error)
|
1297
|
+
{
|
1298
|
+
return NULL;
|
1299
|
+
}
|
1300
|
+
else
|
1301
|
+
{
|
1302
|
+
//This previously was the result of the init call (res)
|
1303
|
+
//but it was never made available to any of the file operations
|
1304
|
+
//and nothing was done to prevent it from being GC'd so
|
1305
|
+
//filesystems would need to have stored it separately anyway
|
1306
|
+
return (void *) self;
|
1307
|
+
}
|
1308
|
+
}
|
1309
|
+
|
1310
|
+
/*
|
1311
|
+
Cleanup filesystem
|
1312
|
+
|
1313
|
+
@overload destroy()
|
1314
|
+
@abstract Fuse Operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#c41d37ab860204fe4bd7612f9fb036c5 destroy}
|
1315
|
+
|
1316
|
+
@param [Context] context
|
1317
|
+
|
1318
|
+
@return [void]
|
1319
|
+
|
1320
|
+
Called at filesystem exit - which itself is triggered when this fuse object
|
1321
|
+
is garbage collected, so not sure it is actually safe to call this
|
1322
|
+
*/
|
1323
|
+
static VALUE unsafe_destroy(VALUE* args)
|
1324
|
+
{
|
1325
|
+
return rb_funcall3(args[0],rb_intern("destroy"),1,&args[1]);
|
1326
|
+
}
|
1327
|
+
|
1328
|
+
static void rf_destroy(void *user_data)
|
1329
|
+
{
|
1330
|
+
VALUE args[2];
|
1331
|
+
int error = 0;
|
1332
|
+
|
1333
|
+
struct fuse_context *ctx = fuse_get_context();
|
1334
|
+
args[0] = ctx->private_data;
|
1335
|
+
args[1] = wrap_context(ctx);
|
1336
|
+
|
1337
|
+
rb_protect((VALUE (*)())unsafe_destroy,(VALUE) args,&error);
|
1338
|
+
}
|
1339
|
+
|
1340
|
+
/*
|
1341
|
+
Check access permissions
|
1342
|
+
|
1343
|
+
@overload access(context,path,mode)
|
1344
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#2248db35e200265f7fb9a18348229858 access}
|
1345
|
+
@param [Context] context
|
1346
|
+
@param [String] path
|
1347
|
+
@param [Integer] mode the permissions to check
|
1348
|
+
|
1349
|
+
@return [void]
|
1350
|
+
@raise [Errno::EACCESS] if the requested permission isn't available
|
1351
|
+
|
1352
|
+
*/
|
1353
|
+
static VALUE unsafe_access(VALUE* args)
|
1354
|
+
{
|
1355
|
+
return rb_funcall3(args[0],rb_intern("access"),3,&args[1]);
|
1356
|
+
}
|
1357
|
+
|
1358
|
+
static int rf_access(const char *path, int mask)
|
1359
|
+
{
|
1360
|
+
VALUE args[4];
|
1361
|
+
VALUE res;
|
1362
|
+
int error = 0;
|
1363
|
+
struct fuse_context *ctx=fuse_get_context();
|
1364
|
+
init_context_path_args(args,ctx,path);
|
1365
|
+
args[3] = INT2NUM(mask);
|
1366
|
+
res = rb_protect((VALUE (*)())unsafe_access,(VALUE) args,&error);
|
1367
|
+
|
1368
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1369
|
+
}
|
1370
|
+
|
1371
|
+
|
1372
|
+
/*
|
1373
|
+
Create and open a file
|
1374
|
+
|
1375
|
+
@overload create(context,path,mode,ffi)
|
1376
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#97243e0f9268a96236bc3b6f2bacee17 create}
|
1377
|
+
@param [Context] context
|
1378
|
+
@param [String] path
|
1379
|
+
@param [Integer] mode the file permissions to create
|
1380
|
+
@param [Fileinfo] ffi - use the {FileInfo#fh} attribute to store a filehandle
|
1381
|
+
|
1382
|
+
@return [void]
|
1383
|
+
@raise [Errno]
|
1384
|
+
|
1385
|
+
If the file does not exist, first create it with the specified mode, and then open it.
|
1386
|
+
|
1387
|
+
*/
|
1388
|
+
static VALUE unsafe_create(VALUE* args)
|
1389
|
+
{
|
1390
|
+
return rb_funcall3(args[0],rb_intern("create"),4,&args[1]);
|
1391
|
+
}
|
1392
|
+
|
1393
|
+
static int rf_create(const char *path, mode_t mode, struct fuse_file_info *ffi)
|
1394
|
+
{
|
1395
|
+
VALUE args[5];
|
1396
|
+
VALUE res;
|
1397
|
+
int error = 0;
|
1398
|
+
|
1399
|
+
struct fuse_context *ctx = fuse_get_context();
|
1400
|
+
init_context_path_args(args,ctx,path);
|
1401
|
+
args[3] = INT2NUM(mode);
|
1402
|
+
args[4] = wrap_file_info(ctx,ffi);
|
1403
|
+
|
1404
|
+
res = rb_protect((VALUE (*)())unsafe_create,(VALUE) args,&error);
|
1405
|
+
|
1406
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1407
|
+
|
1408
|
+
}
|
1409
|
+
|
1410
|
+
|
1411
|
+
/*
|
1412
|
+
Change the size of an open file
|
1413
|
+
|
1414
|
+
@overload ftruncate(context,path,size,ffi)
|
1415
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#1e492882859740f13cbf3344cf963c70 ftruncate}
|
1416
|
+
@param [Context] context
|
1417
|
+
@param [String] path
|
1418
|
+
@param [Integer] size
|
1419
|
+
@param [Fileinfo] ffi
|
1420
|
+
|
1421
|
+
@return [void]
|
1422
|
+
@raise [Errno]
|
1423
|
+
|
1424
|
+
*/
|
1425
|
+
static VALUE unsafe_ftruncate(VALUE* args)
|
1426
|
+
{
|
1427
|
+
return rb_funcall3(args[0],rb_intern("ftruncate"),4,&args[1]);
|
1428
|
+
}
|
1429
|
+
|
1430
|
+
static int rf_ftruncate(const char *path, off_t size,
|
1431
|
+
struct fuse_file_info *ffi)
|
1432
|
+
{
|
1433
|
+
VALUE args[5];
|
1434
|
+
VALUE res;
|
1435
|
+
int error = 0;
|
1436
|
+
|
1437
|
+
struct fuse_context *ctx = fuse_get_context();
|
1438
|
+
init_context_path_args(args,ctx,path);
|
1439
|
+
args[3] = INT2NUM(size);
|
1440
|
+
args[4] = get_file_info(ffi);
|
1441
|
+
|
1442
|
+
res = rb_protect((VALUE (*)())unsafe_ftruncate,(VALUE) args,&error);
|
1443
|
+
|
1444
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1445
|
+
}
|
1446
|
+
|
1447
|
+
|
1448
|
+
/*
|
1449
|
+
Get attributes of an open file
|
1450
|
+
|
1451
|
+
@overload fgetattr(context,path,ffi)
|
1452
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#573d79862df591c98e1685225a4cd3a5 fgetattr}
|
1453
|
+
@param [Context] context
|
1454
|
+
@param [String] path
|
1455
|
+
@param [Fileinfo] ffi
|
1456
|
+
|
1457
|
+
@return [Stat] file attributes
|
1458
|
+
@raise [Errno]
|
1459
|
+
|
1460
|
+
*/
|
1461
|
+
static VALUE unsafe_fgetattr(VALUE *args)
|
1462
|
+
{
|
1463
|
+
return rb_funcall3(args[0],rb_intern("fgetattr"),3,&args[1]);
|
1464
|
+
}
|
1465
|
+
|
1466
|
+
static int rf_fgetattr(const char *path, struct stat *stbuf, struct fuse_file_info *ffi)
|
1467
|
+
{
|
1468
|
+
VALUE args[4];
|
1469
|
+
VALUE res;
|
1470
|
+
int error = 0;
|
1471
|
+
|
1472
|
+
struct fuse_context *ctx = fuse_get_context();
|
1473
|
+
init_context_path_args(args,ctx,path);
|
1474
|
+
args[3] = get_file_info(ffi);
|
1475
|
+
|
1476
|
+
res=rb_protect((VALUE (*)())unsafe_fgetattr,(VALUE) args,&error);
|
1477
|
+
|
1478
|
+
if (error || (res == Qnil))
|
1479
|
+
{
|
1480
|
+
return -(return_error(ENOENT));
|
1481
|
+
}
|
1482
|
+
else
|
1483
|
+
{
|
1484
|
+
rstat2stat(res,stbuf);
|
1485
|
+
return 0;
|
1486
|
+
}
|
1487
|
+
}
|
1488
|
+
|
1489
|
+
/*
|
1490
|
+
Perform POSIX file locking operation
|
1491
|
+
|
1492
|
+
@overload lock(context,path,ffi,cmd,flock)
|
1493
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#1c3fff5cf0c1c2003d117e764b9a76fd lock}
|
1494
|
+
@param [Context] context
|
1495
|
+
@param [String] path
|
1496
|
+
@param [Fileinfo] ffi
|
1497
|
+
@param [Integer] cmd
|
1498
|
+
@param [Struct] flock
|
1499
|
+
|
1500
|
+
@return [void]
|
1501
|
+
@raise [Errno]
|
1502
|
+
|
1503
|
+
The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW.
|
1504
|
+
|
1505
|
+
For the meaning of fields in 'struct flock' see the man page for fcntl(2). The l_whence field will always be set to SEEK_SET.
|
1506
|
+
|
1507
|
+
For checking lock ownership, the {FileInfo#owner} argument must be used.
|
1508
|
+
|
1509
|
+
For F_GETLK operation, the library will first check currently held locks, and if a conflicting lock is found it will return information without calling this method. This ensures, that for local locks the l_pid field is correctly filled in. The results may not be accurate in case of race conditions and in the presence of hard links, but it's unlikly that an application would rely on accurate GETLK results in these cases. If a conflicting lock is not found, this method will be called, and the filesystem may fill out l_pid by a meaningful value, or it may leave this field zero.
|
1510
|
+
|
1511
|
+
For F_SETLK and F_SETLKW the l_pid field will be set to the pid of the process performing the locking operation.
|
1512
|
+
|
1513
|
+
Note: if this method is not implemented, the kernel will still allow file locking to work locally. Hence it is only interesting for network filesystems and similar.
|
1514
|
+
*/
|
1515
|
+
static VALUE unsafe_lock(VALUE *args)
|
1516
|
+
{
|
1517
|
+
return rb_funcall3(args[0],rb_intern("lock"),5,&args[1]);
|
1518
|
+
}
|
1519
|
+
|
1520
|
+
static int rf_lock(const char *path, struct fuse_file_info *ffi,
|
1521
|
+
int cmd, struct flock *lock)
|
1522
|
+
{
|
1523
|
+
VALUE args[6];
|
1524
|
+
VALUE res;
|
1525
|
+
int error = 0;
|
1526
|
+
|
1527
|
+
struct fuse_context *ctx = fuse_get_context();
|
1528
|
+
init_context_path_args(args,ctx,path);
|
1529
|
+
|
1530
|
+
//TODO Wrap the struct flock so these attributes can be set
|
1531
|
+
|
1532
|
+
//Create a struct for the lock structure
|
1533
|
+
VALUE s = rb_const_get(rb_cObject,rb_intern("Struct"));
|
1534
|
+
VALUE lockc = rb_funcall(s,rb_intern("new"),5,
|
1535
|
+
ID2SYM(rb_intern("l_type")),
|
1536
|
+
ID2SYM(rb_intern("l_whence")),
|
1537
|
+
ID2SYM(rb_intern("l_start")),
|
1538
|
+
ID2SYM(rb_intern("l_len")),
|
1539
|
+
ID2SYM(rb_intern("l_pid"))
|
1540
|
+
);
|
1541
|
+
|
1542
|
+
VALUE locko = rb_funcall(lockc,rb_intern("new"),5,
|
1543
|
+
UINT2NUM(lock->l_type),
|
1544
|
+
UINT2NUM(lock->l_whence),
|
1545
|
+
UINT2NUM(lock->l_start),
|
1546
|
+
UINT2NUM(lock->l_len),
|
1547
|
+
UINT2NUM(lock->l_pid)
|
1548
|
+
);
|
1549
|
+
|
1550
|
+
args[3] = get_file_info(ffi);
|
1551
|
+
args[4] = INT2NUM(cmd);
|
1552
|
+
args[5] = locko;
|
1553
|
+
|
1554
|
+
res = rb_protect((VALUE (*)())unsafe_lock,(VALUE) args,&error);
|
1555
|
+
|
1556
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1557
|
+
}
|
1558
|
+
|
1559
|
+
|
1560
|
+
/*
|
1561
|
+
Change access/modification times of a file
|
1562
|
+
|
1563
|
+
@overload utimens(context,path,actime,modtime)
|
1564
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#79955861cc5eb006954476607ef28944 utimens}
|
1565
|
+
|
1566
|
+
@param [Context] context
|
1567
|
+
@param [String] path
|
1568
|
+
@param [Integer] actime access time in nanoseconds
|
1569
|
+
@param [Integer] modtime modification time in nanoseconds
|
1570
|
+
|
1571
|
+
@return [void]
|
1572
|
+
@raise [Errno]
|
1573
|
+
*/
|
1574
|
+
static VALUE unsafe_utimens(VALUE *args)
|
1575
|
+
{
|
1576
|
+
return rb_funcall3(args[0],rb_intern("utimens"),4,&args[1]);
|
1577
|
+
}
|
1578
|
+
|
1579
|
+
static int rf_utimens(const char * path, const struct timespec tv[2])
|
1580
|
+
{
|
1581
|
+
VALUE args[5];
|
1582
|
+
VALUE res;
|
1583
|
+
int error = 0;
|
1584
|
+
|
1585
|
+
struct fuse_context *ctx = fuse_get_context();
|
1586
|
+
init_context_path_args(args,ctx,path);
|
1587
|
+
|
1588
|
+
// tv_sec * 1000000 + tv_nsec
|
1589
|
+
args[3] = rb_funcall(
|
1590
|
+
rb_funcall(
|
1591
|
+
INT2NUM(tv[0].tv_sec), rb_intern("*"), 1, INT2NUM(1000000)
|
1592
|
+
),
|
1593
|
+
rb_intern("+"), 1, INT2NUM(tv[0].tv_nsec)
|
1594
|
+
);
|
1595
|
+
|
1596
|
+
args[4] = rb_funcall(
|
1597
|
+
rb_funcall(
|
1598
|
+
INT2NUM(tv[1].tv_sec), rb_intern("*"), 1, INT2NUM(1000000)
|
1599
|
+
),
|
1600
|
+
rb_intern("+"), 1, INT2NUM(tv[1].tv_nsec)
|
1601
|
+
);
|
1602
|
+
|
1603
|
+
res = rb_protect((VALUE (*)())unsafe_utimens,(VALUE) args, &error);
|
1604
|
+
return error ? -(return_error(ENOENT)) : 0 ;
|
1605
|
+
}
|
1606
|
+
|
1607
|
+
/*
|
1608
|
+
Map block index within file to block index within device
|
1609
|
+
|
1610
|
+
@overload bmap(context,path,blocksize,index)
|
1611
|
+
@abstract Fuse operation {http://fuse.sourceforge.net/doxygen/structfuse__operations.html#e3f3482e33a0eada0292350d76b82901 bmap}
|
1612
|
+
|
1613
|
+
@param [Context] context
|
1614
|
+
@param [String] path
|
1615
|
+
@param [Integer] blocksize
|
1616
|
+
@param [Integer] index
|
1617
|
+
|
1618
|
+
@return [Integer] device relative block index
|
1619
|
+
@raise [Errno]
|
1620
|
+
|
1621
|
+
|
1622
|
+
Note: This makes sense only for block device backed filesystems mounted with the 'blkdev' option
|
1623
|
+
*/
|
1624
|
+
static VALUE unsafe_bmap(VALUE *args)
|
1625
|
+
{
|
1626
|
+
return rb_funcall3(args[0],rb_intern("bmap"),4,&args[1]);
|
1627
|
+
}
|
1628
|
+
|
1629
|
+
static int rf_bmap(const char *path, size_t blocksize, uint64_t *idx)
|
1630
|
+
{
|
1631
|
+
VALUE args[5];
|
1632
|
+
VALUE res;
|
1633
|
+
int error = 0;
|
1634
|
+
|
1635
|
+
struct fuse_context *ctx = fuse_get_context();
|
1636
|
+
init_context_path_args(args,ctx,path);
|
1637
|
+
args[3] = INT2NUM(blocksize);
|
1638
|
+
args[4] = LL2NUM(*idx);
|
1639
|
+
|
1640
|
+
res = rb_protect((VALUE (*)())unsafe_bmap,(VALUE) args, &error);
|
1641
|
+
|
1642
|
+
if (error)
|
1643
|
+
{
|
1644
|
+
return -(return_error(ENOENT));
|
1645
|
+
}
|
1646
|
+
else
|
1647
|
+
{
|
1648
|
+
*idx = NUM2LL(res);
|
1649
|
+
return 0;
|
1650
|
+
}
|
1651
|
+
}
|
1652
|
+
|
1653
|
+
//----------------------IOCTL
|
1654
|
+
|
1655
|
+
static VALUE unsafe_ioctl(VALUE *args)
|
1656
|
+
{
|
1657
|
+
VALUE path = args[0];
|
1658
|
+
VALUE cmd = args[1];
|
1659
|
+
VALUE arg = args[2];
|
1660
|
+
VALUE ffi = args[3];
|
1661
|
+
VALUE flags = args[4];
|
1662
|
+
VALUE data = args[5];
|
1663
|
+
|
1664
|
+
struct fuse_context *ctx = fuse_get_context();
|
1665
|
+
|
1666
|
+
return rb_funcall( ctx->private_data, rb_intern("ioctl"), 7, wrap_context(ctx),
|
1667
|
+
path, cmd, arg, ffi, flags, data);
|
1668
|
+
}
|
1669
|
+
|
1670
|
+
static int rf_ioctl(const char *path, int cmd, void *arg,
|
1671
|
+
struct fuse_file_info *ffi, unsigned int flags, void *data)
|
1672
|
+
{
|
1673
|
+
VALUE args[6];
|
1674
|
+
VALUE res;
|
1675
|
+
int error = 0;
|
1676
|
+
|
1677
|
+
args[0] = rb_str_new2(path);
|
1678
|
+
rb_enc_associate(args[0],rb_filesystem_encoding());
|
1679
|
+
args[1] = INT2NUM(cmd);
|
1680
|
+
args[2] = wrap_buffer(arg);
|
1681
|
+
args[3] = get_file_info(ffi);
|
1682
|
+
args[4] = INT2NUM(flags);
|
1683
|
+
args[5] = wrap_buffer(data);
|
1684
|
+
|
1685
|
+
res = rb_protect((VALUE (*)())unsafe_ioctl,(VALUE) args, &error);
|
1686
|
+
|
1687
|
+
if (error)
|
1688
|
+
{
|
1689
|
+
return -(return_error(ENOENT));
|
1690
|
+
}
|
1691
|
+
|
1692
|
+
return 0;
|
1693
|
+
}
|
1694
|
+
|
1695
|
+
//----------------------POLL
|
1696
|
+
|
1697
|
+
static VALUE unsafe_poll(VALUE *args)
|
1698
|
+
{
|
1699
|
+
VALUE path = args[0];
|
1700
|
+
VALUE ffi = args[1];
|
1701
|
+
VALUE ph = args[2];
|
1702
|
+
VALUE reventsp = args[3];
|
1703
|
+
|
1704
|
+
struct fuse_context *ctx = fuse_get_context();
|
1705
|
+
|
1706
|
+
return rb_funcall( ctx->private_data, rb_intern("poll"), 5, wrap_context(ctx),
|
1707
|
+
path, ffi, ph, reventsp);
|
1708
|
+
}
|
1709
|
+
|
1710
|
+
static int rf_poll(const char *path, struct fuse_file_info *ffi,
|
1711
|
+
struct fuse_pollhandle *ph, unsigned *reventsp)
|
1712
|
+
{
|
1713
|
+
VALUE args[4];
|
1714
|
+
VALUE res;
|
1715
|
+
int error = 0;
|
1716
|
+
|
1717
|
+
args[0] = rb_str_new2(path);
|
1718
|
+
rb_enc_associate(args[0],rb_filesystem_encoding());
|
1719
|
+
args[1] = get_file_info(ffi);
|
1720
|
+
args[2] = wrap_pollhandle(ph);
|
1721
|
+
args[3] = INT2NUM(*reventsp);
|
1722
|
+
|
1723
|
+
res = rb_protect((VALUE (*)())unsafe_poll,(VALUE) args, &error);
|
1724
|
+
|
1725
|
+
if (error)
|
1726
|
+
{
|
1727
|
+
return -(return_error(ENOENT));
|
1728
|
+
}
|
1729
|
+
else
|
1730
|
+
{
|
1731
|
+
*reventsp = NUM2INT(args[3]);
|
1732
|
+
}
|
1733
|
+
return 0;
|
1734
|
+
}
|
1735
|
+
|
1736
|
+
/*
|
1737
|
+
Is the filesystem successfully mounted
|
1738
|
+
|
1739
|
+
@return [Boolean] true if mounted, false otherwise
|
1740
|
+
|
1741
|
+
*/
|
1742
|
+
static VALUE rf_mounted(VALUE self)
|
1743
|
+
{
|
1744
|
+
struct intern_fuse *inf;
|
1745
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1746
|
+
|
1747
|
+
// Never mounted, unmounted via fusermount, or via rf_unmount
|
1748
|
+
return (inf->fuse == NULL || fuse_exited(inf->fuse) ) ? Qfalse : Qtrue;
|
1749
|
+
}
|
1750
|
+
|
1751
|
+
/*
|
1752
|
+
Unmount filesystem
|
1753
|
+
*/
|
1754
|
+
VALUE rf_unmount(VALUE self)
|
1755
|
+
{
|
1756
|
+
struct intern_fuse *inf;
|
1757
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1758
|
+
|
1759
|
+
fuse_exit(inf->fuse);
|
1760
|
+
|
1761
|
+
if (inf->fc != NULL) {
|
1762
|
+
fuse_unmount(inf->mountpoint, inf->fc);
|
1763
|
+
inf->fc = NULL;
|
1764
|
+
}
|
1765
|
+
return Qnil;
|
1766
|
+
}
|
1767
|
+
|
1768
|
+
/*
|
1769
|
+
@return [String] directory where this filesystem is mounted
|
1770
|
+
*/
|
1771
|
+
VALUE rf_mountname(VALUE self)
|
1772
|
+
{
|
1773
|
+
struct intern_fuse *inf;
|
1774
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1775
|
+
VALUE result = rb_str_new2(inf->mountpoint);
|
1776
|
+
rb_enc_associate(result,rb_filesystem_encoding());
|
1777
|
+
|
1778
|
+
return result;
|
1779
|
+
}
|
1780
|
+
|
1781
|
+
/*
|
1782
|
+
@deprecated obsolete in FUSE itself
|
1783
|
+
*/
|
1784
|
+
VALUE rf_invalidate(VALUE self,VALUE path)
|
1785
|
+
{
|
1786
|
+
struct intern_fuse *inf;
|
1787
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1788
|
+
return fuse_invalidate(inf->fuse,STR2CSTR(path));
|
1789
|
+
}
|
1790
|
+
|
1791
|
+
/*
|
1792
|
+
@return [Integer] /dev/fuse file descriptor for use with IO.select and {#process}
|
1793
|
+
@raise [RFuse::Error] if fuse not mounted
|
1794
|
+
*/
|
1795
|
+
VALUE rf_fd(VALUE self)
|
1796
|
+
{
|
1797
|
+
struct intern_fuse *inf;
|
1798
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1799
|
+
if (inf->fuse == NULL) {
|
1800
|
+
rb_raise(eRFuse_Error,"FUSE not mounted");
|
1801
|
+
return Qnil;
|
1802
|
+
} else {
|
1803
|
+
return INT2NUM(intern_fuse_fd(inf));
|
1804
|
+
}
|
1805
|
+
}
|
1806
|
+
|
1807
|
+
/*
|
1808
|
+
Process one fuse command from the kernel
|
1809
|
+
|
1810
|
+
@return [Integer] 0 if successful
|
1811
|
+
@raise [RFuse::Error] if fuse not mounted
|
1812
|
+
*/
|
1813
|
+
VALUE rf_process(VALUE self)
|
1814
|
+
{
|
1815
|
+
struct intern_fuse *inf;
|
1816
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1817
|
+
if (inf->fuse == NULL) {
|
1818
|
+
rb_raise(eRFuse_Error,"FUSE not mounted");
|
1819
|
+
return Qnil;
|
1820
|
+
} else {
|
1821
|
+
return INT2NUM(intern_fuse_process(inf));
|
1822
|
+
}
|
1823
|
+
}
|
1824
|
+
|
1825
|
+
#define RESPOND_TO(obj,methodname) \
|
1826
|
+
rb_funcall( \
|
1827
|
+
obj,rb_intern("respond_to?"), \
|
1828
|
+
1, rb_str_new2(methodname) \
|
1829
|
+
) == Qtrue
|
1830
|
+
|
1831
|
+
/*
|
1832
|
+
* initialize and mount the filesystem
|
1833
|
+
* @param [String] mountpoint The mountpoint
|
1834
|
+
* @param [Array<String>] options fuse arguments (-h to see a list)
|
1835
|
+
*/
|
1836
|
+
static VALUE rf_initialize(
|
1837
|
+
VALUE self,
|
1838
|
+
VALUE mountpoint_obj,
|
1839
|
+
VALUE opts)
|
1840
|
+
{
|
1841
|
+
|
1842
|
+
//Allow things like Pathname to be sent as a mountpoint
|
1843
|
+
VALUE mountpoint = rb_obj_as_string(mountpoint_obj);
|
1844
|
+
Check_Type(opts, T_ARRAY);
|
1845
|
+
|
1846
|
+
struct intern_fuse *inf;
|
1847
|
+
Data_Get_Struct(self,struct intern_fuse,inf);
|
1848
|
+
|
1849
|
+
inf->mountpoint = strdup(StringValueCStr(mountpoint));
|
1850
|
+
|
1851
|
+
if (RESPOND_TO(self,"getattr"))
|
1852
|
+
inf->fuse_op.getattr = rf_getattr;
|
1853
|
+
if (RESPOND_TO(self,"readlink"))
|
1854
|
+
inf->fuse_op.readlink = rf_readlink;
|
1855
|
+
if (RESPOND_TO(self,"getdir"))
|
1856
|
+
inf->fuse_op.getdir = rf_getdir; // Deprecated
|
1857
|
+
if (RESPOND_TO(self,"mknod"))
|
1858
|
+
inf->fuse_op.mknod = rf_mknod;
|
1859
|
+
if (RESPOND_TO(self,"mkdir"))
|
1860
|
+
inf->fuse_op.mkdir = rf_mkdir;
|
1861
|
+
if (RESPOND_TO(self,"unlink"))
|
1862
|
+
inf->fuse_op.unlink = rf_unlink;
|
1863
|
+
if (RESPOND_TO(self,"rmdir"))
|
1864
|
+
inf->fuse_op.rmdir = rf_rmdir;
|
1865
|
+
if (RESPOND_TO(self,"symlink"))
|
1866
|
+
inf->fuse_op.symlink = rf_symlink;
|
1867
|
+
if (RESPOND_TO(self,"rename"))
|
1868
|
+
inf->fuse_op.rename = rf_rename;
|
1869
|
+
if (RESPOND_TO(self,"link"))
|
1870
|
+
inf->fuse_op.link = rf_link;
|
1871
|
+
if (RESPOND_TO(self,"chmod"))
|
1872
|
+
inf->fuse_op.chmod = rf_chmod;
|
1873
|
+
if (RESPOND_TO(self,"chown"))
|
1874
|
+
inf->fuse_op.chown = rf_chown;
|
1875
|
+
if (RESPOND_TO(self,"truncate"))
|
1876
|
+
inf->fuse_op.truncate = rf_truncate;
|
1877
|
+
if (RESPOND_TO(self,"utime"))
|
1878
|
+
inf->fuse_op.utime = rf_utime; // Deprecated
|
1879
|
+
if (RESPOND_TO(self,"open")) {
|
1880
|
+
inf->fuse_op.open = rf_open;
|
1881
|
+
inf->fuse_op.release = rf_release_ffi; // remove open file reference
|
1882
|
+
}
|
1883
|
+
if (RESPOND_TO(self,"create")) {
|
1884
|
+
inf->fuse_op.create = rf_create;
|
1885
|
+
inf->fuse_op.release = rf_release_ffi; // remove open file reference
|
1886
|
+
}
|
1887
|
+
if (RESPOND_TO(self,"read"))
|
1888
|
+
inf->fuse_op.read = rf_read;
|
1889
|
+
if (RESPOND_TO(self,"write"))
|
1890
|
+
inf->fuse_op.write = rf_write;
|
1891
|
+
if (RESPOND_TO(self,"statfs"))
|
1892
|
+
inf->fuse_op.statfs = rf_statfs;
|
1893
|
+
if (RESPOND_TO(self,"flush"))
|
1894
|
+
inf->fuse_op.flush = rf_flush;
|
1895
|
+
if (RESPOND_TO(self,"release"))
|
1896
|
+
inf->fuse_op.release = rf_release;
|
1897
|
+
if (RESPOND_TO(self,"fsync"))
|
1898
|
+
inf->fuse_op.fsync = rf_fsync;
|
1899
|
+
if (RESPOND_TO(self,"setxattr"))
|
1900
|
+
inf->fuse_op.setxattr = rf_setxattr;
|
1901
|
+
if (RESPOND_TO(self,"getxattr"))
|
1902
|
+
inf->fuse_op.getxattr = rf_getxattr;
|
1903
|
+
if (RESPOND_TO(self,"listxattr"))
|
1904
|
+
inf->fuse_op.listxattr = rf_listxattr;
|
1905
|
+
if (RESPOND_TO(self,"removexattr"))
|
1906
|
+
inf->fuse_op.removexattr = rf_removexattr;
|
1907
|
+
if (RESPOND_TO(self,"opendir")) {
|
1908
|
+
inf->fuse_op.opendir = rf_opendir;
|
1909
|
+
inf->fuse_op.release = rf_release_ffi; // remove open file reference
|
1910
|
+
}
|
1911
|
+
if (RESPOND_TO(self,"readdir"))
|
1912
|
+
inf->fuse_op.readdir = rf_readdir;
|
1913
|
+
if (RESPOND_TO(self,"releasedir"))
|
1914
|
+
inf->fuse_op.releasedir = rf_releasedir;
|
1915
|
+
if (RESPOND_TO(self,"fsyncdir"))
|
1916
|
+
inf->fuse_op.fsyncdir = rf_fsyncdir;
|
1917
|
+
if (RESPOND_TO(self,"init"))
|
1918
|
+
inf->fuse_op.init = rf_init;
|
1919
|
+
// if (RESPOND_TO(self,"destroy"))
|
1920
|
+
// inf->fuse_op.destroy = rf_destroy;
|
1921
|
+
if (RESPOND_TO(self,"access"))
|
1922
|
+
inf->fuse_op.access = rf_access;
|
1923
|
+
if (RESPOND_TO(self,"ftruncate"))
|
1924
|
+
inf->fuse_op.ftruncate = rf_ftruncate;
|
1925
|
+
if (RESPOND_TO(self,"fgetattr"))
|
1926
|
+
inf->fuse_op.fgetattr = rf_fgetattr;
|
1927
|
+
if (RESPOND_TO(self,"lock"))
|
1928
|
+
inf->fuse_op.lock = rf_lock;
|
1929
|
+
if (RESPOND_TO(self,"utimens"))
|
1930
|
+
inf->fuse_op.utimens = rf_utimens;
|
1931
|
+
if (RESPOND_TO(self,"bmap"))
|
1932
|
+
inf->fuse_op.bmap = rf_bmap;
|
1933
|
+
/*
|
1934
|
+
if (RESPOND_TO(self,"ioctl"))
|
1935
|
+
inf->fuse_op.ioctl = rf_ioctl;
|
1936
|
+
if (RESPOND_TO(self,"poll"))
|
1937
|
+
inf->fuse_op.poll = rf_poll;
|
1938
|
+
*/
|
1939
|
+
|
1940
|
+
struct fuse_args *args = rarray2fuseargs(opts);
|
1941
|
+
|
1942
|
+
//Store our fuse object in user_data, this will be returned to use in the
|
1943
|
+
//session context
|
1944
|
+
void* user_data = self;
|
1945
|
+
|
1946
|
+
int init_result;
|
1947
|
+
|
1948
|
+
// init_result indicates not mounted, but so does inf->fuse == NULL
|
1949
|
+
// raise exceptions only if we try to use the mount
|
1950
|
+
// can test with mounted?
|
1951
|
+
init_result = intern_fuse_init(inf, args, user_data);
|
1952
|
+
|
1953
|
+
//Create the open files hash where we cache FileInfo objects
|
1954
|
+
VALUE open_files_hash;
|
1955
|
+
if (init_result == 0) {
|
1956
|
+
open_files_hash=rb_hash_new();
|
1957
|
+
rb_iv_set(self,"@open_files",open_files_hash);
|
1958
|
+
rb_funcall(self,rb_intern("ruby_initialize"),0);
|
1959
|
+
}
|
1960
|
+
return self;
|
1961
|
+
}
|
1962
|
+
|
1963
|
+
static VALUE rf_new(VALUE class)
|
1964
|
+
{
|
1965
|
+
struct intern_fuse *inf;
|
1966
|
+
VALUE self;
|
1967
|
+
inf = intern_fuse_new();
|
1968
|
+
self=Data_Wrap_Struct(class, 0, intern_fuse_destroy, inf);
|
1969
|
+
return self;
|
1970
|
+
}
|
1971
|
+
|
1972
|
+
/*
|
1973
|
+
* Document-class: RFuse::Fuse
|
1974
|
+
*
|
1975
|
+
* A FUSE filesystem - extend this class implementing
|
1976
|
+
* the various abstract methods to provide your filesystem.
|
1977
|
+
*
|
1978
|
+
* All file operations take a {Context} and a path as well as any other necessary parameters
|
1979
|
+
*
|
1980
|
+
* Mount your filesystem by creating an instance of your subclass and call #loop to begin processing
|
1981
|
+
*/
|
1982
|
+
void rfuse_init(VALUE module)
|
1983
|
+
{
|
1984
|
+
#if 0
|
1985
|
+
//Trick Yardoc
|
1986
|
+
mRFuse = rb_define_mRFuse("RFuse");
|
1987
|
+
#endif
|
1988
|
+
mRFuse = module;
|
1989
|
+
VALUE cFuse=rb_define_class_under(mRFuse,"Fuse",rb_cObject);
|
1990
|
+
|
1991
|
+
rb_define_alloc_func(cFuse,rf_new);
|
1992
|
+
|
1993
|
+
rb_define_method(cFuse,"initialize",rf_initialize,2);
|
1994
|
+
rb_define_method(cFuse,"mounted?",rf_mounted,0);
|
1995
|
+
rb_define_method(cFuse,"invalidate",rf_invalidate,1);
|
1996
|
+
rb_define_method(cFuse,"unmount",rf_unmount,0);
|
1997
|
+
rb_define_method(cFuse,"mountname",rf_mountname,0);
|
1998
|
+
rb_define_alias(cFuse,"mountpoint","mountname");
|
1999
|
+
rb_define_method(cFuse,"fd",rf_fd,0);
|
2000
|
+
rb_define_method(cFuse,"process",rf_process,0);
|
2001
|
+
rb_attr(cFuse,rb_intern("open_files"),1,0,Qfalse);
|
2002
|
+
|
2003
|
+
eRFuse_Error = rb_define_class_under(mRFuse,"Error",rb_eStandardError);
|
2004
|
+
|
2005
|
+
#if 0
|
2006
|
+
//Trick Yarddoc into documenting abstract fuseoperations
|
2007
|
+
rb_define_method(cFuse,"readdir",unsafe_readdir,0);
|
2008
|
+
rb_define_method(cFuse,"readlink",unsafe_readlink,0);
|
2009
|
+
rb_define_method(cFuse,"getdir",unsafe_getdir,0);
|
2010
|
+
rb_define_method(cFuse,"mknod",unsafe_mknod,0);
|
2011
|
+
rb_define_method(cFuse,"getattr",unsafe_getattr,0);
|
2012
|
+
rb_define_method(cFuse,"mkdir",unsafe_mkdir,0);
|
2013
|
+
rb_define_method(cFuse,"open",unsafe_open,0);
|
2014
|
+
rb_define_method(cFuse,"release",unsafe_release,0);
|
2015
|
+
rb_define_method(cFuse,"fsync",unsafe_fsync,0);
|
2016
|
+
rb_define_method(cFuse,"flush",unsafe_flush,0);
|
2017
|
+
rb_define_method(cFuse,"truncate",unsafe_truncate,0);
|
2018
|
+
rb_define_method(cFuse,"utime",unsafe_utime,0);
|
2019
|
+
rb_define_method(cFuse,"chown",unsafe_chown,0);
|
2020
|
+
rb_define_method(cFuse,"chmod",unsafe_chmod,0);
|
2021
|
+
rb_define_method(cFuse,"unlink",unsafe_unlink,0);
|
2022
|
+
rb_define_method(cFuse,"symlink",unsafe_symlink,0);
|
2023
|
+
rb_define_method(cFuse,"rename",unsafe_rename,0);
|
2024
|
+
rb_define_method(cFuse,"link",unsafe_link,0);
|
2025
|
+
rb_define_method(cFuse,"read",unsafe_read,0);
|
2026
|
+
rb_define_method(cFuse,"write",unsafe_write,0);
|
2027
|
+
rb_define_method(cFuse,"statfs",unsafe_statfs,0);
|
2028
|
+
rb_define_method(cFuse,"setxattr",unsafe_setxattr,0);
|
2029
|
+
rb_define_method(cFuse,"getxattr",unsafe_getxattr,0);
|
2030
|
+
rb_define_method(cFuse,"listxattr",unsafe_listxattr,0);
|
2031
|
+
rb_define_method(cFuse,"removexattr",unsafe_removexattr,0);
|
2032
|
+
rb_define_method(cFuse,"opendir",unsafe_opendir,0);
|
2033
|
+
rb_define_method(cFuse,"releasedir",unsafe_releasedir,0);
|
2034
|
+
rb_define_method(cFuse,"fsyncdir",unsafe_fsyncdir,0);
|
2035
|
+
rb_define_method(cFuse,"init",unsafe_init,0);
|
2036
|
+
rb_define_method(cFuse,"destroy",unsafe_destroy,0);
|
2037
|
+
rb_define_method(cFuse,"access",unsafe_access,0);
|
2038
|
+
rb_define_method(cFuse,"create",unsafe_create,0);
|
2039
|
+
rb_define_method(cFuse,"ftruncate",unsafe_ftruncate,0);
|
2040
|
+
rb_define_method(cFuse,"fgetattr",unsafe_fgetattr,0);
|
2041
|
+
rb_define_method(cFuse,"lock",unsafe_lock,0);
|
2042
|
+
rb_define_method(cFuse,"utimens",unsafe_utimens,0);
|
2043
|
+
rb_define_method(cFuse,"bmap",unsafe_bmap,0);
|
2044
|
+
#endif
|
2045
|
+
}
|