ffi-libfuse 0.3.4 → 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 +22 -0
- 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 +2 -9
- 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 +6 -3
- data/lib/ffi/libfuse/fuse_buffer.rb +0 -257
@@ -1,257 +0,0 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
|
3
|
-
require_relative 'fuse_version'
|
4
|
-
|
5
|
-
module FFI
|
6
|
-
# Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
|
7
|
-
module Libfuse
|
8
|
-
bitmask :fuse_buf_flags, [:is_fd, 1, :fd_seek, :fd_retry]
|
9
|
-
bitmask :fuse_buf_copy_flags, [:no_splice, 1, :force_splice, 2, :splice_move, 4, :splice_nonblock, 8]
|
10
|
-
|
11
|
-
#
|
12
|
-
# Single data buffer
|
13
|
-
#
|
14
|
-
# Generic data buffer for I/O, extended attributes, etc...Data may be supplied as a memory pointer or as a file
|
15
|
-
# descriptor
|
16
|
-
#
|
17
|
-
class FuseBuf < FFI::Struct
|
18
|
-
layout(
|
19
|
-
size: :size_t, # Size of data in bytes
|
20
|
-
flags: :fuse_buf_flags, # Buffer flags
|
21
|
-
mem: :pointer, # Memory pointer - used if :is_fd flag is not set
|
22
|
-
fd: :int, # File descriptor - used if :is_fd is set
|
23
|
-
pos: :off_t # File position - used if :fd_seek flag is set.
|
24
|
-
)
|
25
|
-
|
26
|
-
# rubocop:disable Naming/MethodParameterName
|
27
|
-
|
28
|
-
# @!attribute [r] mem
|
29
|
-
# @return [FFI::Pointer] the memory in the buffer
|
30
|
-
def mem
|
31
|
-
self[:mem]
|
32
|
-
end
|
33
|
-
alias memory mem
|
34
|
-
|
35
|
-
# @!attribute [r] fd
|
36
|
-
# @return [Integer] the file descriptor number
|
37
|
-
def fd
|
38
|
-
self[:fd]
|
39
|
-
end
|
40
|
-
alias file_descriptor fd
|
41
|
-
|
42
|
-
# @return [Boolean] true if this a memory buffer
|
43
|
-
def mem?
|
44
|
-
!fd?
|
45
|
-
end
|
46
|
-
|
47
|
-
# @return [Boolean] true if this is a file descriptor buffer
|
48
|
-
def fd?
|
49
|
-
self[:flags].include?(:is_fd)
|
50
|
-
end
|
51
|
-
alias file_descriptor? fd?
|
52
|
-
|
53
|
-
# Resize mem to smaller than initially allocated
|
54
|
-
# @param [Integer] new_size
|
55
|
-
# @return [void]
|
56
|
-
def resize(new_size)
|
57
|
-
self[:size] = new_size
|
58
|
-
end
|
59
|
-
|
60
|
-
# @overload fill(size:, mem:, auto_release)
|
61
|
-
# Fill as a Memory buffer
|
62
|
-
# @param [Integer] size Size of data in bytes
|
63
|
-
# @param [FFI::Pointer] mem Memory pointer allocated to size if required
|
64
|
-
# @param [Boolean] autorelease
|
65
|
-
#
|
66
|
-
# @overload fill(fd:, fd_retry:, pos:)
|
67
|
-
# Fill as a FileDescriptor buffer
|
68
|
-
# @param [Integer] fd File descriptor
|
69
|
-
# @param [Boolean] fd_retry
|
70
|
-
# Retry operations on file descriptor
|
71
|
-
#
|
72
|
-
# If this flag is set then retry operation on file descriptor until .size bytes have been copied or an error
|
73
|
-
# or EOF is detected.
|
74
|
-
#
|
75
|
-
# @param [Integer] pos
|
76
|
-
# If > 0 then used to seek to the given offset before performing operation on file descriptor.
|
77
|
-
# @return [self]
|
78
|
-
def fill(mem: FFI::Pointer::NULL, size: mem.null? ? 0 : mem.size, fd: -1, fd_retry: false, pos: 0)
|
79
|
-
mem = FFI::MemoryPointer.new(:char, size, true) if fd == -1 && mem.null? && size.positive?
|
80
|
-
mem.autorelease = to_ptr.autorelease? unless mem.null?
|
81
|
-
|
82
|
-
self[:size] = size
|
83
|
-
self[:mem] = mem
|
84
|
-
self[:fd] = fd
|
85
|
-
flags = []
|
86
|
-
flags << :is_fd if fd != -1
|
87
|
-
flags << :fd_seek if pos.positive?
|
88
|
-
flags << :fd_retry if fd_retry
|
89
|
-
self[:flags] = flags
|
90
|
-
self[:pos] = pos
|
91
|
-
self
|
92
|
-
end
|
93
|
-
end
|
94
|
-
# rubocop:enable Naming/MethodParameterName
|
95
|
-
|
96
|
-
#
|
97
|
-
# Data buffer vector
|
98
|
-
#
|
99
|
-
# An array of data buffers, each containing a memory pointer or a file descriptor.
|
100
|
-
#
|
101
|
-
# Allocate dynamically to add more than one buffer.
|
102
|
-
#
|
103
|
-
class FuseBufVec < FFI::Struct
|
104
|
-
layout(
|
105
|
-
count: :size_t,
|
106
|
-
idx: :size_t,
|
107
|
-
off: :size_t,
|
108
|
-
# but is treated as a variable length array of FuseBuf at size +1 following the struct.
|
109
|
-
buf: [FuseBuf, 1] # struct fuse_buf[1]
|
110
|
-
)
|
111
|
-
|
112
|
-
# @!attribute [r] count
|
113
|
-
# @return [Integer] the number of buffers in the array
|
114
|
-
def count
|
115
|
-
self[:count]
|
116
|
-
end
|
117
|
-
|
118
|
-
# @!attribute [r] index
|
119
|
-
# @return [Integer] index of current buffer within the array
|
120
|
-
def index
|
121
|
-
self[:idx]
|
122
|
-
end
|
123
|
-
alias idx index
|
124
|
-
|
125
|
-
# @!attribute [r] offset
|
126
|
-
# @return [Integer] current offset within the current buffer
|
127
|
-
def offset
|
128
|
-
self[:off]
|
129
|
-
end
|
130
|
-
alias off offset
|
131
|
-
|
132
|
-
# @!attribute [r] buffers
|
133
|
-
# @return [Array<FuseBuf>] array of buffers
|
134
|
-
def buffers
|
135
|
-
@buffers ||= Array.new(count) do |i|
|
136
|
-
next self[:buf].first if i.zero?
|
137
|
-
|
138
|
-
FuseBuf.new(self[:buf].to_ptr + (i * FuseBuf.size))
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
# @!attribute [r] current
|
143
|
-
# @return [FuseBuf] the current buffer
|
144
|
-
def current
|
145
|
-
return self[:buf].first if index.zero?
|
146
|
-
|
147
|
-
FuseBuf.new(self[:buf].to_ptr + (index * FuseBuf.size))
|
148
|
-
end
|
149
|
-
|
150
|
-
# Create and initialise a new FuseBufVec
|
151
|
-
# @param [Boolean] autorelease should the struct be freed on GC (default NO!!!)
|
152
|
-
# @param [Hash] buf_options options for configuring the initial buffer. See {#init}
|
153
|
-
# @yield(buf,index)
|
154
|
-
# @yieldparam [FuseBuf] buf
|
155
|
-
# @yieldparam [Integer] index
|
156
|
-
# @yieldreturn [void]
|
157
|
-
# @return [FuseBufVec]
|
158
|
-
def self.init(autorelease: true, count: 1, **buf_options)
|
159
|
-
bufvec_ptr = FFI::MemoryPointer.new(:uchar, FuseBufVec.size + (FuseBuf.size * (count - 1)), true)
|
160
|
-
bufvec_ptr.autorelease = autorelease
|
161
|
-
bufvec = new(bufvec_ptr)
|
162
|
-
bufvec[:count] = count
|
163
|
-
bufvec.init(**buf_options)
|
164
|
-
|
165
|
-
buffers.each_with_index { |b, i| yield i, b } if block_given?
|
166
|
-
bufvec
|
167
|
-
end
|
168
|
-
|
169
|
-
# Set and initialise a specific buffer
|
170
|
-
#
|
171
|
-
# See fuse_common.h FUSE_BUFVEC_INIT macro
|
172
|
-
# @param [Integer] index the index of the buffer
|
173
|
-
# @param [Hash<Symbol,Object>] buf_options see {FuseBuf#fill}
|
174
|
-
# @return [FuseBuf] the initial buffer
|
175
|
-
def init(index: 0, **buf_options)
|
176
|
-
self[:idx] = index
|
177
|
-
self[:off] = 0
|
178
|
-
current.fill(**buf_options) unless buf_options.empty?
|
179
|
-
self
|
180
|
-
end
|
181
|
-
|
182
|
-
# Would pref this to be called #size but clashes with FFI::Struct, might need StructWrapper
|
183
|
-
# @return [Integer] total size of data in a fuse buffer vector
|
184
|
-
def buf_size
|
185
|
-
Libfuse.fuse_buf_size(self)
|
186
|
-
end
|
187
|
-
|
188
|
-
# Copy data from one buffer vector to another
|
189
|
-
# @param [FuseBufVec] dst Destination buffer vector
|
190
|
-
# @param [Array<Symbol>] flags Buffer copy flags
|
191
|
-
# - :no_splice
|
192
|
-
# Don't use splice(2)
|
193
|
-
#
|
194
|
-
# Always fall back to using read and write instead of splice(2) to copy data from one file descriptor to
|
195
|
-
# another.
|
196
|
-
#
|
197
|
-
# If this flag is not set, then only fall back if splice is unavailable.
|
198
|
-
#
|
199
|
-
# - :force_splice
|
200
|
-
#
|
201
|
-
# Always use splice(2) to copy data from one file descriptor to another. If splice is not available, return
|
202
|
-
# -EINVAL.
|
203
|
-
#
|
204
|
-
# - :splice_move
|
205
|
-
#
|
206
|
-
# Try to move data with splice.
|
207
|
-
#
|
208
|
-
# If splice is used, try to move pages from the source to the destination instead of copying. See
|
209
|
-
# documentation of SPLICE_F_MOVE in splice(2) man page.
|
210
|
-
#
|
211
|
-
# - :splice_nonblock
|
212
|
-
#
|
213
|
-
# Don't block on the pipe when copying data with splice
|
214
|
-
#
|
215
|
-
# Makes the operations on the pipe non-blocking (if the pipe is full or empty). See SPLICE_F_NONBLOCK in
|
216
|
-
# the splice(2) man page.
|
217
|
-
#
|
218
|
-
# @return [Integer] actual number of bytes copied or -errno on error
|
219
|
-
#
|
220
|
-
def copy_to(dst, *flags)
|
221
|
-
Libfuse.fuse_buf_copy(dst, self, flags)
|
222
|
-
end
|
223
|
-
|
224
|
-
# Copy our data direct to file descriptor
|
225
|
-
# @param [Integer] fileno a file descriptor
|
226
|
-
# @param [Integer] offset
|
227
|
-
# @param [Array<Symbol>] flags - see {copy_to}
|
228
|
-
# @return [Integer] number of bytes copied
|
229
|
-
def copy_to_fd(fileno, offset = 0, *flags)
|
230
|
-
dst = self.class.init(size: buf_size, fd: fileno, pos: offset)
|
231
|
-
copy_to(dst, *flags)
|
232
|
-
end
|
233
|
-
|
234
|
-
# Copy to string via a temporary buffer
|
235
|
-
# @param [Array<Symbol>] flags - see {copy_to}
|
236
|
-
# @return [String] the extracted data
|
237
|
-
def copy_to_str(*flags)
|
238
|
-
dst = FuseBufVec.init(size: buf_size)
|
239
|
-
copied = copy_to(dst, *flags)
|
240
|
-
dst.current.memory.read_string(copied)
|
241
|
-
end
|
242
|
-
|
243
|
-
def copy_from(src, *flags)
|
244
|
-
Libfuse.fuse_buf_copy(self, src, flags)
|
245
|
-
end
|
246
|
-
end
|
247
|
-
|
248
|
-
attach_function :fuse_buf_size, [FuseBufVec.by_ref], :size_t
|
249
|
-
attach_function :fuse_buf_copy, [FuseBufVec.by_ref, FuseBufVec.by_ref, :fuse_buf_copy_flags], :ssize_t
|
250
|
-
|
251
|
-
class << self
|
252
|
-
# @!visibility private
|
253
|
-
# @!method fuse_buf_size
|
254
|
-
# @!method fuse_buf_copy
|
255
|
-
end
|
256
|
-
end
|
257
|
-
end
|