ffi-libfuse 0.0.1.rctest12 → 0.3.3
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/CHANGELOG.md +60 -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/flock.rb +7 -5
- 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 +7 -4
- data/lib/ffi/libfuse/adapter/interrupt.rb +1 -1
- data/lib/ffi/libfuse/adapter/ruby.rb +499 -148
- data/lib/ffi/libfuse/adapter/safe.rb +12 -11
- 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 +196 -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 +32 -24
- data/lib/ffi/libfuse/fuse3.rb +28 -18
- data/lib/ffi/libfuse/fuse_args.rb +71 -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 +60 -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 +57 -21
- data/lib/ffi/libfuse/fuse_opt.rb +1 -1
- data/lib/ffi/libfuse/fuse_version.rb +10 -6
- data/lib/ffi/libfuse/gem_version.rb +54 -0
- data/lib/ffi/libfuse/main.rb +96 -48
- data/lib/ffi/libfuse/test_helper.rb +145 -0
- data/lib/ffi/libfuse/version.rb +1 -1
- data/lib/ffi/libfuse.rb +13 -4
- data/lib/ffi/ruby_object.rb +4 -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 +83 -10
- data/lib/ffi/libfuse/adapter/thread_local_context.rb +0 -36
- data/lib/ffi/libfuse/test/operations.rb +0 -56
- data/lib/ffi/libfuse/test.rb +0 -3
data/sample/hello_fs.rb
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'ffi/libfuse'
|
|
5
|
+
|
|
6
|
+
# Hello World!
|
|
7
|
+
class HelloFS
|
|
8
|
+
include FFI::Libfuse::Adapter::Ruby
|
|
9
|
+
include FFI::Libfuse::Adapter::Fuse2Compat
|
|
10
|
+
|
|
11
|
+
# FUSE Configuration methods
|
|
12
|
+
|
|
13
|
+
def fuse_options(args)
|
|
14
|
+
args.parse!({ 'subject=' => :subject }) do |key:, value:, **|
|
|
15
|
+
raise FFI::Libfuse::Error, 'subject option must be at least 2 characters' unless value.size >= 2
|
|
16
|
+
|
|
17
|
+
@subject = value if key == :subject
|
|
18
|
+
:handled
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def fuse_help
|
|
23
|
+
'-o subject=<subject> a target to say hello to'
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def fuse_configure
|
|
27
|
+
@subject ||= 'World!'
|
|
28
|
+
@content = "Hello #{@subject}\n"
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# FUSE callbacks
|
|
32
|
+
|
|
33
|
+
def getattr(path, stat, *_args)
|
|
34
|
+
case path
|
|
35
|
+
when '/'
|
|
36
|
+
stat.directory(mode: 0o550)
|
|
37
|
+
when '/hello.txt'
|
|
38
|
+
stat.file(mode: 0o440, size: @content.size)
|
|
39
|
+
else
|
|
40
|
+
raise Errno::ENOENT
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def readdir(_path, *_args)
|
|
45
|
+
yield 'hello.txt'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def read(_path, *_args)
|
|
49
|
+
@content
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# Start the file system
|
|
54
|
+
FFI::Libfuse.fuse_main(operations: HelloFS.new) if __FILE__ == $0
|
data/sample/memory_fs.rb
CHANGED
|
@@ -2,188 +2,12 @@
|
|
|
2
2
|
# frozen_string_literal: true
|
|
3
3
|
|
|
4
4
|
require 'ffi/libfuse'
|
|
5
|
+
require 'ffi/libfuse/filesystem/virtual_fs'
|
|
5
6
|
|
|
6
7
|
# A simple in-memory filesystem defined with hashes.
|
|
7
|
-
|
|
8
|
-
# It is writable to the user that mounted it may create and edit files within it
|
|
9
|
-
#
|
|
10
|
-
# === Usage
|
|
11
|
-
# root = Memory.new(files: { 'hello' => { 'world.txt' => 'Hello World'}})
|
|
12
|
-
# root.mkdir("/hello")
|
|
13
|
-
# root.("/hello/world","Hello World!\n")
|
|
14
|
-
# root.write("/hello/everybody","Hello Everyone!\n")
|
|
15
|
-
#
|
|
16
|
-
# Libfuse::fuse_main($0,ARGV,operations: root)
|
|
17
|
-
#
|
|
18
|
-
#
|
|
19
|
-
class MemoryFS
|
|
20
|
-
# @return [Hash<String,Object>] list of file objects by path
|
|
21
|
-
attr_reader :root
|
|
8
|
+
class MemoryFS < FFI::Libfuse::Filesystem::VirtualFS; end
|
|
22
9
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
include FFI::Libfuse::Adapter::Pathname
|
|
10
|
+
# Set this to test multi-threading etc...
|
|
11
|
+
main_class = ENV.fetch('MEMORY_FS_SKIP_DEFAULT_ARGS', 'N') == 'Y' ? FFI::Libfuse::Main : FFI::Libfuse
|
|
26
12
|
|
|
27
|
-
|
|
28
|
-
def dig(*_args)
|
|
29
|
-
raise Errno::ENOTDIR
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def fill_stat(stat = FFI::Stat.new)
|
|
33
|
-
stat.file(mode: mode, ctime: ctime, atime: atime, mtime: mtime, size: content.size)
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
|
|
37
|
-
# rubocop:disable Lint/StructNewOverride
|
|
38
|
-
Dir = Struct.new(:mode, :entries, :ctime, :atime, :mtime) do
|
|
39
|
-
def dig(*args)
|
|
40
|
-
entries.dig(*args)
|
|
41
|
-
end
|
|
42
|
-
|
|
43
|
-
def fill_stat(stat = FFI::Stat.new)
|
|
44
|
-
stat.directory(mode: mode, ctime: ctime, atime: atime, mtime: mtime)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
# rubocop:enable Lint/StructNewOverride
|
|
48
|
-
|
|
49
|
-
def initialize(files: {}, max_size: 100_000, max_files: 1_000)
|
|
50
|
-
now = Time.now
|
|
51
|
-
@root = Dir.new(0x755, {}, now, now, now)
|
|
52
|
-
@total_size = 0
|
|
53
|
-
@total_files = 1
|
|
54
|
-
@max_size = max_size
|
|
55
|
-
@max_files = max_files
|
|
56
|
-
|
|
57
|
-
build(files)
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
def build(files, path = ::Pathname.new('/'))
|
|
61
|
-
files.each_pair do |basename, content|
|
|
62
|
-
raise 'Initial file keys must be String' unless basename.is_a?(String)
|
|
63
|
-
raise 'Initial file keys must not contain path separators' if basename =~ %r{[/\\]}
|
|
64
|
-
|
|
65
|
-
entry_path = path + basename
|
|
66
|
-
case content
|
|
67
|
-
when String
|
|
68
|
-
create(entry_path, 0x644)
|
|
69
|
-
write(entry_path, content, 0)
|
|
70
|
-
when Hash
|
|
71
|
-
mkdir(entry_path, 0x755)
|
|
72
|
-
build(content, entry_path)
|
|
73
|
-
else
|
|
74
|
-
raise 'Initial files must be String or Hash'
|
|
75
|
-
end
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
def fuse_version
|
|
80
|
-
'MemoryFS: Version x.y.z'
|
|
81
|
-
end
|
|
82
|
-
|
|
83
|
-
def fuse_traps
|
|
84
|
-
{
|
|
85
|
-
HUP: -> { reload }
|
|
86
|
-
}
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def statfs(_path, statfs_buf)
|
|
90
|
-
blocks = @total_size / 1_000
|
|
91
|
-
statfs_buf.bsize = 1 # block size (in Kb)
|
|
92
|
-
statfs_buf.frsize = 1 # fragment size pretty much always bsize
|
|
93
|
-
statfs_buf.blocks = @max_size
|
|
94
|
-
statfs_buf.bfree = @max_size - blocks
|
|
95
|
-
statfs_buf.bavail = @max_size - blocks
|
|
96
|
-
statfs_buf.files = @max_files
|
|
97
|
-
statfs_buf.ffree = @max_files - @total_files
|
|
98
|
-
statfs_buf.favail = @max_files - @total_files
|
|
99
|
-
0
|
|
100
|
-
end
|
|
101
|
-
|
|
102
|
-
def getattr(path, stat_buf)
|
|
103
|
-
entry = find(path)
|
|
104
|
-
return -Errno::ENOENT::Errno unless entry
|
|
105
|
-
|
|
106
|
-
entry.fill_stat(stat_buf)
|
|
107
|
-
0
|
|
108
|
-
end
|
|
109
|
-
|
|
110
|
-
def readdir(path, _offset, _ffi)
|
|
111
|
-
%w[. ..].each { |d| yield(d, nil) }
|
|
112
|
-
dir = find(path)
|
|
113
|
-
dir.entries.each_pair { |k, e| yield(k, e.fill_stat) }
|
|
114
|
-
end
|
|
115
|
-
|
|
116
|
-
def create(path, mode, _ffi)
|
|
117
|
-
dir_entries = find(path.dirname).entries
|
|
118
|
-
now = Time.now
|
|
119
|
-
dir_entries[path.basename.to_s] = File.new(mode, String.new, now, now, now)
|
|
120
|
-
@total_files += 1
|
|
121
|
-
0
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# op[:read] = [:pointer, :size_t, :off_t, FuseFileInfo.by_ref]
|
|
125
|
-
def read(path, len, off, _ffi)
|
|
126
|
-
file = find(path)
|
|
127
|
-
file.atime = Time.now.utc
|
|
128
|
-
FFI::Libfuse::ThreadPool.busy
|
|
129
|
-
sleep 0.5
|
|
130
|
-
file.content[off, len]
|
|
131
|
-
end
|
|
132
|
-
|
|
133
|
-
# write(const char* path, char *buf, size_t size, off_t offset, struct fuse_file_info* fi)
|
|
134
|
-
def write(path, data, offset, _ffi)
|
|
135
|
-
file = find(path)
|
|
136
|
-
content = file.content
|
|
137
|
-
@total_size -= content.size
|
|
138
|
-
content[offset, data.length] = data
|
|
139
|
-
@total_size += content.size
|
|
140
|
-
file.mtime = Time.now.utc
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
def truncate(path, size)
|
|
144
|
-
file = find(path)
|
|
145
|
-
@total_size -= file.content.size
|
|
146
|
-
file.content[size..-1] = ''
|
|
147
|
-
file.mtime = Time.now.utc
|
|
148
|
-
@total_size += file.content.size
|
|
149
|
-
0
|
|
150
|
-
end
|
|
151
|
-
|
|
152
|
-
def unlink(path)
|
|
153
|
-
dir = find(path.dirname)
|
|
154
|
-
deleted = dir.entries.delete(path.basename.to_s)
|
|
155
|
-
@total_files -= 1
|
|
156
|
-
@total_size -= deleted.content.size if deleted.is_a?(File)
|
|
157
|
-
0
|
|
158
|
-
end
|
|
159
|
-
|
|
160
|
-
def mkdir(path, mode)
|
|
161
|
-
entries = find(path.dirname).entries
|
|
162
|
-
now = Time.now
|
|
163
|
-
entries[path.basename.to_s] = Dir.new(mode, {}, now, now, now)
|
|
164
|
-
end
|
|
165
|
-
|
|
166
|
-
def rmdir(path)
|
|
167
|
-
dir = find(path)
|
|
168
|
-
raise Errno::ENOTDIR unless dir.is_a?(Dir)
|
|
169
|
-
raise Errno::ENOTEMPTY unless dir.entries.empty?
|
|
170
|
-
|
|
171
|
-
find(path.dirname).entries.delete(path.basename.to_s)
|
|
172
|
-
0
|
|
173
|
-
end
|
|
174
|
-
|
|
175
|
-
def utimens(path, atime, mtime)
|
|
176
|
-
entry = find(path)
|
|
177
|
-
entry.atime = atime if atime
|
|
178
|
-
entry.mtime = mtime if mtime
|
|
179
|
-
0
|
|
180
|
-
end
|
|
181
|
-
|
|
182
|
-
private
|
|
183
|
-
|
|
184
|
-
def find(path)
|
|
185
|
-
path.root? ? root : root.dig(*path.to_s.split('/')[1..])
|
|
186
|
-
end
|
|
187
|
-
end
|
|
188
|
-
|
|
189
|
-
exit(FFI::Libfuse.fuse_main($0, *ARGV, operations: MemoryFS.new)) if __FILE__ == $0
|
|
13
|
+
exit(main_class.fuse_main(operations: MemoryFS.new)) if __FILE__ == $0
|
data/sample/no_fs.rb
CHANGED
|
@@ -6,13 +6,21 @@ require 'ffi/libfuse'
|
|
|
6
6
|
# An empty file system
|
|
7
7
|
class NoFS
|
|
8
8
|
include FFI::Libfuse::Adapter::Context
|
|
9
|
-
include FFI::Libfuse::Adapter::Fuse3Support
|
|
10
9
|
include FFI::Libfuse::Adapter::Ruby
|
|
10
|
+
include FFI::Libfuse::Adapter::Fuse3Support # must run outside of Adapter::Ruby
|
|
11
11
|
|
|
12
12
|
OPTIONS = { 'log=' => :log }.freeze
|
|
13
13
|
|
|
14
|
-
def fuse_options
|
|
15
|
-
OPTIONS
|
|
14
|
+
def fuse_options(args)
|
|
15
|
+
args.parse!(OPTIONS) do |key:, value:, **|
|
|
16
|
+
case key
|
|
17
|
+
when :log
|
|
18
|
+
@logfile = value
|
|
19
|
+
else
|
|
20
|
+
next :keep
|
|
21
|
+
end
|
|
22
|
+
:handled
|
|
23
|
+
end
|
|
16
24
|
end
|
|
17
25
|
|
|
18
26
|
def fuse_help
|
|
@@ -24,46 +32,37 @@ class NoFS
|
|
|
24
32
|
end
|
|
25
33
|
|
|
26
34
|
def fuse_version
|
|
27
|
-
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def fuse_opt_proc(_data, arg, key, _outargs)
|
|
31
|
-
case key
|
|
32
|
-
when :log
|
|
33
|
-
@logfile = arg[4..]
|
|
34
|
-
return :handled
|
|
35
|
-
end
|
|
36
|
-
:keep
|
|
35
|
+
"NoFS: Version x.y.z. Fuse3Compat=#{fuse3_compat?}"
|
|
37
36
|
end
|
|
38
37
|
|
|
39
|
-
def getattr(
|
|
38
|
+
def getattr(path, stat)
|
|
40
39
|
raise Errno::ENOENT unless path == '/'
|
|
41
40
|
|
|
42
41
|
stat.directory(mode: 0o555)
|
|
43
42
|
end
|
|
44
43
|
|
|
45
|
-
def readdir(
|
|
46
|
-
|
|
44
|
+
def readdir(_path, _offset, _ffi, &block)
|
|
45
|
+
puts "NOFS Readdir: #{block}"
|
|
46
|
+
%w[. ..].each(&block)
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def log
|
|
50
50
|
@log ||= File.open(@logfile || '/tmp/no_fs.out', 'a')
|
|
51
51
|
end
|
|
52
52
|
|
|
53
|
-
def init(
|
|
53
|
+
def init(_conn)
|
|
54
|
+
ctx = FFI::Libfuse::Adapter::Context.fuse_context
|
|
54
55
|
log.puts("NoFS init ctx- #{ctx.inspect}") if ctx
|
|
55
|
-
log.puts("NoFS init conn - #{conn.inspect}") if conn && !conn.null?
|
|
56
|
-
log.puts "NoFS init cfg #{cfg.inspect}" if cfg && !cfg.null?
|
|
57
56
|
warn 'NoFS: DEBUG enabled' if debug?
|
|
58
57
|
log.flush
|
|
59
58
|
'INIT_DATA'
|
|
60
59
|
end
|
|
61
60
|
|
|
62
|
-
def destroy(obj
|
|
61
|
+
def destroy(obj)
|
|
63
62
|
# If the fs is not cleanly unmounted the init data will have been GC'd by the time this is called
|
|
64
63
|
log.puts("NoFS destroy- #{obj.inspect}") if !obj.is_a?(WeakRef) || obj.weakref_alive?
|
|
65
64
|
log.puts "NoFS destroy- pid=#{Process.pid}"
|
|
66
65
|
end
|
|
67
66
|
end
|
|
68
67
|
|
|
69
|
-
exit(FFI::Libfuse.fuse_main($0, *ARGV, operations: NoFS.new, private_data: 'MAIN_DATA')) if __FILE__ == $0
|
|
68
|
+
exit(FFI::Libfuse::Main.fuse_main($0, *ARGV, operations: NoFS.new, private_data: 'MAIN_DATA')) if __FILE__ == $0
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require 'ffi/libfuse'
|
|
5
|
+
require 'ffi/libfuse/filesystem/pass_through_dir'
|
|
6
|
+
|
|
7
|
+
# Pass Through Filesystem - over a base directory
|
|
8
|
+
class PassThroughFS < FFI::Libfuse::Filesystem::PassThroughDir
|
|
9
|
+
def fuse_options(args)
|
|
10
|
+
args.parse!({ 'base_dir=' => :base_dir }) do |key:, value:, **|
|
|
11
|
+
next :keep unless key == :base_dir
|
|
12
|
+
|
|
13
|
+
raise FFI::Libfuse::Error, "#{value} is not a directory" unless Dir.exist?(value)
|
|
14
|
+
|
|
15
|
+
self.base_dir = value
|
|
16
|
+
:handled
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def fuse_help
|
|
21
|
+
'-o base_dir=<dir>'
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def fuse_configure
|
|
25
|
+
self.base_dir ||= Dir.pwd
|
|
26
|
+
warn "Using #{self.base_dir} as base directory for file operations" if debug?
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
exit(FFI::Libfuse.fuse_main(operations: PassThroughFS.new)) if __FILE__ == $0
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ffi-libfuse
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Grant Gardner
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2023-01-07 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: ffi
|
|
@@ -24,6 +24,62 @@ dependencies:
|
|
|
24
24
|
- - "~>"
|
|
25
25
|
- !ruby/object:Gem::Version
|
|
26
26
|
version: '1'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: bundler-audit
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ">="
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '0'
|
|
34
|
+
type: :development
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ">="
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '0'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: minitest
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ">="
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '0'
|
|
48
|
+
type: :development
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ">="
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '0'
|
|
55
|
+
- !ruby/object:Gem::Dependency
|
|
56
|
+
name: minitest-reporters
|
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
|
58
|
+
requirements:
|
|
59
|
+
- - ">="
|
|
60
|
+
- !ruby/object:Gem::Version
|
|
61
|
+
version: '0'
|
|
62
|
+
type: :development
|
|
63
|
+
prerelease: false
|
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
+
requirements:
|
|
66
|
+
- - ">="
|
|
67
|
+
- !ruby/object:Gem::Version
|
|
68
|
+
version: '0'
|
|
69
|
+
- !ruby/object:Gem::Dependency
|
|
70
|
+
name: rake
|
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
|
72
|
+
requirements:
|
|
73
|
+
- - ">="
|
|
74
|
+
- !ruby/object:Gem::Version
|
|
75
|
+
version: '0'
|
|
76
|
+
type: :development
|
|
77
|
+
prerelease: false
|
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
79
|
+
requirements:
|
|
80
|
+
- - ">="
|
|
81
|
+
- !ruby/object:Gem::Version
|
|
82
|
+
version: '0'
|
|
27
83
|
- !ruby/object:Gem::Dependency
|
|
28
84
|
name: rubocop
|
|
29
85
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -74,9 +130,13 @@ extensions: []
|
|
|
74
130
|
extra_rdoc_files: []
|
|
75
131
|
files:
|
|
76
132
|
- ".yardopts"
|
|
133
|
+
- CHANGELOG.md
|
|
134
|
+
- LICENSE
|
|
77
135
|
- README.md
|
|
78
136
|
- lib/ffi/accessors.rb
|
|
137
|
+
- lib/ffi/boolean_int.rb
|
|
79
138
|
- lib/ffi/devt.rb
|
|
139
|
+
- lib/ffi/encoding.rb
|
|
80
140
|
- lib/ffi/flock.rb
|
|
81
141
|
- lib/ffi/gnu_extensions.rb
|
|
82
142
|
- lib/ffi/libfuse.rb
|
|
@@ -90,8 +150,18 @@ files:
|
|
|
90
150
|
- lib/ffi/libfuse/adapter/pathname.rb
|
|
91
151
|
- lib/ffi/libfuse/adapter/ruby.rb
|
|
92
152
|
- lib/ffi/libfuse/adapter/safe.rb
|
|
93
|
-
- lib/ffi/libfuse/adapter/thread_local_context.rb
|
|
94
153
|
- lib/ffi/libfuse/callbacks.rb
|
|
154
|
+
- lib/ffi/libfuse/filesystem.rb
|
|
155
|
+
- lib/ffi/libfuse/filesystem/accounting.rb
|
|
156
|
+
- lib/ffi/libfuse/filesystem/mapped_dir.rb
|
|
157
|
+
- lib/ffi/libfuse/filesystem/mapped_files.rb
|
|
158
|
+
- lib/ffi/libfuse/filesystem/pass_through_dir.rb
|
|
159
|
+
- lib/ffi/libfuse/filesystem/pass_through_file.rb
|
|
160
|
+
- lib/ffi/libfuse/filesystem/utils.rb
|
|
161
|
+
- lib/ffi/libfuse/filesystem/virtual_dir.rb
|
|
162
|
+
- lib/ffi/libfuse/filesystem/virtual_file.rb
|
|
163
|
+
- lib/ffi/libfuse/filesystem/virtual_fs.rb
|
|
164
|
+
- lib/ffi/libfuse/filesystem/virtual_node.rb
|
|
95
165
|
- lib/ffi/libfuse/fuse2.rb
|
|
96
166
|
- lib/ffi/libfuse/fuse3.rb
|
|
97
167
|
- lib/ffi/libfuse/fuse_args.rb
|
|
@@ -108,10 +178,10 @@ files:
|
|
|
108
178
|
- lib/ffi/libfuse/fuse_opt.rb
|
|
109
179
|
- lib/ffi/libfuse/fuse_poll_handle.rb
|
|
110
180
|
- lib/ffi/libfuse/fuse_version.rb
|
|
181
|
+
- lib/ffi/libfuse/gem_version.rb
|
|
111
182
|
- lib/ffi/libfuse/job_pool.rb
|
|
112
183
|
- lib/ffi/libfuse/main.rb
|
|
113
|
-
- lib/ffi/libfuse/
|
|
114
|
-
- lib/ffi/libfuse/test/operations.rb
|
|
184
|
+
- lib/ffi/libfuse/test_helper.rb
|
|
115
185
|
- lib/ffi/libfuse/thread_pool.rb
|
|
116
186
|
- lib/ffi/libfuse/version.rb
|
|
117
187
|
- lib/ffi/ruby_object.rb
|
|
@@ -122,13 +192,16 @@ files:
|
|
|
122
192
|
- lib/ffi/stat_vfs.rb
|
|
123
193
|
- lib/ffi/struct_array.rb
|
|
124
194
|
- lib/ffi/struct_wrapper.rb
|
|
195
|
+
- sample/hello_fs.rb
|
|
125
196
|
- sample/memory_fs.rb
|
|
126
197
|
- sample/no_fs.rb
|
|
198
|
+
- sample/pass_through_fs.rb
|
|
127
199
|
homepage:
|
|
128
200
|
licenses:
|
|
129
201
|
- MIT
|
|
130
202
|
metadata:
|
|
131
|
-
source_code_uri:
|
|
203
|
+
source_code_uri: https://github.com/lwoggardner/ffi-libfuse
|
|
204
|
+
rubygems_mfa_required: 'true'
|
|
132
205
|
post_install_message:
|
|
133
206
|
rdoc_options: []
|
|
134
207
|
require_paths:
|
|
@@ -137,14 +210,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
137
210
|
requirements:
|
|
138
211
|
- - ">="
|
|
139
212
|
- !ruby/object:Gem::Version
|
|
140
|
-
version: 2.
|
|
213
|
+
version: 2.7.0
|
|
141
214
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
142
215
|
requirements:
|
|
143
|
-
- - "
|
|
216
|
+
- - ">="
|
|
144
217
|
- !ruby/object:Gem::Version
|
|
145
|
-
version:
|
|
218
|
+
version: '0'
|
|
146
219
|
requirements: []
|
|
147
|
-
rubygems_version: 3.1.
|
|
220
|
+
rubygems_version: 3.1.6
|
|
148
221
|
signing_key:
|
|
149
222
|
specification_version: 4
|
|
150
223
|
summary: FFI Bindings for Libfuse
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../fuse_context'
|
|
4
|
-
|
|
5
|
-
module FFI
|
|
6
|
-
module Libfuse
|
|
7
|
-
module Adapter
|
|
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
|
|
10
|
-
module ThreadLocalContext
|
|
11
|
-
# @!visibility private
|
|
12
|
-
def fuse_wrappers(*wrappers)
|
|
13
|
-
wrappers.unshift(
|
|
14
|
-
{
|
|
15
|
-
wrapper: proc { |_fm, *args, **_, &b| self.class.thread_local_context(*args, &b) },
|
|
16
|
-
excludes: %i[destroy]
|
|
17
|
-
}
|
|
18
|
-
)
|
|
19
|
-
return wrappers unless defined?(super)
|
|
20
|
-
|
|
21
|
-
super(*wrappers)
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
module_function
|
|
25
|
-
|
|
26
|
-
# Stores {FuseContext} in thread local variable :fuse_context before yielding
|
|
27
|
-
def thread_local_context(*args)
|
|
28
|
-
Thread.current[:fuse_context] = FuseContext.get
|
|
29
|
-
yield(*args)
|
|
30
|
-
ensure
|
|
31
|
-
Thread.current[:fuse_context] = nil
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,56 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
require_relative '../fuse_operations'
|
|
4
|
-
|
|
5
|
-
module FFI
|
|
6
|
-
module Libfuse
|
|
7
|
-
module Test
|
|
8
|
-
# A FuseOperations that holds callback procs in a Hash rather than FFI objects and allows for direct invocation of
|
|
9
|
-
# callback methods
|
|
10
|
-
# @!parse FuseOperations
|
|
11
|
-
class Operations
|
|
12
|
-
include FuseCallbacks
|
|
13
|
-
|
|
14
|
-
def initialize(delegate:, fuse_wrappers: [])
|
|
15
|
-
@callbacks = {}
|
|
16
|
-
initialize_callbacks(delegate: delegate, wrappers: fuse_wrappers)
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
# @!visibility private
|
|
20
|
-
def [](member)
|
|
21
|
-
@callbacks[member]
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
# @!visibility private
|
|
25
|
-
def []=(member, value)
|
|
26
|
-
@callbacks[member] = value
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
# @!visibility private
|
|
30
|
-
def members
|
|
31
|
-
FuseOperations.members
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
private
|
|
35
|
-
|
|
36
|
-
# Allow the fuse operations to be called directly - useful for testing
|
|
37
|
-
# @todo some fancy wrapper to convert tests using Fuse2 signatures when Fuse3 is the loaded library
|
|
38
|
-
# and vice-versa
|
|
39
|
-
def method_missing(method, *args)
|
|
40
|
-
callback = callback?(method) && self[method]
|
|
41
|
-
return super unless callback
|
|
42
|
-
|
|
43
|
-
callback.call(*args)
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
def respond_to_missing?(method, _private = false)
|
|
47
|
-
self[method] && callback?(method)
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def callback?(method)
|
|
51
|
-
callback_members.include?(method)
|
|
52
|
-
end
|
|
53
|
-
end
|
|
54
|
-
end
|
|
55
|
-
end
|
|
56
|
-
end
|
data/lib/ffi/libfuse/test.rb
DELETED