ffi-libfuse 0.0.1.rctest12 → 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 +3 -3
- 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/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 +26 -10
- 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 +77 -4
- data/lib/ffi/libfuse/adapter/thread_local_context.rb +0 -36
@@ -2,62 +2,60 @@
|
|
2
2
|
|
3
3
|
require_relative 'fuse_version'
|
4
4
|
require_relative '../accessors'
|
5
|
+
require_relative '../boolean_int'
|
5
6
|
|
6
7
|
module FFI
|
7
8
|
# Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
|
8
9
|
module Libfuse
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
]
|
54
|
-
end
|
10
|
+
capabilities =
|
11
|
+
if FUSE_MAJOR_VERSION >= 3
|
12
|
+
%i[
|
13
|
+
async_read
|
14
|
+
posix_locks
|
15
|
+
atomic_o_trunc
|
16
|
+
export_support
|
17
|
+
dont_mask
|
18
|
+
splice_write
|
19
|
+
splice_move
|
20
|
+
splice_read
|
21
|
+
flock_locks
|
22
|
+
ioctl_dir
|
23
|
+
auto_inval_data
|
24
|
+
readdirplus
|
25
|
+
readdirplus_auto
|
26
|
+
async_dio
|
27
|
+
writeback_cache
|
28
|
+
no_open_support
|
29
|
+
parallel_dirops
|
30
|
+
posix_acl
|
31
|
+
handle_killpriv
|
32
|
+
cache_symlinks
|
33
|
+
no_opendir_support
|
34
|
+
explicit_inval_data
|
35
|
+
]
|
36
|
+
else
|
37
|
+
%i[
|
38
|
+
async_readcap
|
39
|
+
posix_locks
|
40
|
+
atomic_o_trunc
|
41
|
+
export_support
|
42
|
+
big_writes
|
43
|
+
dont_mask
|
44
|
+
splice_write
|
45
|
+
splice_move
|
46
|
+
splice_read
|
47
|
+
flock_locks
|
48
|
+
ioctl_dir
|
49
|
+
]
|
50
|
+
end
|
51
|
+
|
52
|
+
bitmask :fuse_cap, capabilities
|
53
|
+
|
55
54
|
#
|
56
55
|
# Connection information
|
57
56
|
#
|
58
|
-
# Some of the elements are read-write, these can be changed to
|
59
|
-
#
|
60
|
-
# value must usually be smaller than the indicated value.
|
57
|
+
# Some of the elements are read-write, these can be changed to indicate the value requested by the filesystem. The
|
58
|
+
# requested value must usually be smaller than the indicated value.
|
61
59
|
#
|
62
60
|
# @see FuseOperations#init
|
63
61
|
class FuseConnInfo < FFI::Struct
|
@@ -69,81 +67,18 @@ module FFI
|
|
69
67
|
max_write: :uint,
|
70
68
|
max_read: :uint,
|
71
69
|
max_readahead: :uint,
|
72
|
-
#
|
73
|
-
# Capability flags that the kernel supports (read-only)
|
74
|
-
#
|
75
70
|
capable: :fuse_cap,
|
76
|
-
#
|
77
|
-
# Capability flags that the filesystem wants to enable.
|
78
|
-
#
|
79
|
-
# libfuse attempts to initialize this field with
|
80
|
-
# reasonable default values before calling the init() handler.
|
81
|
-
#
|
82
71
|
want: :fuse_cap,
|
83
|
-
#
|
84
|
-
# Maximum number of pending "background" requests. A
|
85
|
-
# background request is any type of request for which the
|
86
|
-
# total number is not limited by other means. As of kernel
|
87
|
-
# 4.8, only two types of requests fall into this category:
|
88
|
-
#
|
89
|
-
# 1. Read-ahead requests
|
90
|
-
# 2. Asynchronous direct I/O requests
|
91
|
-
#
|
92
|
-
# Read-ahead requests are generated (if max_readahead is
|
93
|
-
# non-zero) by the kernel to preemptively fill its caches
|
94
|
-
# when it anticipates that userspace will soon read more
|
95
|
-
# data.
|
96
|
-
#
|
97
|
-
# Asynchronous direct I/O requests are generated if
|
98
|
-
# FUSE_CAP_ASYNC_DIO is enabled and userspace submits a large
|
99
|
-
# direct I/O request. In this case the kernel will internally
|
100
|
-
# split it up into multiple smaller requests and submit them
|
101
|
-
# to the filesystem concurrently.
|
102
|
-
#
|
103
|
-
# Note that the following requests are *not* background
|
104
|
-
# requests: writeback requests (limited by the kernel's
|
105
|
-
# flusher algorithm), regular (i.e., synchronous and
|
106
|
-
# buffered) userspace read/write requests (limited to one per
|
107
|
-
# thread), asynchronous read requests (Linux's io_submit(2)
|
108
|
-
# call actually blocks, so these are also limited to one per
|
109
|
-
# thread).
|
110
|
-
#
|
111
72
|
max_background: :uint,
|
112
|
-
#
|
113
|
-
# Kernel congestion threshold parameter. If the number of pending
|
114
|
-
# background requests exceeds this number, the FUSE kernel module will
|
115
|
-
# mark the filesystem as "congested". This instructs the kernel to
|
116
|
-
# expect that queued requests will take some time to complete, and to
|
117
|
-
# adjust its algorithms accordingly (e.g. by putting a waiting thread
|
118
|
-
# to sleep instead of using a busy-loop).
|
119
|
-
#
|
120
73
|
congestion_threshold: :uint,
|
121
|
-
#
|
122
|
-
# When FUSE_CAP_WRITEBACK_CACHE is enabled, the kernel is responsible
|
123
|
-
# for updating mtime and ctime when write requests are received. The
|
124
|
-
# updated values are passed to the filesystem with setattr() requests.
|
125
|
-
# However, if the filesystem does not support the full resolution of
|
126
|
-
# the kernel timestamps (nanoseconds), the mtime and ctime values used
|
127
|
-
# by kernel and filesystem will differ (and result in an apparent
|
128
|
-
# change of times after a cache flush).
|
129
|
-
#
|
130
|
-
# To prevent this problem, this variable can be used to inform the
|
131
|
-
# kernel about the timestamp granularity supported by the file-system.
|
132
|
-
# The value should be power of 10. The default is 1, i.e. full
|
133
|
-
# nano-second resolution. Filesystems supporting only second resolution
|
134
|
-
# should set this to 1000000000.
|
135
|
-
#
|
136
74
|
time_gran: :uint,
|
137
|
-
#
|
138
|
-
# For future use.
|
139
|
-
#
|
140
|
-
reserved: [:uint, 22]
|
75
|
+
reserved: [:uint, 22] # for future use
|
141
76
|
}
|
142
77
|
else
|
143
78
|
{
|
144
79
|
proto_major: :uint,
|
145
80
|
proto_minor: :uint,
|
146
|
-
async_read: :
|
81
|
+
async_read: :bool_int, # long deprecated
|
147
82
|
max_write: :uint,
|
148
83
|
max_readahead: :uint,
|
149
84
|
capable: :fuse_cap,
|
@@ -159,25 +94,23 @@ module FFI
|
|
159
94
|
layout fuse_layout
|
160
95
|
|
161
96
|
# @!attribute [r] proto_major
|
162
|
-
#
|
97
|
+
# @return [Integer] Major version of the protocol (read-only)
|
163
98
|
|
164
99
|
# @!attribute [r] proto_minor
|
165
|
-
#
|
100
|
+
# @return [Integer] Minor version of the protocol (read-only)
|
166
101
|
|
167
102
|
ffi_attr_reader :proto_major, :proto_minor
|
168
103
|
|
169
|
-
# Is asynchronous read supported (read-write)
|
170
|
-
ffi_attr_accessor :async_read if FUSE_MAJOR_VERSION < 3
|
171
|
-
|
172
104
|
# @!attribute [rw] max_read
|
173
|
-
#
|
105
|
+
# @return [Integer] Maximum size of read requests.
|
174
106
|
#
|
175
|
-
#
|
176
|
-
#
|
107
|
+
# A value of zero indicates no limit. However, even if the filesystem does not specify a limit, the maximum size
|
108
|
+
# of read requests will still be limited by the kernel.
|
177
109
|
#
|
178
|
-
#
|
179
|
-
#
|
180
|
-
#
|
110
|
+
# @note For the time being, the maximum size of read requests must be set both here *and* passed to
|
111
|
+
# using the ``-o max_read=<n>`` mount option. At some point in the future, specifying the mount
|
112
|
+
# option will no longer be necessary.
|
113
|
+
# @since Fuse3
|
181
114
|
ffi_attr_accessor :max_read if FUSE_MAJOR_VERSION >= 3
|
182
115
|
|
183
116
|
# @!attribute [rw] max_write
|
@@ -188,23 +121,266 @@ module FFI
|
|
188
121
|
|
189
122
|
ffi_attr_accessor :max_write, :max_readahead
|
190
123
|
|
191
|
-
#
|
124
|
+
# @!attribute [r] capable
|
125
|
+
# Capability flags supported by kernel fuse module
|
126
|
+
#
|
127
|
+
# * `:async_read` Indicates that the filesystem supports asynchronous read requests.
|
128
|
+
#
|
129
|
+
# If this capability is not requested/available, the kernel will ensure that there is at most one pending read
|
130
|
+
# request per file-handle at any time, and will attempt to order read requests by increasing offset.
|
131
|
+
#
|
132
|
+
# This feature is enabled by default when supported by the kernel.
|
133
|
+
#
|
134
|
+
# * `:posix_locks` Indicates that the filesystem supports "remote" locking.
|
135
|
+
#
|
136
|
+
# This feature is enabled by default when supported by the kernel,
|
137
|
+
# and if getlk() and setlk() handlers are implemented.
|
138
|
+
#
|
139
|
+
# * `:atomic_o_trunc` Indicates that the filesystem supports the O_TRUNC open flag.
|
140
|
+
#
|
141
|
+
# If disabled, and an application specifies O_TRUNC, fuse first calls truncate() and then open() with O_TRUNC
|
142
|
+
# filtered out.
|
143
|
+
#
|
144
|
+
# This feature is enabled by default when supported by the kernel.
|
145
|
+
#
|
146
|
+
# * `:export_support` Indicates that the filesystem supports lookups of "." and "..".
|
147
|
+
#
|
148
|
+
# This feature is disabled by default.
|
149
|
+
#
|
150
|
+
# * `:big_writes` Indicates the filesystem can handle write size larger than 4kB.
|
151
|
+
#
|
152
|
+
# Removed in Fuse3 where is now always active. Filesystems that want to limit the size of write requests should
|
153
|
+
# use the {#max_write} option instead.
|
154
|
+
#
|
155
|
+
# * `:dont_mask` Indicates that the kernel should not apply the umask to the file mode on create operations.
|
156
|
+
#
|
157
|
+
# This feature is disabled by default.
|
158
|
+
#
|
159
|
+
# * `:splice_write` Indicates that libfuse should try to use splice() when writing to the fuse device.
|
160
|
+
#
|
161
|
+
# This may improve performance. This feature is disabled by default.
|
162
|
+
#
|
163
|
+
# * `:splice_move` Indicates that libfuse should try to move pages instead of copying when writing to / reading
|
164
|
+
# from the fuse device.
|
165
|
+
#
|
166
|
+
# This may improve performance. This feature is disabled by default.
|
167
|
+
#
|
168
|
+
# * `:splice_read` Indicates that libfuse should try to use splice() when reading from the fuse device.
|
169
|
+
#
|
170
|
+
# This may improve performance. This feature is enabled by default when supported by the kernel and
|
171
|
+
# if the filesystem implements a write_buf() handler.
|
172
|
+
#
|
173
|
+
# * `:flock_locks` If set, the calls to flock(2) will be emulated using POSIX locks and must then be handled by
|
174
|
+
# the filesystem's :flock handler.
|
175
|
+
#
|
176
|
+
# If not set, flock(2) calls will be handled by the FUSE kernel module internally (so any access that does not go
|
177
|
+
# through the kernel cannot be taken into account).
|
178
|
+
#
|
179
|
+
# This feature is enabled by default when supported by the kernel and if the filesystem implements a flock()
|
180
|
+
# handler.
|
181
|
+
#
|
182
|
+
# * `:ioctl_dir` Indicates that the filesystem supports ioctl's on directories.
|
183
|
+
#
|
184
|
+
# This feature is enabled by default when supported by the kernel.
|
185
|
+
#
|
186
|
+
# * :`auto_inval_data`
|
187
|
+
#
|
188
|
+
# Traditionally, while a file is open the FUSE kernel module only asks the filesystem for an update of the file's
|
189
|
+
# attributes when a client attempts to read beyond EOF. This is unsuitable for e.g. network filesystems, where
|
190
|
+
# the file contents may change without the kernel knowing about it.
|
191
|
+
#
|
192
|
+
# If this flag is set, FUSE will check the validity of the attributes on every read. If the attributes are no
|
193
|
+
# longer valid (i.e., if the *attr_timeout* passed to fuse_reply_attr() or set in `struct fuse_entry_param` has
|
194
|
+
# passed), it will first issue a `getattr` request. If the new mtime differs from the previous value, any cached
|
195
|
+
# file *contents* will be invalidated as well.
|
196
|
+
#
|
197
|
+
# This flag should always be set when available. If all file changes go through the kernel, *attr_timeout* should
|
198
|
+
# be set to a very large number to avoid unnecessary getattr() calls.
|
199
|
+
#
|
200
|
+
# This feature is enabled by default when supported by the kernel.
|
201
|
+
#
|
202
|
+
# * `:readdirplus` Indicates that the filesystem supports readdirplus.
|
203
|
+
#
|
204
|
+
# This feature is enabled by default when supported by the kernel and if the filesystem implements the
|
205
|
+
# readdirplus() handler
|
206
|
+
#
|
207
|
+
# * `:readdirplus_auto` Indicates that the filesystem supports adaptive readdirplus.
|
208
|
+
#
|
209
|
+
# If :readdirplus is not set, this flag has no effect.
|
210
|
+
#
|
211
|
+
# If :readdirplus is set and this flag is not set, the kernel will always issue readdirplus() requests to
|
212
|
+
# retrieve directory contents.
|
213
|
+
#
|
214
|
+
# If :readdirplus is set and this flag is set, the kernel will issue both readdir() and readdirplus() requests,
|
215
|
+
# depending on how much information is expected to be required.
|
216
|
+
#
|
217
|
+
# As of Linux 4.20, the algorithm is as follows: when userspace starts to read directory entries, issue a
|
218
|
+
# :reaadirplus request to the filesystem. If any entry attributes have been looked up by the time userspace
|
219
|
+
# requests the next batch of entries continue with :reaadirplus, otherwise switch to plain :readdir. This will
|
220
|
+
# result in eg plain "ls" triggering :reaadirplus first then :readdir after that because it doesn't do lookups.
|
221
|
+
# "ls -l" should result in all :reaadirplus, except if dentries are already cached.
|
222
|
+
#
|
223
|
+
# This feature is enabled by default when supported by the kernel and if the filesystem implements both a
|
224
|
+
# readdirplus() and a readdir() handler.
|
225
|
+
#
|
226
|
+
# **Note** The high-level operations mix :readdir and :readdirplus into one operation
|
227
|
+
# with flags to indicate behaviour. As such for the purposes of above :readdirplus is always implemented!
|
228
|
+
#
|
229
|
+
# * `:async_dio` Indicates that the filesystem supports asynchronous direct I/O submission.
|
230
|
+
#
|
231
|
+
# If this capability is not requested/available, the kernel will ensure that there is at most one pending read
|
232
|
+
# and one pending write request per direct I/O file-handle at any time.
|
233
|
+
#
|
234
|
+
# This feature is enabled by default when supported by the kernel.
|
235
|
+
#
|
236
|
+
# * `:writeback_cache` Indicates that writeback caching should be enabled.
|
237
|
+
#
|
238
|
+
# This means that individual write request may be buffered and merged in the kernel before they are send to the
|
239
|
+
# filesystem.
|
240
|
+
#
|
241
|
+
# This feature is disabled by default.
|
242
|
+
#
|
243
|
+
# * `:no_open_support` Indicates support for zero-message opens.
|
244
|
+
#
|
245
|
+
# If this flag is set in the `capable` field of the `fuse_conn_info` structure, then the filesystem may return
|
246
|
+
# `ENOSYS` from the open() handler to indicate success. Further attempts to open files will be handled in the
|
247
|
+
# kernel. (If this flag is not set, returning ENOSYS will be treated as an error and signaled to the caller).
|
248
|
+
#
|
249
|
+
# Setting (or unsetting) this flag in the `want` field has *no effect*.
|
250
|
+
#
|
251
|
+
# * `:parallel_dirops` Indicates support for parallel directory operations.
|
252
|
+
#
|
253
|
+
# If this flag is unset, the FUSE kernel module will ensure that lookup() and readdir() requests are never issued
|
254
|
+
# concurrently for the same directory.
|
255
|
+
#
|
256
|
+
# This feature is enabled by default when supported by the kernel.
|
257
|
+
#
|
258
|
+
# * `:posix_acl` Indicates support for POSIX ACLs.
|
259
|
+
#
|
260
|
+
# If this feature is enabled, the kernel will cache and have responsibility for enforcing ACLs. ACL will be
|
261
|
+
# stored as xattrs and passed to userspace, which is responsible for updating the ACLs in the filesystem, keeping
|
262
|
+
# the file mode in sync with the ACL, and ensuring inheritance of default ACLs when new filesystem nodes are
|
263
|
+
# created. Note that this requires that the file system is able to parse and interpret the xattr representation
|
264
|
+
# of ACLs.
|
265
|
+
#
|
266
|
+
# Enabling this feature implicitly turns on the ``default_permissions`` mount option (even if it was not passed
|
267
|
+
# to mount(2)).
|
268
|
+
#
|
269
|
+
# This feature is disabled by default.
|
270
|
+
#
|
271
|
+
# * `:handle_killpriv` Indicates that the filesystem is responsible for unsetting setuid and setgid bits when a
|
272
|
+
# file is written, truncated, or its owner is changed.
|
273
|
+
#
|
274
|
+
# This feature is enabled by default when supported by the kernel.
|
275
|
+
#
|
276
|
+
# * `:cache_symlinks` Indicates that the kernel supports caching symlinks in its page cache.
|
277
|
+
#
|
278
|
+
# When this feature is enabled, symlink targets are saved in the page cache. You can invalidate a cached link by
|
279
|
+
# calling: `fuse_lowlevel_notify_inval_inode(se, ino, 0, 0);`
|
280
|
+
#
|
281
|
+
# This feature is disabled by default.
|
282
|
+
#
|
283
|
+
# * `:no_opendir_support` Indicates support for zero-message opendirs.
|
284
|
+
#
|
285
|
+
# If this flag is set then the filesystem may return `ENOSYS` from the opendir() handler to indicate success.
|
286
|
+
# Further opendir and releasedir messages will be handled in the kernel. (If this flag is not set, returning
|
287
|
+
# ENOSYS will be treated as an error and signalled to the caller.)
|
288
|
+
#
|
289
|
+
# Setting (or unsetting) this flag in the `want` field has *no effect*.
|
290
|
+
#
|
291
|
+
# * `:explicit_inval_data` Indicates support for invalidating cached pages only on explicit request.
|
292
|
+
#
|
293
|
+
# If this flag is set in the `capable` field of the `fuse_conn_info` structure, then the FUSE kernel module
|
294
|
+
# supports invalidating cached pages only on explicit request by the filesystem through
|
295
|
+
# fuse_lowlevel_notify_inval_inode() or fuse_invalidate_path().
|
296
|
+
#
|
297
|
+
# By setting this flag in the `want` field of the `fuse_conn_info` structure, the filesystem is responsible for
|
298
|
+
# invalidating cached pages through explicit requests to the kernel.
|
299
|
+
#
|
300
|
+
# Note that setting this flag does not prevent the cached pages from being flushed by OS itself and/or through
|
301
|
+
# user actions.
|
302
|
+
#
|
303
|
+
# Note that if both :explicit_inval_data and :auto_inval_data are set then :auto_inval_data takes precedence.
|
304
|
+
#
|
305
|
+
# This feature is disabled by default.
|
306
|
+
# @return [Array<Symbol>]
|
192
307
|
ffi_attr_reader :capable
|
193
308
|
|
194
|
-
#
|
195
|
-
|
196
|
-
|
309
|
+
# @param [Array<Symbol>] capabilities
|
310
|
+
# @return [Boolean] true if {#capable} of all capabilities
|
311
|
+
def capable?(*capabilities)
|
312
|
+
capabilities.all? { |c| self[:capable].include?(c) }
|
313
|
+
end
|
314
|
+
|
315
|
+
# @attribute [rw] want
|
316
|
+
# @overload want()
|
317
|
+
# Capability flags that the filesystem wants to enable.
|
318
|
+
#
|
319
|
+
# libfuse attempts to initialize this field with reasonable default values before calling the :init handler.
|
320
|
+
#
|
321
|
+
# @overload want(*capabiities)
|
322
|
+
# Add to the capabilities wanted by the filesystem
|
323
|
+
# @param [Array<Symbol>] capabilities list to add
|
324
|
+
# @overload want(**capabilities)
|
325
|
+
# @param [Hash<Symbol,Boolean>] capabilities map of capability names to whether they are explicitly wanted
|
326
|
+
# or unwanted
|
327
|
+
# @return [Array<Symbol>]
|
328
|
+
# @see capable
|
329
|
+
ffi_attr_reader(:want, simple: false) do |*caps, **h|
|
330
|
+
next self[:want] if caps.empty? && h.empty?
|
331
|
+
|
332
|
+
h.merge!(caps.pop) if caps.last.is_a?(Hash)
|
333
|
+
add, del = h.keys.partition { |c| h[c] }
|
334
|
+
self[:want] = (self[:want] - del + add + caps)
|
197
335
|
end
|
198
336
|
|
199
|
-
#
|
200
|
-
|
337
|
+
# @param [Array<Symbol>] capabilities
|
338
|
+
# @return [Boolean] true if all capabilities are wanted
|
339
|
+
def wanted?(*capabilities)
|
340
|
+
capabilities.all? { |c| self[:want].include?(c) }
|
341
|
+
end
|
201
342
|
|
202
|
-
#
|
343
|
+
# @!attribute [rw] max_background
|
344
|
+
# @return [Integer] Maximum number of pending "background" requests.
|
345
|
+
#
|
346
|
+
# A background request is any type of request for which the total number is not limited by other means. As of
|
347
|
+
# kernel 4.8, only two types of requests fall into this category:
|
348
|
+
#
|
349
|
+
# 1. Read-ahead requests
|
350
|
+
# 2. Asynchronous direct I/O requests
|
351
|
+
#
|
352
|
+
# Read-ahead requests are generated (if max_readahead is non-zero) by the kernel to preemptively fill its
|
353
|
+
# caches when it anticipates that userspace will soon read more data.
|
354
|
+
#
|
355
|
+
# Asynchronous direct I/O requests are generated if :async_dio is enabled and userspace submits a large
|
356
|
+
# direct I/O request. In this case the kernel will internally split it up into multiple smaller requests and
|
357
|
+
# submit them to the filesystem concurrently.
|
358
|
+
#
|
359
|
+
# Note that the following requests are *not* background requests: writeback requests (limited by the kernel's
|
360
|
+
# flusher algorithm), regular (i.e., synchronous and buffered) userspace read/write requests (limited to one per
|
361
|
+
# thread), asynchronous read requests (Linux's io_submit(2) call actually blocks, so these are also limited to one
|
362
|
+
# per thread).
|
203
363
|
ffi_attr_accessor :max_background
|
204
364
|
|
205
|
-
#
|
206
|
-
|
365
|
+
# @!attribute [rw] congestion_threshold
|
366
|
+
# @return [Integer] Kernel congestion threshold parameter
|
367
|
+
#
|
368
|
+
# f the number of pending background requests exceeds this number, the FUSE kernel module will mark the filesystem
|
369
|
+
# as "congested". This instructs the kernel to expect that queued requests will take some time to complete, and to
|
370
|
+
# adjust its algorithms accordingly (e.g. by putting a waiting thread to sleep instead of using a busy-loop).
|
371
|
+
ffi_attr_accessor :congestion_threshold
|
207
372
|
|
373
|
+
# @!attribute [rw] time_gran
|
374
|
+
# @return [Integer] timestamp granularity supported by the file-system
|
375
|
+
#
|
376
|
+
# When :writeback_cache is enabled, the kernel is responsible for updating mtime and ctime when write requests are
|
377
|
+
# received. The updated values are passed to the filesystem with setattr() requests. However, if the filesystem
|
378
|
+
# does not support the full resolution of the kernel timestamps (nanoseconds), the mtime and ctime values used by
|
379
|
+
# kernel and filesystem will differ (and result in an apparent change of times after a cache flush).
|
380
|
+
#
|
381
|
+
# To prevent this problem, this variable can be used to inform the kernel about the timestamp granularity
|
382
|
+
# supported by the file-system. The value should be power of 10. The default is 1, i.e. full nano-second
|
383
|
+
# resolution. Filesystems supporting only second resolution should set this to 1000000000.
|
208
384
|
ffi_attr_accessor :time_gran if FUSE_MAJOR_VERSION >= 3
|
209
385
|
end
|
210
386
|
end
|
@@ -15,9 +15,20 @@ module FFI
|
|
15
15
|
base[:umask] = :mode_t if FUSE_VERSION >= 28
|
16
16
|
layout base
|
17
17
|
|
18
|
-
ffi_attr_reader(
|
18
|
+
ffi_attr_reader(*members, simple: false) do
|
19
|
+
m = __method__
|
19
20
|
|
20
|
-
|
21
|
+
# Use overrides if they are available, or the default context if the underlying memory is invalid
|
22
|
+
FuseContext.overrides[m] || (null? ? DEFAULT_CONTEXT[m] : self[m])
|
23
|
+
end
|
24
|
+
|
25
|
+
if FUSE_VERSION < 28
|
26
|
+
attr_writer :umask
|
27
|
+
|
28
|
+
def umask
|
29
|
+
@umask ||= File.umask
|
30
|
+
end
|
31
|
+
end
|
21
32
|
|
22
33
|
# @!attribute [r] uid
|
23
34
|
# @return [Integer] user id of the calling process
|
@@ -32,7 +43,9 @@ module FFI
|
|
32
43
|
# @return [Object] private filesystem data
|
33
44
|
# @see FuseOperations#init
|
34
45
|
|
35
|
-
# @!attribute [
|
46
|
+
# @!attribute [rw] umask
|
47
|
+
#
|
48
|
+
# Writable only for Fuse version < 28
|
36
49
|
# @return [Integer] umask of the calling process
|
37
50
|
|
38
51
|
# @return [Boolean]
|
@@ -48,8 +61,37 @@ module FFI
|
|
48
61
|
Libfuse.raise_interrupt
|
49
62
|
end
|
50
63
|
|
64
|
+
# @param [Integer] perms
|
65
|
+
# @return perms adjusted by {#umask}
|
66
|
+
def mask(perms)
|
67
|
+
perms & ~umask
|
68
|
+
end
|
69
|
+
|
70
|
+
DEFAULT_CONTEXT = { uid: Process.uid, gid: Process.gid, umask: File.umask }.freeze
|
71
|
+
|
51
72
|
class << self
|
73
|
+
# @overload overrides(hash)
|
74
|
+
# @param[Hash<Symbol,Object|nil] hash a list of override values that will apply to this context
|
75
|
+
#
|
76
|
+
# If not set uid, gid, umask will be overridden from the current process, which is useful if
|
77
|
+
# {FuseContext} is referenced from outside of a fuse callback
|
78
|
+
# @yield [] executes block with the given hash overriding FuseContext values
|
79
|
+
# @return [Object] the result of the block
|
80
|
+
# @overload overrides()
|
81
|
+
# @return [Hash] current thread local overrides for FuseContext
|
82
|
+
def overrides(hash = nil)
|
83
|
+
return Thread.current[:fuse_context_overrides] ||= {} unless block_given?
|
84
|
+
|
85
|
+
begin
|
86
|
+
Thread.current[:fuse_context_overrides] = hash || DEFAULT_CONTEXT
|
87
|
+
yield
|
88
|
+
ensure
|
89
|
+
Thread.current[:fuse_context_overrides] = nil
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
52
93
|
# @return [FuseContext] the context for the current filesystem operation
|
94
|
+
# @note if called outside a fuse callback the native {FuseContext} will have invalid values. See {overrides}
|
53
95
|
def fuse_get_context
|
54
96
|
Libfuse.fuse_get_context
|
55
97
|
end
|