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