ffi-libfuse 0.0.1.rctest12 → 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 +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
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d71e73d4261d20d3e8318fa01517342da232c0167f4febd73249fb99bb314e15
|
4
|
+
data.tar.gz: 5d478d73897b3d590b1c23ddc656f416574865a53db88bb078ddc949c310bc81
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bfc6ff5b7a9e706be919eaf35fbdfe7b3c2575c68e03008f2381c723ab6896f9826047427e78e8915b90985c0ce26e04e83e639817dd5b7f40bbe1adc69e8aa8
|
7
|
+
data.tar.gz: ac2c8aa63ee627f73cd2d8a06071273bbbc8af64f9ae21862ff6f9bc235c7a0aa031c4fe601aea2b7e3ad4f93ef8ffd248fba35fbcf7cbabf422c37727995f72
|
data/.yardopts
CHANGED
data/CHANGES.md
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
0.1.0 / 2022-04
|
2
|
+
------------------
|
3
|
+
|
4
|
+
#### BREAKING changes
|
5
|
+
* Changed option parsing.
|
6
|
+
|
7
|
+
{FFI::Libfuse::Main#fuse_options} now takes a FuseArgs parameter and fuse_opt_proc is not used
|
8
|
+
|
9
|
+
#### New Features
|
10
|
+
* Implemented helper filesystems in {FFI::Libfuse::Filesystem}
|
11
|
+
|
12
|
+
#### Fixes
|
13
|
+
* Test on OSX with macFuse
|
14
|
+
* Lots
|
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2021 Grant Gardner
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
CHANGED
@@ -2,61 +2,160 @@
|
|
2
2
|
|
3
3
|
Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
|
4
4
|
|
5
|
-
##
|
5
|
+
## Requirements
|
6
6
|
|
7
|
-
|
7
|
+
* Ruby 2.7
|
8
|
+
* Linux: libfuse (Fuse2) or libfuse3 (Fuse3)
|
9
|
+
* MacOS: macFuse (https://osxfuse.github.io/)
|
8
10
|
|
9
|
-
|
11
|
+
## Building a FUSE Filesystem
|
12
|
+
|
13
|
+
Install the gem
|
14
|
+
|
15
|
+
```bash
|
16
|
+
gem install ffi-libfuse
|
17
|
+
```
|
18
|
+
|
19
|
+
Create a filesystem class
|
20
|
+
|
21
|
+
* implement FUSE callbacks for filesystem operations satisfying {FFI::Libfuse::FuseOperations}
|
22
|
+
* recommend including {FFI::Libfuse::Adapter::Ruby} to add some ruby sugar and safety to the native FUSE Callbacks
|
23
|
+
* recommend including {FFI::Libfuse::Adapter::Fuse2Compat} for compatibility with Fuse2/macFuse
|
24
|
+
* implement {FFI::Libfuse::Main} configuration methods, eg to parse custom options with {FFI::Libfuse::FuseArgs#parse!}
|
25
|
+
(as altered by any included adapters from {FFI::Libfuse::Adapter})
|
26
|
+
* Provide an entrypoint to start the filesystem using {FFI::Libfuse::Main.fuse_main}
|
27
|
+
|
28
|
+
{FFI::Libfuse::Filesystem} contains additional classes and modules to help build and compose filesystems
|
29
|
+
|
30
|
+
<!-- SAMPLE BEGIN: sample/hello_fs.rb -->
|
31
|
+
*sample/hello_fs.rb*
|
10
32
|
|
11
33
|
```ruby
|
34
|
+
#!/usr/bin/env ruby
|
35
|
+
# frozen_string_literal: true
|
36
|
+
|
12
37
|
require 'ffi/libfuse'
|
13
38
|
|
14
|
-
|
15
|
-
|
39
|
+
# Hello World!
|
40
|
+
class HelloFS
|
16
41
|
include FFI::Libfuse::Adapter::Ruby
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
42
|
+
include FFI::Libfuse::Adapter::Fuse2Compat
|
43
|
+
|
44
|
+
# FUSE Configuration methods
|
45
|
+
|
46
|
+
def fuse_options(args)
|
47
|
+
args.parse!({ 'subject=' => :subject }) do |key:, value:, **|
|
48
|
+
raise FFI::Libfuse::Error, 'subject option must be at least 2 characters' unless value.size >= 2
|
49
|
+
|
50
|
+
@subject = value if key == :subject
|
51
|
+
:handled
|
52
|
+
end
|
21
53
|
end
|
22
|
-
|
23
|
-
def
|
24
|
-
|
54
|
+
|
55
|
+
def fuse_help
|
56
|
+
'-o subject=<subject> a target to say hello to'
|
57
|
+
end
|
58
|
+
|
59
|
+
def fuse_configure
|
60
|
+
@subject ||= 'World!'
|
61
|
+
@content = "Hello #{@subject}\n"
|
62
|
+
end
|
63
|
+
|
64
|
+
# FUSE callbacks
|
65
|
+
|
66
|
+
def getattr(path, stat, *_args)
|
67
|
+
case path
|
68
|
+
when '/'
|
69
|
+
stat.directory(mode: 0o550)
|
70
|
+
when '/hello.txt'
|
71
|
+
stat.file(mode: 0o440, size: @content.size)
|
72
|
+
else
|
73
|
+
raise Errno::ENOENT
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def readdir(_path, *_args)
|
78
|
+
yield 'hello.txt'
|
79
|
+
end
|
80
|
+
|
81
|
+
def read(_path, *_args)
|
82
|
+
@content
|
25
83
|
end
|
26
|
-
|
27
84
|
end
|
28
85
|
|
29
|
-
|
86
|
+
# Start the file system
|
87
|
+
FFI::Libfuse.fuse_main(operations: HelloFS.new) if __FILE__ == $0
|
88
|
+
|
30
89
|
```
|
90
|
+
<!-- SAMPLE END: sample/hello_fs.rb -->
|
31
91
|
|
32
|
-
|
92
|
+
Mount the filesystem
|
93
|
+
|
94
|
+
```bash
|
95
|
+
hello_fs.rb -h # show help
|
96
|
+
hello_fs.rb /mnt/hello # run deamonized, mounted at /mnt/hello
|
97
|
+
```
|
98
|
+
|
99
|
+
Do file things
|
100
|
+
|
101
|
+
```bash
|
102
|
+
ls /mnt/hello
|
103
|
+
cat /mnt/hello/hello.txt
|
104
|
+
```
|
105
|
+
|
106
|
+
## Fuse2/Fuse3 compatibility
|
33
107
|
|
34
108
|
FFI::Libfuse will prefer Fuse3 over Fuse2 by default. See {FFI::Libfuse::LIBFUSE}
|
35
109
|
|
36
|
-
|
37
|
-
|
110
|
+
New filesystems should write for Fuse3 API and include {FFI::Libfuse::Adapter::Fuse2Compat} for backwards compatibility
|
111
|
+
|
112
|
+
Alternatively filesystems written against Fuse2 API can include {FFI::Libfuse::Adapter::Fuse3Support}
|
38
113
|
|
39
114
|
## MACFuse
|
40
115
|
|
41
|
-
[macFUSE](https://osxfuse.github.io/) (previously OSXFuse) supports a superset of the Fuse2 api
|
42
|
-
|
116
|
+
[macFUSE](https://osxfuse.github.io/) (previously OSXFuse) supports a superset of the Fuse2 api
|
117
|
+
|
118
|
+
**TODO** Implement macFuse extensions
|
119
|
+
|
120
|
+
|
121
|
+
# Under the hood
|
122
|
+
|
123
|
+
{FFI::Libfuse} provides raw access to the underlying libfuse but there some constraints imposed by Ruby.
|
124
|
+
|
125
|
+
## Low-level functions re-implemented in Ruby
|
43
126
|
|
44
|
-
|
127
|
+
The C functions fuse_main(), fuse_daemonize() and fuse_loop<_mt>() are re-implemented to provide
|
45
128
|
|
46
|
-
|
47
|
-
|
129
|
+
* dynamic compatibility between Fuse2 and Fuse3
|
130
|
+
* support for multi-threading under MRI
|
131
|
+
* signal handling in ruby filesystem (eg HUP to reload)
|
48
132
|
|
49
|
-
|
133
|
+
The `-o native' option will use the native C functions but only exists to assist with testing that FFI::Libfuse has
|
134
|
+
similar behaviour to C libfuse.
|
135
|
+
|
136
|
+
See {FFI::Libfuse::Main} and {FFI::Libfuse::FuseCommon}
|
137
|
+
|
138
|
+
## Multi-threading
|
139
|
+
|
140
|
+
{FFI::Libfuse.fuse_main} forces the `-s` (single-thread) option to be set since most Ruby filesystems are
|
141
|
+
unlikely to benefit from the overhead caused by multi-threaded operation obtaining/releasing the GVL around each
|
142
|
+
callback.
|
143
|
+
|
144
|
+
{FFI::Libfuse::Main.fuse_main} does not pass any options by default and should be used in situations where
|
145
|
+
multi-threaded operations may be desirable.
|
50
146
|
|
51
147
|
```ruby
|
52
|
-
FFI::Libfuse::fuse_main(
|
148
|
+
FFI::Libfuse::Main.fuse_main(operations: MyFS.new) if __FILE__ == $0
|
53
149
|
```
|
54
150
|
|
55
|
-
The {FFI::Libfuse::ThreadPool} can be configured with
|
151
|
+
The multi-thread loop uses {FFI::Libfuse::ThreadPool} to control thread usage and can be configured with options
|
152
|
+
`-o max_threads=<n>,max_idle_threads=<n>`
|
56
153
|
|
57
|
-
Callbacks that are about to block (and release the GVL for MRI) should call {FFI::Libfuse::ThreadPool.busy}
|
154
|
+
Callbacks that are about to block (and release the GVL for MRI) should call {FFI::Libfuse::ThreadPool.busy} which will
|
155
|
+
spawn additional worker threads as required.
|
58
156
|
|
59
|
-
|
157
|
+
Note that uncaught exceptions in callbacks will kill the worker thread and if all worker threads are dead the
|
158
|
+
file system will stop and unmount. In particular if the first callback raises an exception
|
60
159
|
|
61
160
|
```ruby
|
62
161
|
def read(*args)
|
@@ -70,29 +169,13 @@ end
|
|
70
169
|
[this discussion](http://fuse.996288.n3.nabble.com/GetAttr-calls-being-serialised-td11741.html)
|
71
170
|
on the serialisation of `#getattr` and `#readdir` calls.
|
72
171
|
|
73
|
-
|
172
|
+
**TODO** Build an example filesystem that makes use of multi-threading
|
74
173
|
|
75
|
-
FFI::Libfuse tries to provide raw access to the underlying libfuse but there some constraints imposed by Ruby.
|
76
|
-
|
77
|
-
The functions fuse_main(), fuse_daemonize() and fuse_loop<_mt>() are re-implemented in Ruby so we can provide
|
78
|
-
|
79
|
-
* dynamic compatibility between Fuse2 and Fuse3
|
80
|
-
* integrated support for multi-threading under MRI (see {FFI::Libfuse::ThreadPool})
|
81
|
-
* signal handling in ruby filesystem (eg HUP to reload)
|
82
|
-
|
83
|
-
Sending `-o native' will used the native C functions but this exists to assist with testing that FFI::Libfuse has
|
84
|
-
similar behaviour to libfuse itself.
|
85
|
-
|
86
|
-
See {FFI::Libfuse::Main} and {FFI::Libfuse::FuseCommon}
|
87
174
|
|
88
175
|
## Contributing
|
89
176
|
|
90
177
|
Bug reports and pull requests are welcome on GitHub at https://github.com/lwoggardner/ffi-libfuse.
|
91
178
|
|
92
|
-
### TODO
|
93
|
-
* Include a MetaFS, PathMapperFS etc (possibly a separate library)
|
94
|
-
* Build a filesystem that can make use of multi-threaded operations
|
95
|
-
* Test with macFUSE
|
96
179
|
|
97
180
|
## License
|
98
181
|
|
data/lib/ffi/accessors.rb
CHANGED
@@ -20,8 +20,8 @@ module FFI
|
|
20
20
|
#
|
21
21
|
# Define a struct attribute reader for members
|
22
22
|
# @param [Array<Symbol>] attrs the attribute names
|
23
|
-
# @param [String] format
|
24
|
-
# A format string containing a single %s to convert attr
|
23
|
+
# @param [Proc|String] format
|
24
|
+
# A Proc, or format string containing a single %s, to convert attr to struct member name
|
25
25
|
# @param [Boolean] simple
|
26
26
|
# Controls how writer methods are defined using block
|
27
27
|
# @param [Proc] block
|
@@ -33,7 +33,7 @@ module FFI
|
|
33
33
|
# @return [void]
|
34
34
|
def ffi_attr_reader(*attrs, format: '%s', simple: true, &block)
|
35
35
|
attrs.each do |attr|
|
36
|
-
member = (format % attr).to_sym
|
36
|
+
member = (format.respond_to?(:call) ? format.call(attr) : format % attr).to_sym
|
37
37
|
ffi_attr_readers[attr] = member
|
38
38
|
if !block
|
39
39
|
define_method(attr) { self[member] }
|
@@ -47,7 +47,7 @@ module FFI
|
|
47
47
|
|
48
48
|
# Define a struct attribute writer
|
49
49
|
# @param [Array<Symbol>] attrs the attribute names
|
50
|
-
# @param [String] format
|
50
|
+
# @param [String|Proc] format
|
51
51
|
# A format string containing a single %s to convert attr symbol to struct member
|
52
52
|
# @param [Boolean] simple
|
53
53
|
# Controls how writer methods are defined using block
|
@@ -55,8 +55,8 @@ module FFI
|
|
55
55
|
# An optional block to set the input value into the struct field.
|
56
56
|
#
|
57
57
|
# If simple is true then the struct field is set to the result of calling block with the input value,
|
58
|
-
# otherwise the method is defined directly from the block. Use __method__[0..-
|
59
|
-
# and self.class.ffi_attr_writers[__method__[0..-
|
58
|
+
# otherwise the method is defined directly from the block. Use __method__[0..-1] to get the attribute name
|
59
|
+
# and self.class.ffi_attr_writers[__method__[0..-1]] to get the struct member name
|
60
60
|
# @return [void]
|
61
61
|
def ffi_attr_writer(*attrs, format: '%s', simple: true, &block)
|
62
62
|
attrs.each do |attr|
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module FFI
|
4
|
+
# Converter generator for different sizes ints as boolean
|
5
|
+
class BooleanInt
|
6
|
+
include DataConverter
|
7
|
+
attr_reader :native_type
|
8
|
+
|
9
|
+
def initialize(int_type)
|
10
|
+
@native_type = FFI.find_type(int_type)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Falsey = 0, Truthy = 1
|
14
|
+
def to_native(obj, _context)
|
15
|
+
obj ? 1 : 0
|
16
|
+
end
|
17
|
+
|
18
|
+
# Not Zero
|
19
|
+
def from_native(object_id, _context)
|
20
|
+
!object_id.zero?
|
21
|
+
end
|
22
|
+
|
23
|
+
%i[char short int long int8 int16 int32 int64].each do |t|
|
24
|
+
FFI.typedef(BooleanInt.new(t), "bool_#{t}".to_sym)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/lib/ffi/devt.rb
CHANGED
@@ -26,5 +26,28 @@ module FFI
|
|
26
26
|
# @param [Integer] dev
|
27
27
|
# @return [Integer] the minor component of dev
|
28
28
|
attach_function :minor, "#{prefix}minor".to_sym, [:int], :int
|
29
|
+
rescue FFI::NotFoundError
|
30
|
+
case Platform::NAME
|
31
|
+
when 'x86_64-darwin'
|
32
|
+
# From https://github.com/golang/go/issues/8106 these functions are not defined on Darwin.
|
33
|
+
class << self
|
34
|
+
# define major(x) ((int32_t)(((u_int32_t)(x) >> 24) & 0xff))
|
35
|
+
def major(dev)
|
36
|
+
(dev >> 24) & 0xff
|
37
|
+
end
|
38
|
+
|
39
|
+
# define minor(x) ((int32_t)((x) & 0xffffff))
|
40
|
+
def minor(dev)
|
41
|
+
(dev & 0xffffff)
|
42
|
+
end
|
43
|
+
|
44
|
+
# define makedev(x,y) ((dev_t)(((x) << 24) | (y)))
|
45
|
+
def makedev(major, minor)
|
46
|
+
(major << 24) | minor
|
47
|
+
end
|
48
|
+
end
|
49
|
+
else
|
50
|
+
raise
|
51
|
+
end
|
29
52
|
end
|
30
53
|
end
|
data/lib/ffi/encoding.rb
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'ffi'
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
# DataConverter for reading/writing encoded strings
|
7
|
+
class Encoding
|
8
|
+
include DataConverter
|
9
|
+
|
10
|
+
attr_reader :encoding
|
11
|
+
|
12
|
+
# Create a dataconverter for the specified encoding
|
13
|
+
# @example
|
14
|
+
# module MyFFIModule
|
15
|
+
# extend FFI::Library
|
16
|
+
# typedef FFI::Encoding.for('utf8'), :utf8_string
|
17
|
+
# end
|
18
|
+
def self.for(encoding)
|
19
|
+
new(encoding)
|
20
|
+
end
|
21
|
+
|
22
|
+
def from_native(value, _ctx)
|
23
|
+
value.force_encoding(encoding)
|
24
|
+
end
|
25
|
+
|
26
|
+
def to_native(value, _ctx)
|
27
|
+
value.encode(encoding)
|
28
|
+
end
|
29
|
+
|
30
|
+
def native_type(_type = nil)
|
31
|
+
FFI::Type::STRING
|
32
|
+
end
|
33
|
+
|
34
|
+
def initialize(encoding)
|
35
|
+
@encoding = encoding
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/lib/ffi/gnu_extensions.rb
CHANGED
@@ -27,7 +27,7 @@ module FFI
|
|
27
27
|
module GNUExtensions
|
28
28
|
if FFI::Platform::IS_GNU
|
29
29
|
extend FFI::Library
|
30
|
-
ffi_lib
|
30
|
+
ffi_lib(%w[libdl.so libdl.so.2].flat_map { |l| [l, "#{FFI::Platform::NAME}-gnu/#{l}"] })
|
31
31
|
|
32
32
|
# @!method dlopen(library,type)
|
33
33
|
# @return [FFI::Pointer] library address, possibly NULL
|
data/lib/ffi/libfuse/ackbar.rb
CHANGED
@@ -29,15 +29,15 @@ module FFI
|
|
29
29
|
end
|
30
30
|
|
31
31
|
# @param [Hash<Symbol|String|Integer,String|Proc>] traps
|
32
|
-
# Map of signal or signo to signal handler as per Signal.trap
|
32
|
+
# Map of signal or signo to signal handler as per {::Signal.trap}
|
33
33
|
# @param [Boolean] force
|
34
|
-
#
|
34
|
+
# Unless set, only installs traps currently set to 'DEFAULT'.
|
35
35
|
def initialize(traps, force: false, signal: Signal)
|
36
36
|
@signal = signal
|
37
37
|
@traps = traps.transform_keys { |k| signame(k) }
|
38
38
|
@pr, @pw = ::IO.pipe
|
39
39
|
@monitor = nil
|
40
|
-
@restore = @traps.
|
40
|
+
@restore = @traps.to_h { |sig, handler| [sig, trap(sig, handler, force: force)] }
|
41
41
|
end
|
42
42
|
|
43
43
|
# Handle the next available signal on the pipe (without blocking)
|
@@ -5,15 +5,14 @@ require_relative '../fuse_context'
|
|
5
5
|
module FFI
|
6
6
|
module Libfuse
|
7
7
|
module Adapter
|
8
|
-
#
|
9
|
-
#
|
10
|
-
# {ThreadLocalContext} may be a less intrusive means to make the context available to callbacks
|
8
|
+
# Injects a wrapper via #{FuseCallbacks#fuse_wrappers} make the current {FuseContext} object available to
|
9
|
+
# callbacks (except :destroy) via thread local variable :fuse_context
|
11
10
|
module Context
|
12
11
|
# @!visibility private
|
13
12
|
def fuse_wrappers(*wrappers)
|
14
13
|
wrappers.unshift(
|
15
14
|
{
|
16
|
-
wrapper: proc { |_fm, *args, **_, &b|
|
15
|
+
wrapper: proc { |_fm, *args, **_, &b| Context.thread_local_context(*args, &b) },
|
17
16
|
excludes: %i[destroy]
|
18
17
|
}
|
19
18
|
)
|
@@ -24,12 +23,15 @@ module FFI
|
|
24
23
|
|
25
24
|
module_function
|
26
25
|
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
26
|
+
# Capture {FuseContext} in thread local variable
|
27
|
+
def fuse_context
|
28
|
+
Thread.current[:fuse_context] ||= FuseContext.get
|
29
|
+
end
|
30
|
+
|
31
|
+
def thread_local_context(*args)
|
32
|
+
yield(*args)
|
33
|
+
ensure
|
34
|
+
Thread.current[:fuse_context] = nil
|
33
35
|
end
|
34
36
|
end
|
35
37
|
end
|
@@ -5,77 +5,78 @@ module FFI
|
|
5
5
|
module Adapter
|
6
6
|
# Wrapper module to assist filesystem written for Fuse3 to be compatible with Fuse2
|
7
7
|
module Fuse2Compat
|
8
|
-
# @!visibility private
|
9
8
|
# Wrapper shim for fuse methods to ensure compatibility with Fuse2
|
10
|
-
module
|
9
|
+
module Prepend
|
11
10
|
include Adapter
|
12
11
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
super(path, size, fuse_file_info)
|
19
|
-
end
|
12
|
+
if FUSE_MAJOR_VERSION == 2
|
13
|
+
# @!visibility private
|
14
|
+
def getattr(path, stat, fuse_file_info = nil)
|
15
|
+
super(path, stat, fuse_file_info)
|
16
|
+
end
|
20
17
|
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
def truncate(path, size, fuse_file_info = nil)
|
19
|
+
super(path, size, fuse_file_info)
|
20
|
+
end
|
24
21
|
|
25
|
-
|
26
|
-
|
27
|
-
|
22
|
+
def init(fuse_conn_info, fuse_config = nil)
|
23
|
+
super(fuse_conn_info, fuse_config)
|
24
|
+
end
|
28
25
|
|
29
|
-
|
30
|
-
|
31
|
-
|
26
|
+
def chown(path, uid, gid, fuse_file_info = nil)
|
27
|
+
super(path, uid, gid, fuse_file_info)
|
28
|
+
end
|
32
29
|
|
33
|
-
|
34
|
-
|
35
|
-
|
30
|
+
def chmod(path, mode, fuse_file_info = nil)
|
31
|
+
super(path, mode, fuse_file_info)
|
32
|
+
end
|
36
33
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
end
|
34
|
+
def utimens(path, atime, mtime, fuse_file_info = nil)
|
35
|
+
super(path, atime, mtime, fuse_file_info)
|
36
|
+
end
|
41
37
|
|
42
|
-
|
43
|
-
|
44
|
-
|
38
|
+
def readdir(path, buffer, filler, offset, fuse_file_info, fuse_readdir_flag = 0)
|
39
|
+
f3_fill = proc { |buf, name, stat, off = 0, _fuse_fill_dir_flag = 0| filler.call(buf, name, stat, off) }
|
40
|
+
super(path, buffer, f3_fill, offset, fuse_file_info, fuse_readdir_flag)
|
41
|
+
end
|
45
42
|
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
def fgetattr(path, stat, ffi)
|
44
|
+
stat.clear # For some reason (at least on OSX) the stat is not clear when this is called.
|
45
|
+
getattr(path, stat, ffi)
|
46
|
+
0
|
47
|
+
end
|
49
48
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
end
|
49
|
+
def ftruncate(*args)
|
50
|
+
truncate(*args)
|
51
|
+
end
|
54
52
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
fuse_config = FuseConfig.new
|
59
|
-
init_fuse_config(fuse_config, :fuse2)
|
60
|
-
res << :nullpath_ok if fuse_config.nullpath_ok?
|
53
|
+
def fuse_respond_to?(fuse_method)
|
54
|
+
fuse_method = fuse_method[1..].to_sym if %i[fgetattr ftruncate].include?(fuse_method)
|
55
|
+
super(fuse_method)
|
61
56
|
end
|
62
57
|
|
63
|
-
|
64
|
-
|
65
|
-
|
58
|
+
def fuse_flags
|
59
|
+
res = defined?(super) ? super : []
|
60
|
+
if respond_to?(:init_fuse_config)
|
61
|
+
fuse_config = FuseConfig.new
|
62
|
+
init_fuse_config(fuse_config, :fuse2)
|
63
|
+
res << :nullpath_ok if fuse_config.nullpath_ok?
|
64
|
+
end
|
66
65
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
66
|
+
res
|
67
|
+
end
|
68
|
+
|
69
|
+
else
|
70
|
+
def init(*args)
|
71
|
+
init_fuse_config(args.detect { |a| a.is_a?(FuseConfig) }) if respond_to?(:init_fuse_config)
|
72
|
+
super if defined?(super)
|
73
|
+
end
|
72
74
|
end
|
73
75
|
end
|
74
76
|
|
75
77
|
# @!visibility private
|
76
78
|
def self.included(mod)
|
77
|
-
|
78
|
-
mod.prepend(prepend_module)
|
79
|
+
mod.prepend(Prepend)
|
79
80
|
end
|
80
81
|
|
81
82
|
# @!method init_fuse_config(fuse_config,compat)
|