ffi-libfuse 0.0.1.pre
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.yardopts +1 -0
- data/README.md +100 -0
- data/lib/ffi/accessors.rb +145 -0
- data/lib/ffi/devt.rb +30 -0
- data/lib/ffi/flock.rb +47 -0
- data/lib/ffi/gnu_extensions.rb +115 -0
- data/lib/ffi/libfuse/ackbar.rb +112 -0
- data/lib/ffi/libfuse/adapter/context.rb +37 -0
- data/lib/ffi/libfuse/adapter/debug.rb +89 -0
- data/lib/ffi/libfuse/adapter/fuse2_compat.rb +91 -0
- data/lib/ffi/libfuse/adapter/fuse3_support.rb +87 -0
- data/lib/ffi/libfuse/adapter/interrupt.rb +37 -0
- data/lib/ffi/libfuse/adapter/pathname.rb +23 -0
- data/lib/ffi/libfuse/adapter/ruby.rb +334 -0
- data/lib/ffi/libfuse/adapter/safe.rb +58 -0
- data/lib/ffi/libfuse/adapter/thread_local_context.rb +36 -0
- data/lib/ffi/libfuse/adapter.rb +79 -0
- data/lib/ffi/libfuse/callbacks.rb +61 -0
- data/lib/ffi/libfuse/fuse2.rb +159 -0
- data/lib/ffi/libfuse/fuse3.rb +162 -0
- data/lib/ffi/libfuse/fuse_args.rb +166 -0
- data/lib/ffi/libfuse/fuse_buffer.rb +155 -0
- data/lib/ffi/libfuse/fuse_callbacks.rb +48 -0
- data/lib/ffi/libfuse/fuse_cmdline_opts.rb +44 -0
- data/lib/ffi/libfuse/fuse_common.rb +249 -0
- data/lib/ffi/libfuse/fuse_config.rb +205 -0
- data/lib/ffi/libfuse/fuse_conn_info.rb +211 -0
- data/lib/ffi/libfuse/fuse_context.rb +79 -0
- data/lib/ffi/libfuse/fuse_file_info.rb +100 -0
- data/lib/ffi/libfuse/fuse_loop_config.rb +43 -0
- data/lib/ffi/libfuse/fuse_operations.rb +870 -0
- data/lib/ffi/libfuse/fuse_opt.rb +54 -0
- data/lib/ffi/libfuse/fuse_poll_handle.rb +59 -0
- data/lib/ffi/libfuse/fuse_version.rb +43 -0
- data/lib/ffi/libfuse/job_pool.rb +53 -0
- data/lib/ffi/libfuse/main.rb +200 -0
- data/lib/ffi/libfuse/test/operations.rb +56 -0
- data/lib/ffi/libfuse/test.rb +3 -0
- data/lib/ffi/libfuse/thread_pool.rb +147 -0
- data/lib/ffi/libfuse/version.rb +8 -0
- data/lib/ffi/libfuse.rb +24 -0
- data/lib/ffi/ruby_object.rb +95 -0
- data/lib/ffi/stat/constants.rb +29 -0
- data/lib/ffi/stat/native.rb +50 -0
- data/lib/ffi/stat/time_spec.rb +137 -0
- data/lib/ffi/stat.rb +96 -0
- data/lib/ffi/stat_vfs.rb +81 -0
- data/lib/ffi/struct_array.rb +39 -0
- data/lib/ffi/struct_wrapper.rb +100 -0
- data/sample/memory_fs.rb +189 -0
- data/sample/no_fs.rb +69 -0
- metadata +165 -0
@@ -0,0 +1,100 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'fuse_version'
|
4
|
+
require_relative '../struct_wrapper'
|
5
|
+
require_relative '../ruby_object'
|
6
|
+
|
7
|
+
module FFI
|
8
|
+
# Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
|
9
|
+
module Libfuse
|
10
|
+
bit_flags = %i[direct_io keep_cache flush nonseekable flock_release cache_readdir]
|
11
|
+
bit_flags.unshift(:writepage) if FUSE_MAJOR_VERSION >= 3
|
12
|
+
bitmask :file_info_flags, bit_flags
|
13
|
+
|
14
|
+
# Native struct layout
|
15
|
+
# @!visibility private
|
16
|
+
class NativeFuseFileInfo < FFI::Struct
|
17
|
+
# NOTE: cache_readdir added in Fuse3, but always available for compatibility
|
18
|
+
if FUSE_MAJOR_VERSION == 2
|
19
|
+
layout(
|
20
|
+
flags: :int,
|
21
|
+
fh_old: :ulong, # deprecated
|
22
|
+
writepage: :int,
|
23
|
+
bit_flags: :file_info_flags,
|
24
|
+
fh: RubyObject.by_object_id(:uint64_t),
|
25
|
+
lock_owner: :uint64_t
|
26
|
+
)
|
27
|
+
else
|
28
|
+
layout(
|
29
|
+
flags: :int,
|
30
|
+
bit_flags: :file_info_flags,
|
31
|
+
padding: :uint,
|
32
|
+
fh: RubyObject.by_object_id(:uint64_t),
|
33
|
+
lock_owner: :uint64_t,
|
34
|
+
poll_events: :uint32_t
|
35
|
+
)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# FuseFileInfo
|
40
|
+
class FuseFileInfo
|
41
|
+
# This uses a struct wrapper as references can be null
|
42
|
+
include(StructWrapper)
|
43
|
+
native_struct(NativeFuseFileInfo)
|
44
|
+
|
45
|
+
if FUSE_MAJOR_VERSION == 2
|
46
|
+
ffi_attr_reader(:writepage) { |v| v != 0 }
|
47
|
+
else
|
48
|
+
ffi_bitflag_reader(:bit_flags, :writepage)
|
49
|
+
end
|
50
|
+
|
51
|
+
# @!attribute [r] flags
|
52
|
+
# @return [Integer] Open flags. Available in open() and release()
|
53
|
+
# @see Fcntl
|
54
|
+
ffi_attr_reader :flags
|
55
|
+
|
56
|
+
# @!attribute [r] lock_owner
|
57
|
+
# @return [Integer] Lock owner id. Available in locking operations and flush
|
58
|
+
ffi_attr_reader :lock_owner
|
59
|
+
|
60
|
+
# @!attribute [rw] fh
|
61
|
+
# Note this fh is weakly referenced by kernel fuse, make sure a reference is kept to prevent it from being
|
62
|
+
# garbage collected until release()
|
63
|
+
# @return [Object] File handle. May be filled in by filesystem in open()
|
64
|
+
ffi_attr_accessor(:fh)
|
65
|
+
|
66
|
+
# @!attribute [r] writepage
|
67
|
+
# In case of a write operation indicates if this was caused by a delayed write from the page cache. If so, then
|
68
|
+
# the context's pid, uid, and gid fields will not be valid, and the *fh* value may not match the *fh* value that
|
69
|
+
# would have been sent with the corresponding individual write requests if write caching had been disabled.
|
70
|
+
# @return [Boolean] indicates if this was caused by a writepage
|
71
|
+
|
72
|
+
# @!attribute [r] flush
|
73
|
+
# Set in flush operation, also maybe set in highlevel lock operation and lowlevel release operation.
|
74
|
+
# @return [Boolean] Indicates a flush operation.
|
75
|
+
ffi_bitflag_reader(:bit_flags, :flush)
|
76
|
+
|
77
|
+
# @!attribute [rw] direct_io
|
78
|
+
# @return [Boolean] Can be filled in by open, to use direct I/O on this file.
|
79
|
+
|
80
|
+
# @!attribute [rw] keep_cache
|
81
|
+
# @return [Boolean] Can be filled in by open, to indicate, that cached file data need not be invalidated.
|
82
|
+
|
83
|
+
# @!attribute [rw] nonseekable
|
84
|
+
# @return [Boolean] Can be filled in by open, to indicate that the file is not seekable
|
85
|
+
# @since Fuse2.8
|
86
|
+
|
87
|
+
# @!attribute [rw] flock_release
|
88
|
+
# If set, lock_owner shall contain a valid value.
|
89
|
+
# May only be set in ->release(). Introduced in version 2.9
|
90
|
+
# @return [Boolean] Indicates that flock locks for this file should be released.
|
91
|
+
|
92
|
+
# @!attribute [rw] cache_readdir
|
93
|
+
# Can be filled in by opendir.
|
94
|
+
# @return [Boolean] signals the kernel to enable caching of entries returned by readdir()
|
95
|
+
# @since Fuse3
|
96
|
+
|
97
|
+
ffi_bitflag_accessor(:bit_flags, :direct_io, :keep_cache, :nonseekable, :flock_release, :cache_readdir)
|
98
|
+
end
|
99
|
+
end
|
100
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative '../accessors'
|
4
|
+
|
5
|
+
module FFI
|
6
|
+
module Libfuse
|
7
|
+
# struct fuse_loop_config {
|
8
|
+
# int clone_fd;
|
9
|
+
# unsigned int max_idle_threads;
|
10
|
+
# };
|
11
|
+
class FuseLoopConfig < FFI::Struct
|
12
|
+
include(FFI::Accessors)
|
13
|
+
|
14
|
+
layout(
|
15
|
+
clone_fd: :int,
|
16
|
+
max_idle: :int
|
17
|
+
)
|
18
|
+
|
19
|
+
# @!attribute [rw] clone_fd
|
20
|
+
# whether to use separate device fds for each thread (may increase performance)
|
21
|
+
# Unused by ffi-libfuse as we do not call fuse_loop_mt
|
22
|
+
# @return [Boolean]
|
23
|
+
ffi_attr_reader(:clone_fd) do |v|
|
24
|
+
v != 0
|
25
|
+
end
|
26
|
+
|
27
|
+
ffi_attr_writer(:clone_fd) do |v|
|
28
|
+
v ? 1 : 0
|
29
|
+
end
|
30
|
+
|
31
|
+
# @!attribute [rw] max_idle_threads
|
32
|
+
# The maximum number of available worker threads before they start to get deleted when they become idle. If not
|
33
|
+
# specified, the default is 10.
|
34
|
+
#
|
35
|
+
# Adjusting this has performance implications; a very small number of threads in the pool will cause a lot of
|
36
|
+
# thread creation and deletion overhead and performance may suffer. When set to 0, a new thread will be created
|
37
|
+
# to service every operation.
|
38
|
+
#
|
39
|
+
# @return [Integer] the maximum number of threads to leave idle
|
40
|
+
ffi_attr_accessor(:max_idle)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,870 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'fuse_version'
|
4
|
+
require_relative '../ruby_object'
|
5
|
+
require_relative 'fuse_conn_info'
|
6
|
+
require_relative 'fuse_buffer'
|
7
|
+
require_relative 'fuse_context'
|
8
|
+
require_relative 'fuse_file_info'
|
9
|
+
require_relative 'fuse_poll_handle'
|
10
|
+
require_relative '../stat_vfs'
|
11
|
+
require_relative '../flock'
|
12
|
+
require_relative 'thread_pool'
|
13
|
+
require_relative '../stat'
|
14
|
+
require_relative '../struct_array'
|
15
|
+
require_relative 'fuse_callbacks'
|
16
|
+
|
17
|
+
module FFI
|
18
|
+
# Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
|
19
|
+
module Libfuse
|
20
|
+
# typedef int (*fuse_fill_dir_t) (void *buf, const char *name, const struct stat *stbuf, off_t off);
|
21
|
+
fill_dir_t_args = [:pointer, :string, Stat.by_ref, :off_t]
|
22
|
+
if FUSE_MAJOR_VERSION > 2
|
23
|
+
enum :fuse_readdir_flags, [:fuse_readdir_plus, (1 << 0)]
|
24
|
+
enum :fuse_fill_dir_flags, [:fuse_fill_dir_plus, (1 << 1)]
|
25
|
+
fill_dir_t_args << :fuse_fill_dir_flags
|
26
|
+
end
|
27
|
+
|
28
|
+
bitmask :lock_op, [:lock_sh, 0, :lock_ex, 2, :lock_nb, 4, :lock_un, 8]
|
29
|
+
bitmask :falloc_mode, %i[keep_size punch_hole no_hide_stale collapse_range zero_range insert_range unshare_range]
|
30
|
+
bitmask :flags_mask, %i[nullpath_ok nopath utime_omit_ok] if FUSE_MAJOR_VERSION < 3
|
31
|
+
enum :xattr, [:xattr_create, 1, :xattr_replace]
|
32
|
+
callback :fill_dir_t, fill_dir_t_args, :int
|
33
|
+
|
34
|
+
# The file system operations as specified in libfuse.
|
35
|
+
#
|
36
|
+
# All Callback and Configuration methods are optional, but some are essential for a useful filesystem
|
37
|
+
# e.g. {getattr},{readdir}
|
38
|
+
#
|
39
|
+
# Almost all callback operations take a path which can be of any length and will return 0 for success, or raise a
|
40
|
+
# {::SystemCallError} on failure
|
41
|
+
#
|
42
|
+
class FuseOperations < FFI::Struct
|
43
|
+
include FuseCallbacks
|
44
|
+
|
45
|
+
# Container to dynamically build up the operations layout which is dependent on the loaded libfuse version
|
46
|
+
op = {}
|
47
|
+
|
48
|
+
# @!group FUSE Callbacks
|
49
|
+
|
50
|
+
# @!method getattr(path,stat,fuse_file_info = nil)
|
51
|
+
# @abstract
|
52
|
+
# Get file attributes.
|
53
|
+
#
|
54
|
+
# Similar to stat(). The 'st_dev' and 'st_blksize' fields are ignored. The 'st_ino' field is ignored
|
55
|
+
# except if the 'use_ino' mount option is given.
|
56
|
+
#
|
57
|
+
# @param [String] path
|
58
|
+
# @param [Stat] stat to be filled with result information
|
59
|
+
# @param [FuseFileInfo] fuse_file_info
|
60
|
+
# will always be nil if the file is not currently open, but may also be nil if the file is open.
|
61
|
+
# @return [Integer] 0 for success or -ve Errno value
|
62
|
+
|
63
|
+
# int (*getattr) (const char *, struct stat *);
|
64
|
+
op[:getattr] = [Stat.by_ref]
|
65
|
+
op[:getattr] << FuseFileInfo.by_ref if FUSE_MAJOR_VERSION >= 3
|
66
|
+
|
67
|
+
# @!method readlink(path, target_buffer, buffer_size)
|
68
|
+
# @abstract
|
69
|
+
# Resolve the target of a symbolic link
|
70
|
+
#
|
71
|
+
# @param [String] path
|
72
|
+
# @param [FFI::Pointer] target_buffer
|
73
|
+
#
|
74
|
+
# The buffer should be filled with a null terminated string. The buffer size argument includes the space for
|
75
|
+
# the terminating null character. If the linkname is too long to fit in the buffer, it should be truncated.
|
76
|
+
#
|
77
|
+
# @param [Integer] buffer_size
|
78
|
+
#
|
79
|
+
# @return [Integer] 0 for success.
|
80
|
+
|
81
|
+
# int (*readlink) (const char *, char *, size_t);
|
82
|
+
op[:readlink] = %i[pointer size_t]
|
83
|
+
|
84
|
+
# @!method getdir
|
85
|
+
# @deprecated use {readdir} instead
|
86
|
+
|
87
|
+
# int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
|
88
|
+
op[:getdir] = %i[pointer pointer] if FUSE_MAJOR_VERSION < 3
|
89
|
+
|
90
|
+
# @!method mknod(path,mode,dev)
|
91
|
+
# Create a file node
|
92
|
+
#
|
93
|
+
# @param [String] path
|
94
|
+
# @param [Integer] mode
|
95
|
+
# @param [Integer] dev
|
96
|
+
# This is called for creation of all non-directory, non-symlink nodes. If the filesystem defines a create()
|
97
|
+
# method, then for regular files that will be called instead.
|
98
|
+
#
|
99
|
+
# @return [Integer] 0 for success or -ve errno
|
100
|
+
|
101
|
+
# int (*mknod) (const char *, mode_t, dev_t);
|
102
|
+
op[:mknod] = %i[mode_t dev_t]
|
103
|
+
|
104
|
+
# @!method mkdir(path,mode)
|
105
|
+
# @abstract
|
106
|
+
# Create a directory
|
107
|
+
#
|
108
|
+
# @param [String] path
|
109
|
+
# @param [Integer] mode
|
110
|
+
# Note that the mode argument may not have the type specification bits set, i.e. S_ISDIR(mode) can be false. To
|
111
|
+
# obtain the correct directory type bits use mode | {FFI::Stat::S_IFDIR}
|
112
|
+
#
|
113
|
+
# @return [Integer] 0 for success or -ve errno
|
114
|
+
|
115
|
+
# int (*mkdir) (const char *, mode_t);
|
116
|
+
op[:mkdir] = [:mode_t]
|
117
|
+
|
118
|
+
# @!method unlink(path)
|
119
|
+
# @abstract
|
120
|
+
# Remove a file
|
121
|
+
# @param [String] path
|
122
|
+
#
|
123
|
+
# @return [Integer] 0 for success or -ve errno
|
124
|
+
|
125
|
+
# int (*unlink) (const char *);
|
126
|
+
op[:unlink] = []
|
127
|
+
|
128
|
+
# @!method rmdir(path)
|
129
|
+
# @abstract
|
130
|
+
# Remove a directory
|
131
|
+
# @param [String] path
|
132
|
+
#
|
133
|
+
# @return [Integer] 0 for success or -ve errno
|
134
|
+
|
135
|
+
# int (*rmdir) (const char *);
|
136
|
+
op[:rmdir] = []
|
137
|
+
|
138
|
+
# @!method symlink(path,target)
|
139
|
+
# @abstract
|
140
|
+
# Create a symbolic link
|
141
|
+
# @param [String] path
|
142
|
+
# @param [String] target the link target
|
143
|
+
#
|
144
|
+
# @return [Integer] 0 for success or -ve errno
|
145
|
+
|
146
|
+
# int (*symlink) (const char *, const char *);
|
147
|
+
op[:symlink] = [:string]
|
148
|
+
|
149
|
+
# @!method rename(from_path,to_path)
|
150
|
+
# @abstract
|
151
|
+
# Rename a file
|
152
|
+
# @param [String] from_path
|
153
|
+
# @param [String] to_path
|
154
|
+
#
|
155
|
+
# @return [Integer] 0 for success or -ve errno
|
156
|
+
|
157
|
+
# int (*rename) (const char *, const char *);
|
158
|
+
op[:rename] = [:string]
|
159
|
+
|
160
|
+
# @!method link(path,target)
|
161
|
+
# @abstract
|
162
|
+
# Create a hard link to a file
|
163
|
+
# @param [String] path
|
164
|
+
# @param [String] target
|
165
|
+
#
|
166
|
+
# @return [Integer] 0 for success or -ve errno
|
167
|
+
|
168
|
+
# int (*link) (const char *, const char *);
|
169
|
+
op[:link] = [:string]
|
170
|
+
|
171
|
+
# @!method chmod(path,mode,fuse_file_info=nil)
|
172
|
+
# @abstract
|
173
|
+
# Change the permission bits of a file
|
174
|
+
# @param [String] path
|
175
|
+
# @param [Integer] mode
|
176
|
+
# @param [FuseFileInfo] fuse_file_info (Fuse3 only)
|
177
|
+
#
|
178
|
+
# @return [Integer] 0 for success or -ve errno
|
179
|
+
|
180
|
+
# int (*chmod) (const char *, mode_t);
|
181
|
+
op[:chmod] = [:mode_t]
|
182
|
+
op[:chmod] << FuseFileInfo.by_ref if FUSE_MAJOR_VERSION >= 3
|
183
|
+
|
184
|
+
# @!method chown(path,uid,gid,fuse_file_info=nil)
|
185
|
+
# @abstract
|
186
|
+
# Change the owner and group of a file
|
187
|
+
# @param [String] path
|
188
|
+
# @param [Integer] uid
|
189
|
+
# @param [Integer] gid
|
190
|
+
# @param [FuseFileInfo] fuse_file_info (Fuse3 only)
|
191
|
+
#
|
192
|
+
# @return [Integer] 0 for success or -ve errno
|
193
|
+
|
194
|
+
# int (*chown) (const char *, uid_t, gid_t);
|
195
|
+
op[:chown] = %i[uid_t gid_t]
|
196
|
+
op[:chown] << FuseFileInfo.by_ref if FUSE_MAJOR_VERSION >= 3
|
197
|
+
|
198
|
+
# @!method truncate(path,offset,fuse_file_info=nil)
|
199
|
+
# @abstract
|
200
|
+
# Change the size of a file
|
201
|
+
# @param [String] path
|
202
|
+
# @param [Integer] offset
|
203
|
+
# @param [FuseFileInfo] fuse_file_info (Fuse3 only)
|
204
|
+
#
|
205
|
+
# @return [Integer] 0 for success or -ve errno
|
206
|
+
|
207
|
+
# int (*truncate) (const char *, off_t);
|
208
|
+
op[:truncate] = [:off_t]
|
209
|
+
op[:truncate] << FuseFileInfo.by_ref if FUSE_MAJOR_VERSION >= 3
|
210
|
+
|
211
|
+
# int (*utime) (const char *, struct utimbuf *);
|
212
|
+
op[:utime] = [:pointer] if FUSE_MAJOR_VERSION < 3
|
213
|
+
|
214
|
+
# @!method open(path,fuse_file_info)
|
215
|
+
# @abstract
|
216
|
+
# File open operation
|
217
|
+
#
|
218
|
+
# No creation (O_CREAT, O_EXCL) and by default also no truncation (O_TRUNC) flags will be passed to open(). If an
|
219
|
+
# application specifies O_TRUNC, fuse first calls truncate() and then open(). Only if 'atomic_o_trunc' has been
|
220
|
+
# specified and kernel version is 2.6.24 or later, O_TRUNC is passed on to open.
|
221
|
+
#
|
222
|
+
# Unless the 'default_permissions' mount option is given, open should check if the operation is permitted for the
|
223
|
+
# given flags.
|
224
|
+
#
|
225
|
+
# Optionally open may also return an arbitrary filehandle in the fuse_file_info structure, which
|
226
|
+
# will be passed to all file operations.
|
227
|
+
#
|
228
|
+
# @param [String] path
|
229
|
+
# @param [FuseFileInfo] fuse_file_info
|
230
|
+
#
|
231
|
+
# @return [Integer] 0 for success or -ve errno
|
232
|
+
|
233
|
+
# int (*open) (const char *, struct fuse_file_info *);
|
234
|
+
op[:open] = [FuseFileInfo.by_ref]
|
235
|
+
|
236
|
+
# @!method read(path,buf,size,offset,fuse_file_info)
|
237
|
+
# @abstract
|
238
|
+
# Read data from an open file
|
239
|
+
# @param [String] path
|
240
|
+
# @param [FFI::Pointer] buf
|
241
|
+
# @param [Integer] size
|
242
|
+
# @param [Integer] offset
|
243
|
+
# @param [FuseFileInfo] fuse_file_info
|
244
|
+
#
|
245
|
+
# @return [Integer]
|
246
|
+
# Read should return exactly the number of bytes requested except on EOF or error, otherwise the rest of the
|
247
|
+
# data will be substituted with zeroes. An exception to this is when the 'direct_io' mount option is
|
248
|
+
# specified, in which case the return value of the read system call will reflect the return value of this
|
249
|
+
# operation.
|
250
|
+
|
251
|
+
# int (*read) (const char *, char *, size_t, off_t, struct fuse_file_info *);
|
252
|
+
op[:read] = [:pointer, :size_t, :off_t, FuseFileInfo.by_ref]
|
253
|
+
|
254
|
+
# @!method write(path, data, size,offset,fuse_file_info)
|
255
|
+
# @abstract
|
256
|
+
# Write data to an open file
|
257
|
+
#
|
258
|
+
# @param [String] path
|
259
|
+
# @param [FFI::Pointer] data
|
260
|
+
# @param [Integer] size
|
261
|
+
# @param [Integer] offset
|
262
|
+
# @param [FuseFileInfo] fuse_file_info
|
263
|
+
#
|
264
|
+
# @return [Integer]
|
265
|
+
# Write should return exactly the number of bytes requested except on error. An exception to this is when the
|
266
|
+
# 'direct_io' mount option is specified (see read operation).
|
267
|
+
|
268
|
+
# int (*write) (const char *, const char *, size_t, off_t, struct fuse_file_info *);
|
269
|
+
op[:write] = [:pointer, :size_t, :off_t, FuseFileInfo.by_ref]
|
270
|
+
|
271
|
+
# @!method statfs(path,statvfs)
|
272
|
+
# @abstract
|
273
|
+
# Get file system statistics
|
274
|
+
#
|
275
|
+
# @param [String] path
|
276
|
+
# @param [StatVfs] statvfs result struct
|
277
|
+
# Note 'frsize', 'favail', 'fsid' and 'flag' fields are ignored
|
278
|
+
#
|
279
|
+
# @return [Integer] 0 for success or -ve errno
|
280
|
+
|
281
|
+
# int (*statfs) (const char *, struct statvfs *);
|
282
|
+
op[:statfs] = [StatVfs.by_ref]
|
283
|
+
|
284
|
+
# @!method flush(path,fuse_file_info)
|
285
|
+
# Possibly flush cached data
|
286
|
+
#
|
287
|
+
# BIG NOTE: This is not equivalent to fsync(). It's not a request to sync dirty data.
|
288
|
+
#
|
289
|
+
# Flush is called on each close() of a file descriptor. So if a filesystem wants to return write errors in
|
290
|
+
# close() and the file has cached dirty data, this is a good place to write back data and return any errors.
|
291
|
+
# Since many applications ignore close() errors this is not always useful.
|
292
|
+
#
|
293
|
+
# NOTE: The flush() method may be called more than once for each open(). This happens if more than one file
|
294
|
+
# descriptor refers to an opened file due to dup(), dup2() or fork() calls. It is not possible to determine if a
|
295
|
+
# flush is final, so each flush should be treated equally. Multiple write-flush sequences are relatively rare,
|
296
|
+
# so this shouldn't be a problem.
|
297
|
+
#
|
298
|
+
# Filesystems shouldn't assume that flush will always be called after some writes, or that if will be called at
|
299
|
+
# all.
|
300
|
+
#
|
301
|
+
# @param [String] path
|
302
|
+
# @param [FuseFileInfo] fuse_file_info
|
303
|
+
#
|
304
|
+
# @return [Integer] 0 for success or -ve errno
|
305
|
+
|
306
|
+
# int (*flush) (const char *, struct fuse_file_info *);
|
307
|
+
op[:flush] = [FuseFileInfo.by_ref]
|
308
|
+
|
309
|
+
# @!method release(path,fuse_file_info)
|
310
|
+
# Release an open file
|
311
|
+
#
|
312
|
+
# Release is called when there are no more references to an open file: all file descriptors are closed and all
|
313
|
+
# memory mappings are unmapped.
|
314
|
+
#
|
315
|
+
# For every open() call there will be exactly one release() call with the same flags and file descriptor. It is
|
316
|
+
# possible to have a file opened more than once, in which case only the last release will mean, that no more
|
317
|
+
# reads \/ writes will happen on the file.
|
318
|
+
#
|
319
|
+
# @param [String] path
|
320
|
+
# @param [FuseFileInfo] fuse_file_info
|
321
|
+
#
|
322
|
+
# @return [Integer] The return value of release is ignored.
|
323
|
+
|
324
|
+
# int (*release) (const char *, struct fuse_file_info *);
|
325
|
+
op[:release] = [FuseFileInfo.by_ref]
|
326
|
+
|
327
|
+
# @!method fsync(path,datasync,fuse_file_info)
|
328
|
+
# Synchronize file contents
|
329
|
+
#
|
330
|
+
# @param [String] path
|
331
|
+
# @param [Integer] datasync If non-zero, then only the user data should be flushed, not the meta data.
|
332
|
+
# @param [FuseFileInfo] fuse_file_info
|
333
|
+
#
|
334
|
+
# @return [Integer] 0 for success or -ve errno
|
335
|
+
|
336
|
+
# int (*fsync) (const char *, int, struct fuse_file_info *);
|
337
|
+
op[:fsync] = [:int, FuseFileInfo.by_ref]
|
338
|
+
|
339
|
+
# @!method setxattr(path,name,data,size,flags)
|
340
|
+
# @abstract
|
341
|
+
# Set extended attributes
|
342
|
+
# @param [String] path
|
343
|
+
# @param [String] name
|
344
|
+
# @param [String] data
|
345
|
+
# @param [Integer] size
|
346
|
+
# @param [Symbol|Integer] flags (:xattr_create or :xattr_replace)
|
347
|
+
# @return [Integer] 0 for success or -ve errno
|
348
|
+
# @see setxattr(2)
|
349
|
+
|
350
|
+
# int (*setxattr) (const char *, const char *, const char *, size_t, int);
|
351
|
+
op[:setxattr] = %i[string string size_t xattr]
|
352
|
+
|
353
|
+
# @!method getxattr(path,name,buf,size)
|
354
|
+
# @abstract
|
355
|
+
# Get extended attributes
|
356
|
+
# @param [String] path
|
357
|
+
# @param [String] name
|
358
|
+
# @param [FFI::Pointer] buf
|
359
|
+
# @param [Integer] size
|
360
|
+
# @return [Integer]
|
361
|
+
# @see getxattr(2)
|
362
|
+
|
363
|
+
# int (*getxattr) (const char *, const char *, char *, size_t);
|
364
|
+
op[:getxattr] = %i[string pointer size_t]
|
365
|
+
|
366
|
+
# @!method listxattr(path,buf,size)
|
367
|
+
# @abstract
|
368
|
+
# List extended attributes
|
369
|
+
# @param [String] path
|
370
|
+
# @param [FFI::Pointer] buf
|
371
|
+
# @param [Integer] size
|
372
|
+
# @return [Integer]
|
373
|
+
# @see listxattr(2)
|
374
|
+
|
375
|
+
# int (*listxattr) (const char *, char *, size_t);
|
376
|
+
op[:listxattr] = %i[pointer size_t]
|
377
|
+
|
378
|
+
# @!method removexattr(path,name)
|
379
|
+
# @abstract
|
380
|
+
# Remove extended attributes
|
381
|
+
# @param [String] path
|
382
|
+
# @param [String] name
|
383
|
+
# @return [Integer] 0 on success or -ve errno
|
384
|
+
# @see removexattr(2)
|
385
|
+
|
386
|
+
# int (*removexattr) (const char *, const char *);
|
387
|
+
op[:removexattr] = [:string]
|
388
|
+
|
389
|
+
if FUSE_VERSION >= 23
|
390
|
+
|
391
|
+
# @!method opendir(path,fuse_file_info)
|
392
|
+
# @abstract
|
393
|
+
# Open directory
|
394
|
+
#
|
395
|
+
# Unless the 'default_permissions' mount option is given, this method should check if opendir is permitted for
|
396
|
+
# this directory. Optionally opendir may also return an arbitrary filehandle in the fuse_file_info structure,
|
397
|
+
# which will be passed to readdir, releasedir and fsyncdir.
|
398
|
+
#
|
399
|
+
# @param [String] path
|
400
|
+
# @param [FuseFileInfo] fuse_file_info
|
401
|
+
# @return [Integer] 0 for success or -ve errno
|
402
|
+
|
403
|
+
# int (*opendir) (const char *, struct fuse_file_info *);
|
404
|
+
op[:opendir] = [FuseFileInfo.by_ref]
|
405
|
+
|
406
|
+
# @!method readdir(path,buffer,filler,offset,fuse_file_info, fuse_readdir_flag = 0)
|
407
|
+
# @abstract
|
408
|
+
# Read directory
|
409
|
+
#
|
410
|
+
# The filesystem may choose between two modes of operation:
|
411
|
+
#
|
412
|
+
# 1) The readdir implementation ignores the offset parameter, and passes zero to the filler function's offset.
|
413
|
+
# The filler function will not return '1' (unless an error happens), so the whole directory is read in a single
|
414
|
+
# readdir operation.
|
415
|
+
#
|
416
|
+
# 2) The readdir implementation keeps track of the offsets of the directory entries. It uses the offset
|
417
|
+
# parameter and always passes non-zero offset to the filler function. When the buffer is full (or an error
|
418
|
+
# happens) the filler function will return '1'.
|
419
|
+
#
|
420
|
+
# @param [String] path
|
421
|
+
# @param [FFI::Pointer] buffer
|
422
|
+
# @param [Proc<FFI::Pointer,String,Stat,Integer,Integer=0>] filler the filler function to be called
|
423
|
+
# for each directory entry, ie filler.call(buffer,next_name,next_stat,next_offset, fuse_fill_dir_flag)
|
424
|
+
#
|
425
|
+
# @param [Integer] offset the starting offset
|
426
|
+
# @param [FuseFileInfo] fuse_file_info
|
427
|
+
# @param [Symbol] fuse_readdir_flag (Fuse3 only)
|
428
|
+
#
|
429
|
+
# @return [Integer] 0 on success or -ve errno
|
430
|
+
#
|
431
|
+
|
432
|
+
# int (*readdir) (const char *, void *buf, fuse_fill_dir_t, off_t, struct fuse_file_info *);
|
433
|
+
op[:readdir] = [:pointer, :fill_dir_t, :off_t, FuseFileInfo.by_ref]
|
434
|
+
op[:readdir] << :fuse_readdir_flags if FUSE_MAJOR_VERSION > 2
|
435
|
+
|
436
|
+
# @!method releasedir(path,fuse_file_info)
|
437
|
+
# Release directory
|
438
|
+
# @param [String] path
|
439
|
+
# @param [FuseFileInfo] fuse_file_info
|
440
|
+
# @return [Integer] 0 for success or -ve errno
|
441
|
+
|
442
|
+
# int (*releasedir) (const char *, struct fuse_file_info *);
|
443
|
+
op[:releasedir] = [FuseFileInfo.by_ref]
|
444
|
+
|
445
|
+
# @!method fsyncdir(path,datasync,fuse_file_info)
|
446
|
+
# Synchronize directory contents
|
447
|
+
#
|
448
|
+
# @param [String] path
|
449
|
+
# @param [Integer] datasync If non-zero, then only the user data should be flushed, not the meta data
|
450
|
+
# @param [FuseFileInfo] fuse_file_info
|
451
|
+
# @return [Integer] 0 for success or -ve errno
|
452
|
+
|
453
|
+
# int (*fsyncdir) (const char *, int, struct fuse_file_info *);
|
454
|
+
op[:fsyncdir] = [:int, FuseFileInfo.by_ref]
|
455
|
+
|
456
|
+
# @!method init(fuse_conn_info,fuse_config=nil)
|
457
|
+
# @abstract
|
458
|
+
# Initialize filesystem
|
459
|
+
#
|
460
|
+
# @param [FuseConnInfo] fuse_conn_info
|
461
|
+
# @param [FuseConfig|nil] fuse_config only provided for fuse3 and later
|
462
|
+
#
|
463
|
+
# @return [Object]
|
464
|
+
# The return value will passed in the private_data field of fuse_context to all file operations and as a
|
465
|
+
# parameter to the destroy() method.
|
466
|
+
#
|
467
|
+
|
468
|
+
# fuse2: void *(*init) (struct fuse_conn_info *conn);
|
469
|
+
# fuse3: void *(*init) (struct fuse_conn_info *conn, struct fuse_config *cfg);
|
470
|
+
op[:init] =
|
471
|
+
if FUSE_MAJOR_VERSION >= 3
|
472
|
+
require_relative 'fuse_config'
|
473
|
+
callback([FuseConnInfo.by_ref, FuseConfig.by_ref], RubyObject)
|
474
|
+
else
|
475
|
+
callback([FuseConnInfo.by_ref], RubyObject)
|
476
|
+
end
|
477
|
+
|
478
|
+
# @!method destroy(obj)
|
479
|
+
# @abstract
|
480
|
+
# @param [Object] obj - the object passed from {init}.
|
481
|
+
# Clean up filesystem. Called on filesystem exit.
|
482
|
+
|
483
|
+
# void (*destroy) (void *);
|
484
|
+
op[:destroy] = callback([RubyObject], :void)
|
485
|
+
end
|
486
|
+
|
487
|
+
if FUSE_VERSION >= 25
|
488
|
+
|
489
|
+
# @!method access(path,mode)
|
490
|
+
# @abstract
|
491
|
+
# Check file access permissions
|
492
|
+
#
|
493
|
+
# This will be called for the access() system call. If the 'default_permissions' mount option is given, this
|
494
|
+
# method is not called.
|
495
|
+
#
|
496
|
+
# This method is not called under Linux kernel versions 2.4.x
|
497
|
+
#
|
498
|
+
# @param [String] path
|
499
|
+
# @param [Integer] mode
|
500
|
+
# @return [Integer] 0 for success or -ve errno
|
501
|
+
# @see access(2)
|
502
|
+
|
503
|
+
# int (*access) (const char *, int);
|
504
|
+
op[:access] = [:int]
|
505
|
+
|
506
|
+
# @!method create(path,mode,fuse_file_info)
|
507
|
+
# @abstract
|
508
|
+
# Create and open a file
|
509
|
+
#
|
510
|
+
# If the file does not exist, first create it with the specified mode, and then open it.
|
511
|
+
#
|
512
|
+
# If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the mknod() and open()
|
513
|
+
# methods will be called instead.
|
514
|
+
#
|
515
|
+
# @param [String] path
|
516
|
+
# @param [Integer] mode
|
517
|
+
# @param [FuseFileInfo] fuse_file_info
|
518
|
+
# @return [Integer] 0 for success or -ve errno
|
519
|
+
|
520
|
+
# int (*create) (const char *, mode_t, struct fuse_file_info *);
|
521
|
+
op[:create] = [:mode_t, FuseFileInfo.by_ref]
|
522
|
+
|
523
|
+
# @!method ftruncate(path,offset,fuse_file_info)
|
524
|
+
# @deprecated in Fuse3 implement {truncate} instead
|
525
|
+
# @abstract
|
526
|
+
# Change the size of an open file
|
527
|
+
#
|
528
|
+
# This method is called instead of the truncate() method if the truncation was invoked from an ftruncate()
|
529
|
+
# system call.
|
530
|
+
#
|
531
|
+
# If this method is not implemented or under Linux kernel versions earlier than 2.6.15, the truncate() method
|
532
|
+
# will be called instead.
|
533
|
+
#
|
534
|
+
# @param [String] path
|
535
|
+
# @param [Integer] offset
|
536
|
+
# @param [FuseFileInfo] fuse_file_info
|
537
|
+
# @return [Integer] 0 for success or -ve errno
|
538
|
+
|
539
|
+
# int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
|
540
|
+
op[:ftruncate] = [:off_t, FuseFileInfo.by_ref] if FUSE_MAJOR_VERSION < 3
|
541
|
+
|
542
|
+
# @!method fgetattr(path,stat,fuse_file_info)
|
543
|
+
# @deprecated in Fuse3 implement {getattr} instead
|
544
|
+
# Get attributes from an open file
|
545
|
+
#
|
546
|
+
# This method is called instead of the getattr() method if the file information is available.
|
547
|
+
#
|
548
|
+
# Currently this is only called after the create() method if that is implemented (see above). Later it may be
|
549
|
+
# called for invocations of fstat() too.
|
550
|
+
# @param [String] path
|
551
|
+
# @param [Stat] stat
|
552
|
+
# @param [FuseFileInfo] fuse_file_info
|
553
|
+
# @return [Integer] 0 for success or -ve errno
|
554
|
+
|
555
|
+
# int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
|
556
|
+
op[:fgetattr] = [Stat, FuseFileInfo.by_ref] if FUSE_MAJOR_VERSION < 3
|
557
|
+
end
|
558
|
+
if FUSE_VERSION >= 26
|
559
|
+
# @!method lock(path,fuse_file_info,cmd,flock)
|
560
|
+
# @abstract
|
561
|
+
#
|
562
|
+
# Perform POSIX file locking operation
|
563
|
+
# @param [String] path
|
564
|
+
# @param [FuseFileInfo] fuse_file_info
|
565
|
+
# For checking lock ownership, the 'fuse_file_info->owner' argument must be used.
|
566
|
+
# @param [Symbol] cmd either :f_getlck, :f_setlck or :f_setlkw.
|
567
|
+
# @param [Flock] flock
|
568
|
+
# For the meaning of fields in 'struct flock' see the man page for fcntl(2). The whence field will always
|
569
|
+
# be set to :seek_set.
|
570
|
+
#
|
571
|
+
# @return [Integer] 0 for success or -ve errno
|
572
|
+
#
|
573
|
+
# For :f_getlk operation, the library will first check currently held locks, and if a conflicting lock is found
|
574
|
+
# it will return information without calling this method. This ensures, that for local locks the pid field
|
575
|
+
# is correctly filled in. The results may not be accurate in case of race conditions and in the presence of
|
576
|
+
# hard links, but its unlikely that an application would rely on accurate GETLK results in these cases. If a
|
577
|
+
# conflicting lock is not found, this method will be called, and the filesystem may fill out l_pid by a
|
578
|
+
# meaningful value, or it may leave this field zero.
|
579
|
+
#
|
580
|
+
# For :f_setlk and :f_setlkw the pid field will be set to the pid of the process performing the locking
|
581
|
+
# operation.
|
582
|
+
#
|
583
|
+
# @note if this method is not implemented, the kernel will still allow file locking to work locally. Hence it
|
584
|
+
# is only interesting for network filesystem and similar.
|
585
|
+
|
586
|
+
# int (*lock) (const char *, struct fuse_file_info *, int cmd, struct flock *);
|
587
|
+
op[:lock] = [FuseFileInfo.by_ref, Flock::Enums::LockCmd, Flock.by_ref]
|
588
|
+
|
589
|
+
# @!method utimens(path,time_specs,fuse_file_info=nil)
|
590
|
+
# @abstract
|
591
|
+
# Change the access and modification times of a file with nanosecond resolution
|
592
|
+
#
|
593
|
+
# This supersedes the old utime() interface. New applications should use this.
|
594
|
+
#
|
595
|
+
# @param [String] path
|
596
|
+
# @param [Array<Stat::TimeSpec>] time_specs atime,mtime
|
597
|
+
# @param [FuseFileInfo] fuse_file_info (only since Fuse3)
|
598
|
+
# @return [Integer] 0 for success or -ve errno
|
599
|
+
#
|
600
|
+
# @see utimensat(2)
|
601
|
+
#
|
602
|
+
|
603
|
+
# int (*utimens) (const char *, const struct timespec tv[2]);
|
604
|
+
op[:utimens] = [FFI::Stat::TimeSpec.array(2)]
|
605
|
+
op[:utimens] << FuseFileInfo.by_ref if FUSE_MAJOR_VERSION >= 3
|
606
|
+
|
607
|
+
# @!method bmap(path,blocksize,index)
|
608
|
+
# @abstract
|
609
|
+
# Map block index within file to block index within device
|
610
|
+
#
|
611
|
+
# @param [String] path
|
612
|
+
# @param [Integer] blocksize
|
613
|
+
# @param [FFI::Pointer] index pointer to index result
|
614
|
+
# @return [Integer] 0 success or -ve errno
|
615
|
+
# @note This makes sense only for block device backed filesystem mounted with the 'blkdev' option
|
616
|
+
|
617
|
+
# int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
|
618
|
+
op[:bmap] = %i[size_t pointer]
|
619
|
+
|
620
|
+
end
|
621
|
+
|
622
|
+
# @!method fuse_flags
|
623
|
+
# @abstract
|
624
|
+
# Configuration method to set fuse flags
|
625
|
+
#
|
626
|
+
# - :nullpath_ok
|
627
|
+
#
|
628
|
+
# Flag indicating that the filesystem can accept a NULL path as the first argument for the following
|
629
|
+
# operations: read, write, flush, release, fsync, readdir, releasedir, fsyncdir, ftruncate, fgetattr, lock,
|
630
|
+
# ioctl and poll
|
631
|
+
#
|
632
|
+
# If this flag is set these operations continue to work on unlinked files even if "-ohard_remove" option was
|
633
|
+
# specified.
|
634
|
+
#
|
635
|
+
# - :nopath
|
636
|
+
#
|
637
|
+
# Flag indicating that the path need not be calculated for the following operations: read, write, flush,
|
638
|
+
# release, fsync, readdir, releasedir, fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
|
639
|
+
#
|
640
|
+
# Closely related to flag_nullpath_ok, but if this flag is set then the path will not be calculaged even if
|
641
|
+
# the file wasnt unlinked. However the path can still be non-NULL if it needs to be calculated for some other
|
642
|
+
# reason.
|
643
|
+
#
|
644
|
+
# - :utime_omit_ok
|
645
|
+
#
|
646
|
+
# Flag indicating that the filesystem accepts special UTIME_NOW and UTIME_OMIT values in its utimens
|
647
|
+
# operation.
|
648
|
+
#
|
649
|
+
# @return [Array[]Symbol>] a list of flags to set capabilities
|
650
|
+
# @note Not available in Fuse3
|
651
|
+
# @deprecated in Fuse3 use fuse_config object in {init}
|
652
|
+
op[:flags] = :flags_mask if FUSE_MAJOR_VERSION < 3
|
653
|
+
|
654
|
+
if FUSE_VERSION >= 28
|
655
|
+
|
656
|
+
# @!method ioctl(path,cmd,arg,fuse_file_info, flags,data)
|
657
|
+
# @abstract
|
658
|
+
# Ioctl
|
659
|
+
# @param [String] path
|
660
|
+
# @param [Integer] cmd
|
661
|
+
# @param [FFI::Pointer] arg
|
662
|
+
# @param [FuseFileInfo] fuse_file_info
|
663
|
+
# @param [Integer] flags
|
664
|
+
# @param [FFI::Pointer] data
|
665
|
+
#
|
666
|
+
# flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in 64bit environment. The size and direction of data
|
667
|
+
# is determined by _IOC_*() decoding of cmd. For _IOC_NONE, data will be NULL, for _IOC_WRITE data is out
|
668
|
+
# area, for _IOC_READ in area and if both are set in/out area. In all non-NULL cases, the area is of
|
669
|
+
# _IOC_SIZE(cmd) bytes.
|
670
|
+
#
|
671
|
+
# If flags has FUSE_IOCTL_DIR then the fuse_file_info refers to a directory file handle.
|
672
|
+
|
673
|
+
# int (*ioctl) (const char *, int cmd, void *arg, struct fuse_file_info *, unsigned int flags, void *data);
|
674
|
+
op[:ioctl] = [:int, :pointer, FuseFileInfo.by_ref, :uint, :pointer]
|
675
|
+
|
676
|
+
# @!method poll(path,fuse_file_info,ph,reventsp)
|
677
|
+
# @abstract
|
678
|
+
# Poll for IO readiness events
|
679
|
+
#
|
680
|
+
# @param [String] path
|
681
|
+
# @param [FuseFileInfo] fuse_file_info
|
682
|
+
# @param [FusePollHandle|nil] ph
|
683
|
+
# If ph is set, the client should notify when IO readiness events occur by calling
|
684
|
+
# {FusePollHandle#notify_poll} (possibly asynchronously)
|
685
|
+
#
|
686
|
+
# Regardless of the number of times poll is received, single notification is enough to clear
|
687
|
+
# all. Notifying more times incurs overhead but doesnt harm correctness.
|
688
|
+
#
|
689
|
+
# @param [FFI::Pointer] reventsp return events
|
690
|
+
# @return [Integer] 0 for success, -ve for error
|
691
|
+
# @see poll(2)
|
692
|
+
|
693
|
+
# int (*poll) (const char *, struct fuse_file_info *, struct fuse_pollhandle *ph, unsigned *reventsp);
|
694
|
+
op[:poll] = [FuseFileInfo.by_ref, FusePollHandle, :pointer]
|
695
|
+
|
696
|
+
# @!method write_buf(path,buf,offset,fuse_file_info)
|
697
|
+
# @abstract
|
698
|
+
# Write contents of buffer to an open file
|
699
|
+
#
|
700
|
+
# Similar to the write() method, but data is supplied in a generic buffer. Use fuse_buf_copy() to transfer
|
701
|
+
# data to the destination.
|
702
|
+
#
|
703
|
+
# @param [String] path
|
704
|
+
# @param [FuseBufVec] buf
|
705
|
+
# @param [Integer] offset
|
706
|
+
# @param [FuseFileInfo] fuse_file_info
|
707
|
+
#
|
708
|
+
# @return [Integer] the number of bytes written or -ve errno
|
709
|
+
|
710
|
+
# int (*write_buf) (const char *, struct fuse_bufvec *buf, off_t off, struct fuse_file_info *);
|
711
|
+
op[:write_buf] = [FuseBufVec.by_ref, :off_t, FuseFileInfo.by_ref]
|
712
|
+
|
713
|
+
# @!method read_buf(path,bufp,size,offset,fuse_file_info)
|
714
|
+
# @abstract
|
715
|
+
#
|
716
|
+
# Similar to the read() method, but data is stored and returned in a generic buffer.
|
717
|
+
#
|
718
|
+
# No actual copying of data has to take place, the source file descriptor may simply be stored in the buffer
|
719
|
+
# for later data transfer.
|
720
|
+
#
|
721
|
+
# @param [String] path
|
722
|
+
# @param [FFI::Pointer<FuseBufVec>] bufp
|
723
|
+
# The buffer must be allocated dynamically and stored at the location pointed to by bufp. If the buffer
|
724
|
+
# contains memory regions, they too must be allocated using malloc(). The allocated memory will be freed by
|
725
|
+
# the caller.
|
726
|
+
# @param [Integer] size
|
727
|
+
# @param [Integer] offset
|
728
|
+
# @param [FuseFileInfo] fuse_file_info
|
729
|
+
# @return 0 success or -ve errno
|
730
|
+
|
731
|
+
# int (*read_buf) (const char *, struct fuse_bufvec **bufp, size_t size, off_t off, struct fuse_file_info *);
|
732
|
+
op[:read_buf] = [:pointer, :size_t, :off_t, FuseFileInfo.by_ref]
|
733
|
+
|
734
|
+
# @!method flock(path,fuse_file_info,op)
|
735
|
+
# @abstract
|
736
|
+
# Perform BSD file locking operation
|
737
|
+
#
|
738
|
+
# @param [String] path
|
739
|
+
# @param [FuseFileInfo] fuse_file_info
|
740
|
+
# Additionally fi->owner will be set to a value unique to this open file. This same value will be supplied
|
741
|
+
# to {release} when the file is released.
|
742
|
+
# @param [Array<Symbol>] op the lock operation
|
743
|
+
# The op argument will contain one of :lock_sh, :lock_ex, or :lock_un
|
744
|
+
# Nonblocking requests also include :lock_nb
|
745
|
+
# @return 0 or -ve errno
|
746
|
+
# @see flock(2)
|
747
|
+
#
|
748
|
+
# @note: if this method is not implemented, the kernel will still allow file locking to work locally. Hence it
|
749
|
+
# is only interesting for network filesystem and similar.
|
750
|
+
|
751
|
+
# int (*flock) (const char *, struct fuse_file_info *, int op);
|
752
|
+
op[:flock] = [FuseFileInfo.by_ref, :lock_op]
|
753
|
+
|
754
|
+
# @!method fallocate(path,mode,offset,len,fuse_file_info)
|
755
|
+
# @abstract
|
756
|
+
# Allocates space for an open file
|
757
|
+
#
|
758
|
+
# This function ensures that required space is allocated for specified file. If this function returns success
|
759
|
+
# then any subsequent write request to specified range is guaranteed not to fail because of lack of space on
|
760
|
+
# the file system media.
|
761
|
+
#
|
762
|
+
# @param [String] path
|
763
|
+
# @param [Array<Symbol>] mode allocation mode flags
|
764
|
+
# :keep_size :punch_hole :no_hide_stale :collapse_range :zero_range :insert_range :unshare_range
|
765
|
+
# see linux/falloc.h
|
766
|
+
# @param [Integer] offset
|
767
|
+
# @param [Integer] len
|
768
|
+
# @return 0 or -ve errno
|
769
|
+
#
|
770
|
+
# @see fallocate(2)
|
771
|
+
|
772
|
+
# Introduced in version 2.9.1 - fuse_version does not contain patch level.
|
773
|
+
# this will generate a warning on 2.9.0 that the struct is bigger than expected
|
774
|
+
# and thus some operations (ie falllocate) may be unsupported.
|
775
|
+
#
|
776
|
+
# int (*fallocate) (const char *, int, off_t, off_t, struct fuse_file_info *);
|
777
|
+
op[:fallocate] = [:falloc_mode, :off_t, :off_t, FuseFileInfo.by_ref]
|
778
|
+
|
779
|
+
if FUSE_MAJOR_VERSION >= 3
|
780
|
+
|
781
|
+
# @!method copy_file_range(path_in,fi_in, offset_in, path_out, fi_out, offset_out, size, flags)
|
782
|
+
# @abstract
|
783
|
+
# Copy a range of data from one file to another
|
784
|
+
#
|
785
|
+
# Performs an optimized copy between two file descriptors without the additional cost of transferring data
|
786
|
+
# through the FUSE kernel module to user space (glibc) and then back into the FUSE filesystem again.
|
787
|
+
#
|
788
|
+
# In case this method is not implemented, glibc falls back to reading data from the source and writing to the
|
789
|
+
# destination. Effectively doing an inefficient copy of the data.
|
790
|
+
#
|
791
|
+
# @param [String] path_in
|
792
|
+
# @param [FuseFileInfo] fi_in
|
793
|
+
# @param [Integer] offset_in
|
794
|
+
# @param [String] path_out
|
795
|
+
# @param [FuseFileInfo] fi_out
|
796
|
+
# @param [Integer] offset_out
|
797
|
+
# @param [Integer] size
|
798
|
+
# @param [Array<Symbol>] flags (unused)
|
799
|
+
# @return [Integer] copied size or -ve errno
|
800
|
+
|
801
|
+
# ssize_t (*copy_file_range) (
|
802
|
+
# const char *path_in, struct fuse_file_info *fi_in, off_t offset_in, const char *path_out,
|
803
|
+
# struct fuse_file_info *fi_out, off_t offset_out, size_t size, int flags
|
804
|
+
# );
|
805
|
+
op[:copy_file_range] =
|
806
|
+
callback [
|
807
|
+
:string, FuseFileInfo.by_ref, :off_t,
|
808
|
+
:string, FuseFileInfo.by_ref, :off_t,
|
809
|
+
:size_t, :int
|
810
|
+
], :ssize_t
|
811
|
+
|
812
|
+
# @!method lseek(path,offset,whence,fuse_file_info)
|
813
|
+
# @abstract
|
814
|
+
# Find next data or hole after the specified offset
|
815
|
+
# @param [String] path
|
816
|
+
# @param [Integer] offset
|
817
|
+
# @param [Symbol] whence
|
818
|
+
# either :seek_set ,:seek_cur, :seek_end, :seek_data, :seek_hole
|
819
|
+
# @return [Integer] the found offset in bytes from the beginning of the file or -ve errno
|
820
|
+
# @see lseek(2)
|
821
|
+
|
822
|
+
# off_t (*lseek) (const char *, off_t off, int whence, struct fuse_file_info *);
|
823
|
+
op[:lseek] = callback [:string, :off_t, Flock::Enums::SeekWhence, FuseFileInfo.by_ref], :off_t
|
824
|
+
end
|
825
|
+
end
|
826
|
+
|
827
|
+
# @!endgroup
|
828
|
+
|
829
|
+
layout_data = op.transform_values do |v|
|
830
|
+
if v.is_a?(Array) && !v.last.is_a?(Integer)
|
831
|
+
# A typical fuse callback
|
832
|
+
callback([:string] + v, :int)
|
833
|
+
else
|
834
|
+
v
|
835
|
+
end
|
836
|
+
end
|
837
|
+
|
838
|
+
layout layout_data
|
839
|
+
|
840
|
+
# @overload initialize(fuse_wrappers: [], fuse_flags: [], delegate: self)
|
841
|
+
# Build a FuseOperations struct and register callback methods
|
842
|
+
#
|
843
|
+
# The methods to register are identified by delegate.{fuse_respond_to?} if available
|
844
|
+
# otherwise delegate.{::respond_to?} is used.
|
845
|
+
#
|
846
|
+
# @param [Object] delegate
|
847
|
+
# delegate object that quacks like our abstract methods (after any wrappers)
|
848
|
+
#
|
849
|
+
# if not provided defaults to self, ie a subclass of FuseOperations that implements the otherwise abstract
|
850
|
+
# callback and configuration methods, or a naked FuseOperations that must be externally configured.
|
851
|
+
#
|
852
|
+
# @param [Array] fuse_wrappers
|
853
|
+
# A list of fuse_wrappers (see {register}). Passed into delegate.{fuse_wrappers} if available
|
854
|
+
#
|
855
|
+
# @param [Array<Symbol>] fuse_flags list of configuration flags (Not used in Fuse3)
|
856
|
+
# concatenated #fuse_flags if available
|
857
|
+
def initialize(*args, fuse_wrappers: [], fuse_flags: [], delegate: self)
|
858
|
+
super(*args) # FFI::Struct constructor
|
859
|
+
return if args.any? # only configure if this is a new allocation
|
860
|
+
|
861
|
+
initialize_callbacks(wrappers: fuse_wrappers, delegate: delegate)
|
862
|
+
|
863
|
+
return unless FUSE_MAJOR_VERSION < 3
|
864
|
+
|
865
|
+
fuse_flags.concat(delegate.fuse_flags) if delegate.respond_to?(:fuse_flags)
|
866
|
+
send(:[]=, :flags, fuse_flags.uniq)
|
867
|
+
end
|
868
|
+
end
|
869
|
+
end
|
870
|
+
end
|