ffi-libfuse 0.0.1.pre → 0.1.0.rc20220550
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +3 -1
- data/CHANGES.md +14 -0
- data/LICENSE +21 -0
- data/README.md +127 -44
- data/lib/ffi/accessors.rb +6 -6
- data/lib/ffi/boolean_int.rb +27 -0
- data/lib/ffi/devt.rb +23 -0
- data/lib/ffi/encoding.rb +38 -0
- data/lib/ffi/gnu_extensions.rb +1 -1
- data/lib/ffi/libfuse/ackbar.rb +6 -8
- data/lib/ffi/libfuse/adapter/context.rb +12 -10
- data/lib/ffi/libfuse/adapter/fuse2_compat.rb +52 -51
- data/lib/ffi/libfuse/adapter/fuse3_support.rb +0 -1
- data/lib/ffi/libfuse/adapter/ruby.rb +499 -148
- data/lib/ffi/libfuse/adapter/safe.rb +1 -1
- data/lib/ffi/libfuse/adapter.rb +1 -2
- data/lib/ffi/libfuse/callbacks.rb +1 -1
- data/lib/ffi/libfuse/filesystem/accounting.rb +116 -0
- data/lib/ffi/libfuse/filesystem/mapped_dir.rb +74 -0
- data/lib/ffi/libfuse/filesystem/mapped_files.rb +141 -0
- data/lib/ffi/libfuse/filesystem/pass_through_dir.rb +55 -0
- data/lib/ffi/libfuse/filesystem/pass_through_file.rb +45 -0
- data/lib/ffi/libfuse/filesystem/utils.rb +102 -0
- data/lib/ffi/libfuse/filesystem/virtual_dir.rb +306 -0
- data/lib/ffi/libfuse/filesystem/virtual_file.rb +94 -0
- data/lib/ffi/libfuse/filesystem/virtual_fs.rb +188 -0
- data/lib/ffi/libfuse/filesystem/virtual_node.rb +101 -0
- data/lib/ffi/libfuse/filesystem.rb +25 -0
- data/lib/ffi/libfuse/fuse2.rb +21 -21
- data/lib/ffi/libfuse/fuse3.rb +12 -12
- data/lib/ffi/libfuse/fuse_args.rb +69 -34
- data/lib/ffi/libfuse/fuse_buffer.rb +128 -26
- data/lib/ffi/libfuse/fuse_callbacks.rb +1 -5
- data/lib/ffi/libfuse/fuse_common.rb +55 -61
- data/lib/ffi/libfuse/fuse_config.rb +134 -143
- data/lib/ffi/libfuse/fuse_conn_info.rb +310 -134
- data/lib/ffi/libfuse/fuse_context.rb +45 -3
- data/lib/ffi/libfuse/fuse_operations.rb +43 -19
- data/lib/ffi/libfuse/fuse_version.rb +10 -6
- data/lib/ffi/libfuse/main.rb +80 -37
- data/lib/ffi/libfuse/thread_pool.rb +1 -1
- data/lib/ffi/libfuse/version.rb +1 -1
- data/lib/ffi/libfuse.rb +13 -4
- data/lib/ffi/ruby_object.rb +1 -1
- data/lib/ffi/stat/constants.rb +9 -0
- data/lib/ffi/stat/native.rb +36 -6
- data/lib/ffi/stat/time_spec.rb +28 -12
- data/lib/ffi/stat.rb +111 -22
- data/lib/ffi/stat_vfs.rb +59 -1
- data/lib/ffi/struct_wrapper.rb +22 -1
- data/sample/hello_fs.rb +54 -0
- data/sample/memory_fs.rb +5 -181
- data/sample/no_fs.rb +20 -21
- data/sample/pass_through_fs.rb +30 -0
- metadata +66 -7
- data/lib/ffi/libfuse/adapter/thread_local_context.rb +0 -36
@@ -13,7 +13,7 @@ module FFI
|
|
13
13
|
attach_function :fuse_get_session, [:fuse], :session
|
14
14
|
attach_function :fuse_set_signal_handlers, [:session], :int
|
15
15
|
attach_function :fuse_remove_signal_handlers, [:session], :void
|
16
|
-
attach_function :fuse_loop, [:fuse], :int
|
16
|
+
attach_function :fuse_loop, [:fuse], :int
|
17
17
|
attach_function :fuse_clean_cache, [:fuse], :int
|
18
18
|
attach_function :fuse_exit, [:fuse], :void
|
19
19
|
attach_function :fuse_destroy, [:fuse], :void
|
@@ -42,16 +42,11 @@ module FFI
|
|
42
42
|
def run(native: false, **options)
|
43
43
|
return false unless mounted?
|
44
44
|
|
45
|
-
|
46
|
-
run_native(**options)
|
47
|
-
else
|
48
|
-
run_ruby(**options)
|
49
|
-
end
|
45
|
+
native ? run_native(**options) : run_ruby(**options)
|
50
46
|
rescue Errno => e
|
51
47
|
-e.errno
|
52
|
-
rescue StandardError => e
|
53
|
-
warn e
|
54
|
-
warn e.backtrace.join("\n")
|
48
|
+
rescue StandardError, ScriptError => e
|
49
|
+
warn "#{e}\n#{e.backtrace.join("\n")}"
|
55
50
|
-1
|
56
51
|
ensure
|
57
52
|
teardown
|
@@ -75,15 +70,14 @@ module FFI
|
|
75
70
|
#
|
76
71
|
# * clone_fd is ignored
|
77
72
|
# * filesystem interrupts probably can't work
|
78
|
-
def run_ruby(foreground: true, single_thread: true, traps: {}, **options)
|
73
|
+
def run_ruby(foreground: true, single_thread: true, traps: {}, remember: false, **options)
|
79
74
|
Ackbar.trap(default_traps.merge(traps)) do |signals|
|
80
75
|
daemonize unless foreground
|
81
76
|
|
82
|
-
if
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
end
|
77
|
+
# Monitor for signals (and cache cleaning if required)
|
78
|
+
signals.monitor { fuse_cache_timeout(remember) }
|
79
|
+
|
80
|
+
single_thread ? fuse_loop(**options) : fuse_loop_mt(**options)
|
87
81
|
0
|
88
82
|
end
|
89
83
|
end
|
@@ -100,43 +94,28 @@ module FFI
|
|
100
94
|
# * multi-threading will create a new ruby thread for every callback
|
101
95
|
# * cannot daemonize multi-threaded (hangs) TODO: Why - pthread_lock?, GVL?
|
102
96
|
# * cannot pass signals to the filesystem
|
97
|
+
# * connot use fuse_context (because the ruby thread is not the native thread)
|
103
98
|
#
|
104
99
|
# @api private
|
105
100
|
# @param [Boolean] foreground
|
106
101
|
# @param [Boolean] single_thread
|
107
|
-
#
|
108
102
|
def run_native(foreground: true, single_thread: true, **options)
|
109
|
-
if !single_thread && !foreground
|
110
|
-
warn 'Cannot run native multi-thread fuse_loop when daemonized. Using single_thread mode'
|
111
|
-
single_thread = true
|
112
|
-
end
|
103
|
+
raise 'Cannot run deamonized native multi-thread fuse_loop' if !single_thread && !foreground
|
113
104
|
|
114
105
|
clear_default_traps
|
115
106
|
(se = session) && Libfuse.fuse_set_signal_handlers(se)
|
116
107
|
|
117
108
|
Libfuse.fuse_daemonize(foreground ? 1 : 0)
|
118
|
-
|
119
|
-
if single_thread
|
120
|
-
Libfuse.fuse_loop(@fuse)
|
121
|
-
else
|
122
|
-
native_fuse_loop_mt(**options)
|
123
|
-
end
|
109
|
+
single_thread ? Libfuse.fuse_loop(@fuse) : native_fuse_loop_mt(**options)
|
124
110
|
ensure
|
125
111
|
(se = session) && Libfuse.fuse_remove_signal_handlers(se)
|
126
112
|
end
|
127
113
|
|
128
|
-
# Tell the processing loop to stop and force unmount the filesystem which is unfortunately required to make
|
129
|
-
# the processing threads, which are mostly blocked on io reads from /dev/fuse fd, to exit.
|
130
|
-
def exit
|
131
|
-
Libfuse.fuse_exit(@fuse) if @fuse
|
132
|
-
# Force threads blocked reading on #io to finish
|
133
|
-
unmount
|
134
|
-
end
|
135
|
-
|
136
114
|
# Ruby implementation of fuse default traps
|
137
115
|
# @see Ackbar
|
138
116
|
def default_traps
|
139
|
-
|
117
|
+
exproc = ->(signame) { exit(signame) }
|
118
|
+
@default_traps ||= { INT: exproc, HUP: exproc, TERM: exproc, TSTP: exproc, PIPE: 'IGNORE' }
|
140
119
|
end
|
141
120
|
|
142
121
|
# @api private
|
@@ -185,24 +164,8 @@ module FFI
|
|
185
164
|
|
186
165
|
# @api private
|
187
166
|
# Ruby implementation of single threaded fuse loop
|
188
|
-
def fuse_loop(
|
189
|
-
|
190
|
-
break unless mounted?
|
191
|
-
|
192
|
-
timeout = remember ? fuse_clean_cache : nil
|
193
|
-
|
194
|
-
ready, _ignore_writable, errors = ::IO.select([io, signals.pr], [], [io], timeout)
|
195
|
-
|
196
|
-
next unless ready || errors
|
197
|
-
|
198
|
-
raise 'FUSE error' unless errors.empty?
|
199
|
-
|
200
|
-
break if ready.include?(io) && !process
|
201
|
-
|
202
|
-
break if ready.include?(signals.pr) && !signals.next
|
203
|
-
rescue Errno::EBADF
|
204
|
-
raise if mounted? # This will occur on exit
|
205
|
-
end
|
167
|
+
def fuse_loop(**_options)
|
168
|
+
fuse_process until fuse_exited?
|
206
169
|
end
|
207
170
|
|
208
171
|
# @api private
|
@@ -212,24 +175,51 @@ module FFI
|
|
212
175
|
# fuse api.
|
213
176
|
#
|
214
177
|
# @see ThreadPool ThreadPool for the mechanism that controls creation and termination of worker threads
|
215
|
-
def fuse_loop_mt(
|
216
|
-
|
178
|
+
def fuse_loop_mt(max_idle_threads: 10, max_threads: nil, **_options)
|
179
|
+
ThreadPool.new(name: 'FuseThread', max_idle: max_idle_threads.to_i, max_active: max_threads&.to_i) do
|
180
|
+
raise StopIteration if fuse_exited?
|
217
181
|
|
218
|
-
|
219
|
-
|
182
|
+
fuse_process
|
183
|
+
end.join
|
220
184
|
end
|
221
185
|
|
222
186
|
# @!visibility private
|
223
187
|
def teardown
|
224
188
|
return unless @fuse
|
225
189
|
|
226
|
-
|
227
|
-
|
228
|
-
|
190
|
+
self.exit&.join
|
191
|
+
|
192
|
+
Libfuse.fuse_destroy(@fuse) if @fuse
|
229
193
|
@fuse = nil
|
194
|
+
ensure
|
195
|
+
ObjectSpace.undefine_finalizer(self)
|
196
|
+
end
|
197
|
+
|
198
|
+
# Starts a thread to unmount the filesystem and stop the processing loop.
|
199
|
+
# generally expected to be called from a signal handler
|
200
|
+
# @return [Thread] the unmount thread
|
201
|
+
def exit(_signame = nil)
|
202
|
+
return unless @fuse
|
203
|
+
|
204
|
+
# Unmount/exit in a separate thread so the main fuse thread can keep running.
|
205
|
+
@exit ||= Thread.new do
|
206
|
+
unmount
|
207
|
+
|
208
|
+
# without this sleep before exit, MacOS does not complete unmounting
|
209
|
+
sleep 0.2 if mac_fuse?
|
210
|
+
|
211
|
+
Libfuse.fuse_exit(@fuse)
|
212
|
+
|
213
|
+
true
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
private
|
218
|
+
|
219
|
+
def fuse_cache_timeout(remember)
|
220
|
+
remember ? fuse_clean_cache : nil
|
230
221
|
end
|
231
222
|
|
232
|
-
# @!visibility private
|
233
223
|
def session
|
234
224
|
return nil unless @fuse
|
235
225
|
|
@@ -244,6 +234,10 @@ module FFI
|
|
244
234
|
Signal.trap(sig, prev) unless prev == 'DEFAULT'
|
245
235
|
end
|
246
236
|
end
|
237
|
+
|
238
|
+
def mac_fuse?
|
239
|
+
FFI::Platform::IS_MAC
|
240
|
+
end
|
247
241
|
end
|
248
242
|
end
|
249
243
|
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative '../accessors'
|
4
|
+
require_relative '../boolean_int'
|
4
5
|
module FFI
|
5
6
|
module Libfuse
|
6
7
|
#
|
@@ -11,195 +12,185 @@ module FFI
|
|
11
12
|
#
|
12
13
|
class FuseConfig < FFI::Struct
|
13
14
|
include FFI::Accessors
|
15
|
+
|
14
16
|
layout(
|
15
17
|
{
|
16
|
-
# @!method set_gid?
|
17
|
-
# @return [Boolean]
|
18
18
|
# @!attribute [r] gid
|
19
|
-
#
|
20
|
-
|
21
|
-
#
|
22
|
-
set_gid: :int,
|
19
|
+
# @return [Integer|nil] if set, this value will be used for the :gid attribute of each file
|
20
|
+
set_gid: :bool_int,
|
23
21
|
gid: :uint,
|
24
22
|
|
25
|
-
# @!method set_uid?
|
26
|
-
# @return [Boolean]
|
27
23
|
# @!attribute [r] uid
|
28
|
-
#
|
29
|
-
|
30
|
-
#
|
31
|
-
set_uid: :int,
|
24
|
+
# @return [Integer|nil] if set, this value will be used for the :uid attribute of each file
|
25
|
+
set_uid: :bool_int,
|
32
26
|
uid: :uint,
|
33
27
|
|
34
|
-
# @!
|
35
|
-
#
|
36
|
-
|
37
|
-
# @return [Integer]
|
38
|
-
# If `set_mode?` is true, the any permissions bits set in `umask` are unset in the st_mode attribute of each
|
39
|
-
# file.
|
40
|
-
#
|
41
|
-
set_mode: :int,
|
28
|
+
# @!attribute [r] umask
|
29
|
+
# @return [Integer|nil] if set, this mask will be applied to the mode attribute of each file
|
30
|
+
set_mode: :bool_int,
|
42
31
|
umask: :uint,
|
43
|
-
|
44
|
-
#
|
45
|
-
# cached.
|
46
|
-
#
|
32
|
+
|
33
|
+
# @!attribute [rw] entry_timeout
|
34
|
+
# The timeout in seconds for which name lookups will be cached.
|
35
|
+
# @return [Float]
|
47
36
|
entry_timeout: :double,
|
37
|
+
|
38
|
+
# @!attribute [rw] negative_timeout
|
39
|
+
# The timeout in seconds for which a negative lookup will be cached.
|
48
40
|
#
|
49
|
-
#
|
50
|
-
#
|
51
|
-
#
|
52
|
-
# timeout, and the file/directory will be assumed to not
|
53
|
-
# exist until then. A value of zero means that negative
|
54
|
-
# lookups are not cached.
|
41
|
+
# This means, that if file did not exist (lookup retuned ENOENT), the lookup will only be redone after the
|
42
|
+
# timeout, and the file/directory will be assumed to not exist until then. A value of zero means that
|
43
|
+
# negative lookups are not cached.
|
55
44
|
#
|
45
|
+
# @return [Float]
|
56
46
|
negative_timeout: :double,
|
57
|
-
|
47
|
+
|
48
|
+
# @!attribute [rw] attr_timeout
|
58
49
|
# The timeout in seconds for which file/directory attributes
|
59
|
-
# (as returned by e.g. the `getattr` handler) are cached.
|
60
50
|
#
|
61
|
-
|
51
|
+
# (as returned by e.g. the `getattr` handler) are cached.
|
62
52
|
#
|
53
|
+
# @return [Float]
|
54
|
+
attr_timeout: :double,
|
55
|
+
|
56
|
+
# @!attribute [rw] intr
|
63
57
|
# Allow requests to be interrupted
|
58
|
+
# @return [Boolean]
|
59
|
+
intr: :bool_int,
|
60
|
+
|
61
|
+
# @!attribute [rw] intr_signal
|
62
|
+
# Which signal number to send to the filesystem when a request is interrupted.
|
64
63
|
#
|
65
|
-
|
66
|
-
#
|
67
|
-
# Specify which signal number to send to the filesystem when
|
68
|
-
# a request is interrupted. The default is hardcoded to
|
69
|
-
# USR1.
|
64
|
+
# The default is hardcoded to USR1.
|
70
65
|
#
|
66
|
+
# @return [Integer]
|
71
67
|
intr_signal: :int,
|
68
|
+
|
69
|
+
# @!attribute [rw] remember
|
70
|
+
# the number of seconds inodes are remembered
|
72
71
|
#
|
73
|
-
# Normally, FUSE assigns inodes to paths only for as long as
|
74
|
-
#
|
75
|
-
#
|
76
|
-
# will require more memory, but may be necessary when using
|
77
|
-
# applications that make use of inode numbers.
|
72
|
+
# Normally, FUSE assigns inodes to paths only for as long as the kernel is aware of them. With this option
|
73
|
+
# inodes are instead remembered for at least this many seconds. This will require more memory, but may be
|
74
|
+
# necessary when using applications that make use of inode numbers.
|
78
75
|
#
|
79
|
-
# A number of -1 means that inodes will be remembered for the
|
80
|
-
# entire life-time of the file-system process.
|
76
|
+
# A number of -1 means that inodes will be remembered for the entire life-time of the file-system process.
|
81
77
|
#
|
78
|
+
# @return [Integer]
|
82
79
|
remember: :int,
|
80
|
+
|
81
|
+
# @!attribute [rw] hard_remove
|
82
|
+
# should open files be removed immediately
|
83
83
|
#
|
84
|
-
# The default behavior is that if an open file is deleted,
|
85
|
-
# the file is
|
86
|
-
#
|
87
|
-
#
|
88
|
-
# with this problem. This option disables the hiding
|
89
|
-
# behavior, and files are removed immediately in an unlink
|
90
|
-
# operation (or in a rename operation which overwrites an
|
91
|
-
# existing file).
|
92
|
-
#
|
93
|
-
# It is recommended that you not use the hard_remove
|
94
|
-
# option. When hard_remove is set, the following libc
|
95
|
-
# functions fail on unlinked files (returning errno of
|
96
|
-
# ENOENT): read(2), write(2), fsync(2), close(2), f*xattr(2),
|
97
|
-
# ftruncate(2), fstat(2), fchmod(2), fchown(2)
|
98
|
-
#
|
99
|
-
hard_remove: :int,
|
84
|
+
# The default behavior is that if an open file is deleted, the file is renamed to a hidden file
|
85
|
+
# (.fuse_hiddenXXX), and only removed when the file is finally released. This relieves the filesystem
|
86
|
+
# implementation of having to deal with this problem. This option disables the hiding behavior, and files are
|
87
|
+
# removed immediately in an unlink operation (or in a rename operation which overwrites an existing file).
|
100
88
|
#
|
101
|
-
#
|
102
|
-
#
|
103
|
-
#
|
104
|
-
# field in the readdir(2) function. The filesystem does not
|
105
|
-
# have to guarantee uniqueness, however some applications
|
106
|
-
# rely on this value being unique for the whole filesystem.
|
89
|
+
# It is recommended that you not use the hard_remove option. When hard_remove is set, the following libc
|
90
|
+
# functions fail on unlinked files (returning errno of ENOENT): read(2), write(2), fsync(2), close(2),
|
91
|
+
# f*xattr(2), ftruncate(2), fstat(2), fchmod(2), fchown(2)
|
107
92
|
#
|
108
|
-
#
|
109
|
-
|
93
|
+
# @return [Boolean]
|
94
|
+
hard_remove: :bool_int,
|
95
|
+
|
96
|
+
# @!attribute [rw] use_ino
|
97
|
+
# use filesystem provided inode values
|
110
98
|
#
|
111
|
-
|
99
|
+
# Honor the st_ino field in the functions getattr() and fill_dir(). This value is used to fill in the st_ino
|
100
|
+
# field in the stat(2), lstat(2), fstat(2) functions and the d_ino field in the readdir(2) function. The
|
101
|
+
# filesystem does not have to guarantee uniqueness, however some applications rely on this value being unique
|
102
|
+
# for the whole filesystem.
|
112
103
|
#
|
113
|
-
#
|
114
|
-
#
|
115
|
-
# looked up, and is still in the cache, the inode number
|
116
|
-
# found there will be used. Otherwise it will be set to -1.
|
117
|
-
# If use_ino option is given, this option is ignored.
|
104
|
+
# Note that this does *not* affect the inode that libfuse and the kernel use internally (also called the
|
105
|
+
# "nodeid").
|
118
106
|
#
|
119
|
-
|
107
|
+
# @return [Boolean]
|
108
|
+
use_ino: :bool_int,
|
109
|
+
|
110
|
+
# @!attribute [rw] readdir_ino
|
111
|
+
# generate inodes for readdir even if {#use_ino} is set
|
112
|
+
#
|
113
|
+
# If use_ino option is not given, still try to fill in the d_ino field in readdir(2). If the name was
|
114
|
+
# previously looked up, and is still in the cache, the inode number found there will be used. Otherwise it
|
115
|
+
# will be set to -1. If use_ino option is given, this option is ignored.
|
116
|
+
# @return [Boolean]
|
117
|
+
readdir_ino: :bool_int,
|
118
|
+
|
119
|
+
# @!attribute [rw] direct_io
|
120
|
+
# disables the use of kernel page cache (file content cache) in the kernel for this filesystem.
|
120
121
|
#
|
121
|
-
# This
|
122
|
-
# in the kernel for this filesystem. This has several affects:
|
122
|
+
# This has several affects:
|
123
123
|
#
|
124
|
-
# 1. Each read(2) or write(2) system call will initiate one
|
125
|
-
# or more read or write operations, data will not be
|
124
|
+
# 1. Each read(2) or write(2) system call will initiate one or more read or write operations, data will not be
|
126
125
|
# cached in the kernel.
|
127
126
|
#
|
128
|
-
# 2. The return value of the read() and write() system calls
|
129
|
-
#
|
130
|
-
#
|
131
|
-
# file size is not known in advance (before reading it).
|
132
|
-
#
|
133
|
-
# Internally, enabling this option causes fuse to set the
|
134
|
-
# `direct_io` field of `struct fuse_file_info` - overwriting
|
135
|
-
# any value that was put there by the file system.
|
136
|
-
#
|
137
|
-
direct_io: :int,
|
138
|
-
#
|
139
|
-
# This option disables flushing the cache of the file
|
140
|
-
# contents on every open(2). This should only be enabled on
|
141
|
-
# filesystem where the file data is never changed
|
142
|
-
# externally (not through the mounted FUSE filesystem). Thus
|
143
|
-
# it is not suitable for network filesystem and other
|
144
|
-
# intermediate filesystem.
|
145
|
-
#
|
146
|
-
# NOTE: if this option is not specified (and neither
|
147
|
-
# direct_io) data is still cached after the open(2), so a
|
148
|
-
# read(2) system call will not always initiate a read
|
149
|
-
# operation.
|
150
|
-
#
|
151
|
-
# Internally, enabling this option causes fuse to set the
|
152
|
-
# `keep_cache` field of `struct fuse_file_info` - overwriting
|
153
|
-
# any value that was put there by the file system.
|
154
|
-
#
|
155
|
-
kernel_cache: :int,
|
127
|
+
# 2. The return value of the read() and write() system calls will correspond to the return values of the read
|
128
|
+
# and write operations. This is useful for example if the file size is not known in advance (before reading
|
129
|
+
# it).
|
156
130
|
#
|
157
|
-
#
|
158
|
-
#
|
159
|
-
#
|
160
|
-
|
131
|
+
# Internally, enabling this option causes fuse to set {FuseFileInfo#direct_io} overwriting any value that was
|
132
|
+
# put there by the file system during :open
|
133
|
+
# @return [Boolean]
|
134
|
+
direct_io: :bool_int,
|
135
|
+
|
136
|
+
# @!attribute [rw] kernel_cache
|
137
|
+
# disables flushing the cache of the file contents on every open(2).
|
161
138
|
#
|
162
|
-
|
139
|
+
# This should only be enabled on filesystem where the file data is never changed externally (not through the
|
140
|
+
# mounted FUSE filesystem). Thus it is not suitable for network filesystem and other intermediate filesystem.
|
163
141
|
#
|
164
|
-
#
|
165
|
-
#
|
166
|
-
# file data on open.
|
142
|
+
# **Note**: if neither this option or {#direct_io} is specified data is still cached after the open(2),
|
143
|
+
# so a read(2) system call will not always initiate a read operation.
|
167
144
|
#
|
168
|
-
|
145
|
+
# Internally, enabling this option causes fuse to set {FuseFileInfo#keep_cache} overwriting any value that was
|
146
|
+
# put there by the file system.
|
147
|
+
# @return [Boolean]
|
148
|
+
kernel_cache: :bool_int,
|
149
|
+
|
150
|
+
# @!attribute [rw] auto_cache
|
151
|
+
# invalidate cached data on open based on changes in file attributes
|
152
|
+
#
|
153
|
+
# This option is an alternative to `kernel_cache`. Instead of unconditionally keeping cached data, the cached
|
154
|
+
# data is invalidated on open(2) if if the modification time or the size of the file has changed since it was
|
155
|
+
# last opened.
|
156
|
+
# @return [Boolean]
|
157
|
+
auto_cache: :bool_int,
|
158
|
+
|
159
|
+
# @!attribute [rw] ac_attr_timeout
|
160
|
+
# if set the timeout in seconds for which file attributes are cached for the purpose of checking if
|
161
|
+
# auto_cache should flush the file data on open.
|
162
|
+
# @return [Float|nil]
|
163
|
+
ac_attr_timeout_set: :bool_int,
|
169
164
|
ac_attr_timeout: :double,
|
165
|
+
|
166
|
+
# @!attribute [rw] nullpath_ok
|
167
|
+
# operations on open files and directories are ok to receive nil paths
|
170
168
|
#
|
171
|
-
# If this option is given the file-system handlers for the
|
172
|
-
#
|
173
|
-
# read, write, flush, release, fsync, readdir, releasedir,
|
174
|
-
# fsyncdir, lock, ioctl and poll.
|
175
|
-
#
|
176
|
-
# For the truncate, getattr, chmod, chown and utimens
|
177
|
-
# operations the path will be provided only if the struct
|
178
|
-
# fuse_file_info argument is NULL.
|
179
|
-
#
|
180
|
-
nullpath_ok: :int,
|
181
|
-
#
|
182
|
-
# The remaining options are used by libfuse internally and
|
183
|
-
# should not be touched.
|
169
|
+
# If this option is given the file-system handlers for the following operations will not receive path
|
170
|
+
# information: read, write, flush, release, fsync, readdir, releasedir, fsyncdir, lock, ioctl and poll.
|
184
171
|
#
|
185
|
-
|
172
|
+
# For the truncate, getattr, chmod, chown and utimens operations the path will be provided only if the
|
173
|
+
# {FuseFileInfo} argument is nil.
|
174
|
+
# @return [Boolean]
|
175
|
+
nullpath_ok: :bool_int,
|
176
|
+
|
177
|
+
# The remaining options are used by libfuse internally and should not be touched.
|
178
|
+
show_help: :bool_int,
|
186
179
|
modules: :pointer,
|
187
|
-
debug: :
|
180
|
+
debug: :bool_int
|
188
181
|
}
|
189
182
|
)
|
190
183
|
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
184
|
+
setters = { gid: :set_gid, uid: :set_uid, umask: :set_mode, ac_attr_timeout: :ac_attr_timeout_set }
|
185
|
+
setters.each do |(attr, setter)|
|
186
|
+
ffi_attr_reader(attr)
|
187
|
+
ffi_attr_writer(attr) do |val|
|
188
|
+
self[setter] = !val.nil?
|
189
|
+
val || 0
|
190
|
+
end
|
191
|
+
end
|
199
192
|
|
200
|
-
|
201
|
-
gid].freeze
|
202
|
-
ffi_attr_accessor(*OTHER_ATTRS)
|
193
|
+
ffi_attr_accessor(*(members - (setters.keys + setters.values)))
|
203
194
|
end
|
204
195
|
end
|
205
196
|
end
|