ffi-libfuse 0.3.4 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|