ffi-libfuse 0.3.3 → 0.4.0
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/CHANGELOG.md +18 -22
- data/README.md +1 -1
- data/lib/ffi/accessors.rb +21 -7
- data/lib/ffi/boolean_int.rb +1 -1
- data/lib/ffi/devt.rb +3 -3
- data/lib/ffi/libfuse/adapter/debug.rb +53 -15
- data/lib/ffi/libfuse/adapter/fuse2_compat.rb +38 -21
- data/lib/ffi/libfuse/adapter/fuse3_support.rb +0 -1
- data/lib/ffi/libfuse/adapter/ruby.rb +210 -159
- data/lib/ffi/libfuse/adapter/safe.rb +69 -21
- data/lib/ffi/libfuse/callbacks.rb +2 -1
- data/lib/ffi/libfuse/filesystem/accounting.rb +1 -1
- data/lib/ffi/libfuse/filesystem/mapped_files.rb +33 -7
- data/lib/ffi/libfuse/filesystem/pass_through_dir.rb +0 -1
- data/lib/ffi/libfuse/filesystem/virtual_dir.rb +293 -126
- data/lib/ffi/libfuse/filesystem/virtual_file.rb +85 -79
- data/lib/ffi/libfuse/filesystem/virtual_fs.rb +34 -15
- data/lib/ffi/libfuse/filesystem/virtual_link.rb +60 -0
- data/lib/ffi/libfuse/filesystem/virtual_node.rb +104 -87
- data/lib/ffi/libfuse/filesystem.rb +1 -1
- data/lib/ffi/libfuse/fuse2.rb +3 -2
- data/lib/ffi/libfuse/fuse3.rb +1 -1
- data/lib/ffi/libfuse/fuse_args.rb +5 -2
- data/lib/ffi/libfuse/fuse_buf.rb +112 -0
- data/lib/ffi/libfuse/fuse_buf_vec.rb +228 -0
- data/lib/ffi/libfuse/fuse_common.rb +10 -4
- data/lib/ffi/libfuse/fuse_config.rb +16 -7
- data/lib/ffi/libfuse/fuse_operations.rb +86 -41
- data/lib/ffi/libfuse/gem_helper.rb +91 -0
- data/lib/ffi/libfuse/gem_version.rb +4 -44
- data/lib/ffi/libfuse/io.rb +56 -0
- data/lib/ffi/libfuse/main.rb +27 -24
- data/lib/ffi/libfuse/test_helper.rb +68 -60
- data/lib/ffi/libfuse/version.rb +1 -1
- data/lib/ffi/libfuse.rb +1 -1
- data/lib/ffi/stat/native.rb +4 -4
- data/lib/ffi/stat.rb +19 -3
- data/lib/ffi/struct_array.rb +2 -1
- data/sample/hello_fs.rb +1 -1
- metadata +7 -3
- data/lib/ffi/libfuse/fuse_buffer.rb +0 -257
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e105d84b1d0f73af20845ed1d39e51ae61f9ca4998fa9caf505b4e87ae08eaa9
|
4
|
+
data.tar.gz: 7f9013b530bc62e9fb4071899e13f191fdc720f662221da1cac0cd554a76bc5f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72b0a464ab67be704cb14f3ce4b07f1f9a29d260ee50864dcf8c75cc24ba2eaf43aab6ae9f79fda9edb707cded39fde10e8504be7b8ca011b1a7d625969d62f6
|
7
|
+
data.tar.gz: b85626a26f149dc1852ae5928cef67eb5dd7fc4353acb6bafa4fb0061aec38dce6d6e6c8137b216bc540263ba28f5b5f627f3af8feecb9bab417bbfc64df45ab
|
data/CHANGELOG.md
CHANGED
@@ -1,47 +1,43 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
-
## [0.
|
3
|
+
## [0.4.0](https://github.com/lwoggardner/ffi-libfuse/compare/v0.3.4...v0.4.0) (2024-01-21)
|
4
4
|
|
5
5
|
|
6
6
|
### ⚠ BREAKING CHANGES
|
7
7
|
|
8
|
-
*
|
8
|
+
* **filesystem:** Fuse callbacks :init and :destroy are no longer passed on to sub-filesystems.
|
9
|
+
* **adapters:** Adapter::Debug now includes Adapter::Safe.
|
10
|
+
* Option parsing errors via raise exception rather than return false/nil
|
9
11
|
|
10
12
|
### Features
|
11
13
|
|
12
|
-
*
|
13
|
-
|
14
|
-
|
15
|
-
|
14
|
+
* **adapters:** Adapter::Debug now includes Adapter::Safe. ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
15
|
+
* **filesystem:** Support :rename operation in virtual filesystems ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
16
|
+
* **filesystem:** Support symlinks and hardlinks in virtual filesystems (VirtualDir/MemoryFS) ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
17
|
+
* Option parsing errors via raise exception rather than return false/nil ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
16
18
|
|
17
|
-
* Support downstream RFuse/RFuseFS ([e6b3fb5](https://github.com/lwoggardner/ffi-libfuse/commit/e6b3fb552b8881dbf28f014617b7412f2542aaa3))
|
18
19
|
|
20
|
+
### Bug Fixes
|
19
21
|
|
20
|
-
|
22
|
+
* **fuse2compat:** Enhanced Fuse2 compatibility in Fuse2Compat module ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
23
|
+
* symlinks and hard links ([a595304](https://github.com/lwoggardner/ffi-libfuse/commit/a59530427d7eb85961a724969eaa6ec099c5e4f6))
|
21
24
|
|
22
|
-
|
23
|
-
|
24
|
-
## [0.3.2](https://github.com/lwoggardner/ffi-libfuse/compare/v0.3.0...v0.3.2) (2023-01-07)
|
25
|
+
## [0.3.4](https://github.com/lwoggardner/ffi-libfuse/compare/v0.3.3...v0.3.4) (2023-01-08)
|
25
26
|
|
26
27
|
|
27
28
|
### Miscellaneous Chores
|
28
29
|
|
29
|
-
*
|
30
|
-
|
31
|
-
## [0.3.0](https://github.com/lwoggardner/ffi-libfuse/compare/v0.2.1...v0.3.0) (2023-01-07)
|
30
|
+
* **github:** allow downstream gems to use gem_version etc ([73f3b92](https://github.com/lwoggardner/ffi-libfuse/commit/73f3b92f5e8a1f86a9f6053b71470d7c113e6d19))
|
32
31
|
|
32
|
+
## [0.3.3](https://github.com/lwoggardner/ffi-libfuse/compare/v0.1.0...v0.3.3) (2023-01-07)
|
33
33
|
|
34
34
|
### Miscellaneous Chores
|
35
35
|
|
36
|
-
*
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
### Miscellaneous Chores
|
41
|
-
|
42
|
-
* release 0.2.1 ([bb0ef37](https://github.com/lwoggardner/ffi-libfuse/commit/bb0ef37c05a41c6b51a14e5cae292b2d7b75ef1c))
|
36
|
+
* **github:** release 0.3.3 ([b54a56f](https://github.com/lwoggardner/ffi-libfuse/commit/b54a56f3f93f15c7684aa2cb2c2dd38c9d033e7f))
|
37
|
+
|
38
|
+
Using github actions
|
43
39
|
|
44
|
-
##
|
40
|
+
## 0.1.0 (2023-01-07)
|
45
41
|
|
46
42
|
### ⚠ BREAKING CHANGES
|
47
43
|
|
data/README.md
CHANGED
data/lib/ffi/accessors.rb
CHANGED
@@ -19,22 +19,29 @@ module FFI
|
|
19
19
|
|
20
20
|
#
|
21
21
|
# Define a struct attribute reader for members
|
22
|
-
# @param [Array<Symbol>]
|
22
|
+
# @param [Array<Symbol>]
|
23
|
+
# attrs the attribute names used as the reader method name
|
24
|
+
#
|
25
|
+
# a trailing '?' will be stripped from attribute names for primary reader method name, and cause an
|
26
|
+
# boolean alias method to be created.
|
23
27
|
# @param [Proc|String] format
|
24
|
-
# A Proc, or format string containing a single %s, to convert
|
28
|
+
# A Proc, or format string containing a single %s, to convert each attribute name to the corresponding
|
29
|
+
# struct member name
|
25
30
|
# @param [Boolean] simple
|
26
31
|
# Controls how writer methods are defined using block
|
27
32
|
# @param [Proc] block
|
28
|
-
# An optional block to the struct field
|
33
|
+
# An optional block to convert the struct field value into something more useful
|
29
34
|
#
|
30
35
|
# If simple is true then block takes the struct field value, otherwise method is defined directly from the block
|
31
|
-
# and should use __method__ to get the
|
32
|
-
# name
|
36
|
+
# and should use __method__ to get the attribute name. and self.class.ffi_attr_readers[__method__] to get the
|
37
|
+
# member name if these are not available from enclosed variables.
|
33
38
|
# @return [void]
|
34
39
|
def ffi_attr_reader(*attrs, format: '%s', simple: true, &block)
|
35
40
|
attrs.each do |attr|
|
41
|
+
bool, attr = attr[-1] == '?' ? [true, attr[..-2]] : [false, attr]
|
42
|
+
|
36
43
|
member = (format.respond_to?(:call) ? format.call(attr) : format % attr).to_sym
|
37
|
-
ffi_attr_readers[attr] = member
|
44
|
+
ffi_attr_readers[attr.to_sym] = member
|
38
45
|
if !block
|
39
46
|
define_method(attr) { self[member] }
|
40
47
|
elsif simple
|
@@ -42,11 +49,14 @@ module FFI
|
|
42
49
|
else
|
43
50
|
define_method(attr, &block)
|
44
51
|
end
|
52
|
+
|
53
|
+
alias_method "#{attr}?", attr if bool
|
45
54
|
end
|
46
55
|
end
|
47
56
|
|
48
57
|
# Define a struct attribute writer
|
49
58
|
# @param [Array<Symbol>] attrs the attribute names
|
59
|
+
# trailing '?' will be stripped from attribute names
|
50
60
|
# @param [String|Proc] format
|
51
61
|
# A format string containing a single %s to convert attr symbol to struct member
|
52
62
|
# @param [Boolean] simple
|
@@ -60,6 +70,8 @@ module FFI
|
|
60
70
|
# @return [void]
|
61
71
|
def ffi_attr_writer(*attrs, format: '%s', simple: true, &block)
|
62
72
|
attrs.each do |attr|
|
73
|
+
attr = attr[..-2] if attr[-1] == '?'
|
74
|
+
|
63
75
|
member = (format % attr).to_sym
|
64
76
|
ffi_attr_writers[attr.to_sym] = member
|
65
77
|
if !block
|
@@ -95,7 +107,9 @@ module FFI
|
|
95
107
|
# @param [Array<Symbol>] flags list of flags
|
96
108
|
# @return [void]
|
97
109
|
def ffi_bitflag_reader(attr, *flags)
|
98
|
-
flags.each
|
110
|
+
flags.each do |f|
|
111
|
+
ffi_attr_reader(:"#{f}?", simple: false) { self[attr].include?(f) }
|
112
|
+
end
|
99
113
|
end
|
100
114
|
|
101
115
|
# Define individual flag writers over a bitmask field
|
data/lib/ffi/boolean_int.rb
CHANGED
data/lib/ffi/devt.rb
CHANGED
@@ -15,17 +15,17 @@ module FFI
|
|
15
15
|
# @param [Integer] major
|
16
16
|
# @param [Integer] minor
|
17
17
|
# @return [Integer] combined major/minor to a single value to pass to mknod etc
|
18
|
-
attach_function :makedev, "#{prefix}makedev"
|
18
|
+
attach_function :makedev, :"#{prefix}makedev", %i[int int], :int
|
19
19
|
|
20
20
|
# @!method major(dev)
|
21
21
|
# @param [Integer] dev
|
22
22
|
# @return [Integer] the major component of dev
|
23
|
-
attach_function :major, "#{prefix}major"
|
23
|
+
attach_function :major, :"#{prefix}major", [:int], :int
|
24
24
|
|
25
25
|
# @!method minor(dev)
|
26
26
|
# @param [Integer] dev
|
27
27
|
# @return [Integer] the minor component of dev
|
28
|
-
attach_function :minor, "#{prefix}minor"
|
28
|
+
attach_function :minor, :"#{prefix}minor", [:int], :int
|
29
29
|
rescue FFI::NotFoundError
|
30
30
|
case Platform::NAME
|
31
31
|
when 'x86_64-darwin'
|
@@ -1,13 +1,24 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require_relative 'safe'
|
4
|
+
|
3
5
|
module FFI
|
4
6
|
module Libfuse
|
5
7
|
module Adapter
|
6
8
|
# Debug callbacks
|
7
9
|
#
|
8
10
|
# When included in a filesystem class, and if debugging is enabled via {Main#fuse_debug}, then installs a wrapper
|
9
|
-
# via #{FuseCallbacks#fuse_wrappers} to log callbacks
|
11
|
+
# via #{FuseCallbacks#fuse_wrappers} to log callbacks.
|
12
|
+
#
|
13
|
+
# Simple format options can be handled by #{debug_config}, or override the **Module Functions** on an including
|
14
|
+
# class for more programmatic control of output.
|
15
|
+
#
|
16
|
+
# @note {Debug} includes {Safe} as it expects to handle (and re-raise) exceptions.
|
10
17
|
module Debug
|
18
|
+
include Safe
|
19
|
+
|
20
|
+
# Default format
|
21
|
+
# @see debug_callback
|
11
22
|
DEFAULT_FORMAT = "%<p>s %<n>s %<t>s %<m>s(%<a>s)\n\t=> %<r>s"
|
12
23
|
|
13
24
|
# @return [Boolean] true if debug is enabled
|
@@ -26,8 +37,8 @@ module FFI
|
|
26
37
|
def fuse_wrappers(*wrappers)
|
27
38
|
conf = { prefix: self.class.name }.merge!(debug_config)
|
28
39
|
# validate config for bad formats, strftime etc
|
29
|
-
|
30
|
-
wrappers << proc { |fm, *args, &b|
|
40
|
+
debug_format(:test_debug, [], :result, **conf)
|
41
|
+
wrappers << proc { |fm, *args, &b| debug_callback(fm, *args, **conf, &b) } if debug?
|
31
42
|
return wrappers unless defined?(super)
|
32
43
|
|
33
44
|
super(*wrappers)
|
@@ -41,10 +52,11 @@ module FFI
|
|
41
52
|
|
42
53
|
module_function
|
43
54
|
|
44
|
-
# Debug fuse method, args and result
|
55
|
+
# Debug fuse method, args and result of yielding args to the block
|
56
|
+
#
|
45
57
|
# @param [Symbol] fuse_method the callback name
|
46
58
|
# @param [Array] args callback arguments
|
47
|
-
# @param [Hash<Symbol,String>] options see {
|
59
|
+
# @param [Hash<Symbol,String>] options see {debug_format} for defaults
|
48
60
|
# @option options [String] prefix
|
49
61
|
# @option options [String] strftime a date time format
|
50
62
|
# @option options [String] format format string with fields
|
@@ -55,25 +67,49 @@ module FFI
|
|
55
67
|
# * %<a>: Comma separate list of arguments
|
56
68
|
# * %<r>: Result of the method call (or any error raised)
|
57
69
|
# * %<p>: The value of prefix option
|
70
|
+
# @raise [SystemCallError]
|
71
|
+
# expected Errors raised from callbacks are logged with their cause (if any)
|
72
|
+
# @raise [StandardError,ScriptError]
|
73
|
+
# unexpected Errors raised from callbacks are logged with their backtrace
|
58
74
|
def debug_callback(fuse_method, *args, **options)
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
debug(fuse_method, args, "#{e.class.name}(errno=#{e.errno}): #{e.message}", **options)
|
63
|
-
raise
|
75
|
+
result = yield(*args)
|
76
|
+
debug(fuse_method, args, result, **options)
|
77
|
+
result
|
64
78
|
rescue StandardError, ScriptError => e
|
65
|
-
|
66
|
-
|
79
|
+
debug(fuse_method, args, error_message(e), **options)
|
80
|
+
debug_error(e)
|
67
81
|
raise
|
68
82
|
end
|
69
83
|
|
70
|
-
# @!
|
84
|
+
# @!group Module Functions
|
85
|
+
|
86
|
+
# Logs the callback
|
71
87
|
def debug(fuse_method, args, result, **options)
|
72
88
|
warn debug_format(fuse_method, args, result, **options)
|
73
|
-
result
|
74
89
|
end
|
75
90
|
|
76
|
-
#
|
91
|
+
# @param [Exception] err
|
92
|
+
# @return [String] the detailed error message for err
|
93
|
+
def error_message(err)
|
94
|
+
if err.is_a?(SystemCallError)
|
95
|
+
"#{err.class.name}(errno=#{err.errno}): #{err.message}"
|
96
|
+
else
|
97
|
+
"#{err.class.name}: #{err.message}"
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
# Log additional information for errors (cause/backtrace etc)
|
102
|
+
# @see debug_callback
|
103
|
+
def debug_error(err)
|
104
|
+
if err.is_a?(SystemCallError)
|
105
|
+
warn "Caused by #{error_message(err.cause)}" if err.cause
|
106
|
+
else
|
107
|
+
warn err.backtrace.join("\n\t")
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# @return [String] the formatted debug message
|
112
|
+
# @see debug_callback
|
77
113
|
def debug_format(fuse_method, args, result, prefix: 'DEBUG', strftime: '%FT%T%:z', format: DEFAULT_FORMAT)
|
78
114
|
format(format,
|
79
115
|
p: prefix,
|
@@ -83,6 +119,8 @@ module FFI
|
|
83
119
|
a: args.map(&:to_s).join(','),
|
84
120
|
r: result)
|
85
121
|
end
|
122
|
+
|
123
|
+
# @!endgroup
|
86
124
|
end
|
87
125
|
end
|
88
126
|
end
|
@@ -31,8 +31,8 @@ module FFI
|
|
31
31
|
super(path, mode, fuse_file_info)
|
32
32
|
end
|
33
33
|
|
34
|
-
def utimens(path,
|
35
|
-
super(path,
|
34
|
+
def utimens(path, times, fuse_file_info = nil)
|
35
|
+
super(path, times, fuse_file_info)
|
36
36
|
end
|
37
37
|
|
38
38
|
def readdir(path, buffer, filler, offset, fuse_file_info, fuse_readdir_flag = 0)
|
@@ -40,49 +40,66 @@ module FFI
|
|
40
40
|
super(path, buffer, f3_fill, offset, fuse_file_info, fuse_readdir_flag)
|
41
41
|
end
|
42
42
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
end
|
43
|
+
def fuse_respond_to?(fuse_method)
|
44
|
+
# getdir is never supported here anyway
|
45
|
+
# fgetattr and ftruncate already fallback to the respective basic method
|
46
|
+
return false if %i[getdir fgetattr ftruncate].include?(fuse_method)
|
48
47
|
|
49
|
-
|
50
|
-
truncate(*args)
|
48
|
+
super(fuse_method)
|
51
49
|
end
|
52
50
|
|
53
|
-
def
|
54
|
-
|
55
|
-
|
51
|
+
def fuse_options(args)
|
52
|
+
super if defined?(super)
|
53
|
+
return unless respond_to?(:init_fuse_config)
|
54
|
+
|
55
|
+
FUSE_CONFIG_ONLY_ATTRIBUTES.each do |opt|
|
56
|
+
args.add("-o#{opt}") if fuse_config.send(opt)
|
57
|
+
end
|
56
58
|
end
|
57
59
|
|
58
60
|
def fuse_flags
|
59
61
|
res = defined?(super) ? super : []
|
60
|
-
|
61
|
-
fuse_config = FuseConfig.new
|
62
|
-
init_fuse_config(fuse_config, :fuse2)
|
63
|
-
res << :nullpath_ok if fuse_config.nullpath_ok?
|
64
|
-
end
|
62
|
+
return res unless respond_to?(:init_fuse_config)
|
65
63
|
|
64
|
+
FUSE_CONFIG_FLAGS.each { |opt| res << opt if fuse_config.send(opt) }
|
66
65
|
res
|
67
66
|
end
|
68
67
|
|
68
|
+
private
|
69
|
+
|
70
|
+
def fuse_config
|
71
|
+
@fuse_config ||= begin
|
72
|
+
fuse_config = FuseConfig.new
|
73
|
+
init_fuse_config(fuse_config, :fuse2) if respond_to?(:init_fuse_config)
|
74
|
+
fuse_config
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
69
78
|
else
|
70
79
|
def init(*args)
|
71
|
-
init_fuse_config(args.detect { |a| a.is_a?(FuseConfig) }) if respond_to?(:init_fuse_config)
|
80
|
+
init_fuse_config(args.detect { |a| a.is_a?(FuseConfig) }, :fuse3) if respond_to?(:init_fuse_config)
|
72
81
|
super if defined?(super)
|
73
82
|
end
|
74
83
|
end
|
75
84
|
end
|
76
85
|
|
86
|
+
# Attributes in Fuse3 config that cannot be set by Fuse3 options. If set via {init_fuse_config} the
|
87
|
+
# equivalent options will be force set under Fuse 2
|
88
|
+
FUSE_CONFIG_ONLY_ATTRIBUTES = %i[hard_remove use_ino readdir_ino direct_io].freeze
|
89
|
+
|
90
|
+
# Attributes in Fuse3 config that were {FuseOperations#fuse_flags} in Fuse2. If set via {init_fuse_config} the
|
91
|
+
# equivalent flags will be added
|
92
|
+
FUSE_CONFIG_FLAGS = %i[nullpath_ok].freeze
|
93
|
+
|
77
94
|
# @!visibility private
|
78
95
|
def self.included(mod)
|
79
|
-
mod.prepend(Prepend)
|
96
|
+
mod.prepend(Prepend) if FUSE_MAJOR_VERSION < 3
|
80
97
|
end
|
81
98
|
|
82
99
|
# @!method init_fuse_config(fuse_config,compat)
|
83
100
|
# @abstract
|
84
|
-
# Define this method to configure the
|
85
|
-
# can be converted to appropriate flags
|
101
|
+
# Define this method to configure the {FuseConfig} object so that under Fuse2 the config options
|
102
|
+
# can be converted to appropriate flags or options
|
86
103
|
#
|
87
104
|
# @param [FuseConfig] fuse_config the fuse config object
|
88
105
|
# @param [Symbol] compat either :fuse2 or :fuse3
|