ffi-libfuse 0.4.0 → 0.4.1

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.
data/lib/ffi/flock.rb CHANGED
@@ -18,32 +18,36 @@ module FFI
18
18
 
19
19
  include(Accessors)
20
20
 
21
- layout(l_type: Enums::LockType, l_whence: Enums::SeekWhenceShort, l_start: :off_t, l_len: :off_t, l_pid: :pid_t)
22
-
23
- l_members = members.grep(/^l_/).map { |m| m[2..].to_sym }
24
-
25
- ffi_attr_reader(*l_members, format: 'l_%s')
26
-
27
- # @!attribute [r] type
28
- # @return [Symbol] lock type, :rdlck, :wrlck, :unlck
29
-
30
- # @!attribute [r] whence
31
- # @return [Symbol] specifies what the offset is relative to, one of :seek_set, :seek_cur or :seek_end
32
- # corresponding to the whence argument to fseek(2) or lseek(2),
33
-
34
- # @!attribute [r] start
35
- # @return [Integer] the offset of the start of the region to which the lock applies, and is given in bytes
36
- # relative to the point specified by #{whence} member.
37
-
38
- # @!attribute [r] len
39
- # @return [Integer] the length of the region to be locked.
40
- #
41
- # A value of 0 means the region extends to the end of the file.
42
-
43
- # @!attribute [r] pid
44
- # @return [Integer] the process ID (see Process Creation Concepts) of the process holding the lock.
45
- # It is filled in by calling fcntl with the F_GETLK command, but is ignored when making a lock. If the
46
- # conflicting lock is an open file description lock (see Open File Description Locks), then this field will be
47
- # set to -1.
21
+ layout(
22
+ # @!attribute [r] type
23
+ # @return [Symbol] lock type, :rdlck, :wrlck, :unlck
24
+ l_type: Enums::LockType,
25
+
26
+ # @!attribute [r] whence
27
+ # @return [Symbol] specifies what the offset is relative to, one of :seek_set, :seek_cur or :seek_end
28
+ # corresponding to the whence argument to fseek(2) or lseek(2),
29
+ l_whence: Enums::SeekWhenceShort,
30
+
31
+ # @!attribute [r] start
32
+ # @return [Integer] the offset of the start of the region to which the lock applies, and is given in bytes
33
+ # relative to the point specified by #{whence} member.
34
+ l_start: :off_t,
35
+
36
+ # @!attribute [r] len
37
+ # @return [Integer] the length of the region to be locked.
38
+ #
39
+ # A value of 0 means the region extends to the end of the file.
40
+ l_len: :off_t,
41
+
42
+ # @!attribute [r] pid
43
+ # @return [Integer] the process ID (see Process Creation Concepts) of the process holding the lock.
44
+ # It is filled in by calling fcntl with the F_GETLK command, but is ignored when making a lock. If the
45
+ # conflicting lock is an open file description lock (see Open File Description Locks), then this field will be
46
+ # set to -1.
47
+ l_pid: :pid_t
48
+ )
49
+
50
+ # Strip leading 'l_' to make attribute names
51
+ ffi_attr_reader(**members.to_h { |m| [m[2..].to_sym, m] })
48
52
  end
49
53
  end
@@ -18,7 +18,7 @@ module FFI
18
18
  )
19
19
  return wrappers unless defined?(super)
20
20
 
21
- super(*wrappers)
21
+ super
22
22
  end
23
23
 
24
24
  module_function
@@ -41,7 +41,7 @@ module FFI
41
41
  wrappers << proc { |fm, *args, &b| debug_callback(fm, *args, **conf, &b) } if debug?
42
42
  return wrappers unless defined?(super)
43
43
 
44
- super(*wrappers)
44
+ super
45
45
  end
46
46
 
47
47
  # @!visibility private
@@ -12,27 +12,27 @@ module FFI
12
12
  if FUSE_MAJOR_VERSION == 2
13
13
  # @!visibility private
14
14
  def getattr(path, stat, fuse_file_info = nil)
15
- super(path, stat, fuse_file_info)
15
+ super
16
16
  end
17
17
 
18
18
  def truncate(path, size, fuse_file_info = nil)
19
- super(path, size, fuse_file_info)
19
+ super
20
20
  end
21
21
 
22
22
  def init(fuse_conn_info, fuse_config = nil)
23
- super(fuse_conn_info, fuse_config)
23
+ super
24
24
  end
25
25
 
26
26
  def chown(path, uid, gid, fuse_file_info = nil)
27
- super(path, uid, gid, fuse_file_info)
27
+ super
28
28
  end
29
29
 
30
30
  def chmod(path, mode, fuse_file_info = nil)
31
- super(path, mode, fuse_file_info)
31
+ super
32
32
  end
33
33
 
34
34
  def utimens(path, times, fuse_file_info = nil)
35
- super(path, times, fuse_file_info)
35
+ super
36
36
  end
37
37
 
38
38
  def readdir(path, buffer, filler, offset, fuse_file_info, fuse_readdir_flag = 0)
@@ -45,7 +45,7 @@ module FFI
45
45
  # fgetattr and ftruncate already fallback to the respective basic method
46
46
  return false if %i[getdir fgetattr ftruncate].include?(fuse_method)
47
47
 
48
- super(fuse_method)
48
+ super
49
49
  end
50
50
 
51
51
  def fuse_options(args)
@@ -24,24 +24,24 @@ module FFI
24
24
  fi = args.pop
25
25
  return fgetattr(*args, fi) if fi && fuse_super_respond_to?(:fgetattr)
26
26
 
27
- super(*args)
27
+ super
28
28
  end
29
29
 
30
30
  def truncate(*args)
31
31
  fi = args.pop
32
32
  return ftruncate(*args, fi) if fi && fuse_super_respond_to?(:ftruncate)
33
33
 
34
- super(*args)
34
+ super
35
35
  end
36
36
 
37
37
  def chown(*args)
38
38
  args.pop
39
- super(*args)
39
+ super
40
40
  end
41
41
 
42
42
  def chmod(*args)
43
43
  args.pop
44
- super(*args)
44
+ super
45
45
  end
46
46
 
47
47
  # TODO: Fuse3 deprecated flag utime_omit_ok - which meant that UTIME_OMIT and UTIME_NOW are passed through
@@ -50,14 +50,14 @@ module FFI
50
50
  # but there is no way to handle OMIT
51
51
  def utimens(*args)
52
52
  args.pop
53
- super(*args) if defined?(super)
53
+ super if defined?(super)
54
54
  end
55
55
 
56
56
  def init(*args)
57
57
  args.pop
58
58
 
59
59
  # TODO: populate FuseConfig with output from fuse_flags/FuseConnInfo where appropriate
60
- super(*args)
60
+ super
61
61
  end
62
62
 
63
63
  def readdir(*args, &block)
@@ -71,7 +71,7 @@ module FFI
71
71
  proc { |buf, name, stat, off| a.call(buf, name, stat, off, 0) }
72
72
  end
73
73
 
74
- super(*args, &block)
74
+ super
75
75
  end
76
76
 
77
77
  def fuse_respond_to(fuse_callback)
@@ -20,7 +20,7 @@ module FFI
20
20
  }
21
21
  return wrappers unless defined?(super)
22
22
 
23
- super(*wrappers)
23
+ super
24
24
  end
25
25
 
26
26
  module_function
@@ -15,7 +15,7 @@ module FFI
15
15
  }
16
16
  return wrappers unless defined?(super)
17
17
 
18
- super(*wrappers)
18
+ super
19
19
  end
20
20
  end
21
21
  end
@@ -338,7 +338,7 @@ module FFI
338
338
 
339
339
  # Calls super if defined and storing result to protect from GC until {#destroy}
340
340
  def init(*args)
341
- o = super(*args) if fuse_super_respond_to?(:init)
341
+ o = super if fuse_super_respond_to?(:init)
342
342
  handles << o if o
343
343
  end
344
344
 
@@ -23,7 +23,7 @@ module FFI
23
23
  }
24
24
  return wrappers unless defined?(super)
25
25
 
26
- super(*wrappers)
26
+ super
27
27
  end
28
28
 
29
29
  # @return [Integer] the default errno to return for rescued errors. ENOTRECOVERABLE unless overridden
@@ -41,7 +41,7 @@ module FFI
41
41
 
42
42
  def initialize(accounting: Accounting.new)
43
43
  @entries = {}
44
- super(accounting: accounting)
44
+ super
45
45
  end
46
46
 
47
47
  # @!endgroup
@@ -157,7 +157,7 @@ module FFI
157
157
  # TODO: Strictly should understand setgid and sticky bits of this dir's mode when creating new files
158
158
  new_file = file ? file.call(name) : new_file(name)
159
159
  if entry_fuse_respond_to?(new_file, :create)
160
- new_file.public_send(:create, '/', mode, ffi)
160
+ new_file.create('/', mode, ffi)
161
161
  else
162
162
  # TODO: generate a sensible device number
163
163
  entry_send(new_file, :mknod, '/', mode, 0)
@@ -20,7 +20,7 @@ module FFI
20
20
 
21
21
  # Create an empty synthetic file
22
22
  def initialize(accounting: nil)
23
- super(accounting: accounting)
23
+ super
24
24
  end
25
25
 
26
26
  # @!group FUSE Callbacks
@@ -12,7 +12,7 @@ module FFI
12
12
  include VirtualNode
13
13
  def initialize(accounting: nil)
14
14
  @target = target
15
- super(accounting: accounting)
15
+ super
16
16
  end
17
17
 
18
18
  def readlink(_path, size)
@@ -58,12 +58,12 @@ module FFI
58
58
  cmdline_opts = FuseCmdlineOpts.new
59
59
  raise Error unless Libfuse.fuse_parse_cmdline3(args, cmdline_opts).zero?
60
60
 
61
- handler&.fuse_debug(cmdline_opts.debug) if handler.respond_to?(:fuse_debug)
61
+ handler&.fuse_debug(cmdline_opts.debug?) if handler.respond_to?(:fuse_debug)
62
62
 
63
63
  # mimics fuse_main which exits after printing version info, even if -h
64
- if cmdline_opts.show_version
64
+ if cmdline_opts.show_version?
65
65
  show_version(handler)
66
- elsif cmdline_opts.show_help
66
+ elsif cmdline_opts.show_help?
67
67
  show_help(args, handler)
68
68
  end
69
69
 
@@ -145,8 +145,8 @@ module FFI
145
145
 
146
146
  private
147
147
 
148
- def native_fuse_loop_mt(max_idle_threads: 10, **_options)
149
- Libfuse.fuse_loop_mt3(@fuse, FuseLoopConfig.new.fill(max_idle: max_idle_threads))
148
+ def native_fuse_loop_mt(**options)
149
+ Libfuse.fuse_loop_mt3(@fuse, FuseLoopConfig.create(**options))
150
150
  end
151
151
 
152
152
  def unmount
@@ -3,13 +3,17 @@
3
3
  require_relative 'fuse_version'
4
4
  require_relative 'fuse_opt'
5
5
  require_relative '../ruby_object'
6
+ require_relative '../boolean_int'
7
+ require_relative '../accessors'
6
8
 
7
9
  module FFI
8
10
  # Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
9
11
  module Libfuse
10
12
  # struct fuse_args
11
13
  class FuseArgs < FFI::Struct
12
- layout :argc, :int, :argv, :pointer, :allocated, :int
14
+ include FFI::Accessors
15
+
16
+ layout :argc, :int, :argv, :pointer, :allocated, :bool_int
13
17
 
14
18
  # Create a fuse_args struct from command line options
15
19
  # @param [Array<String>] argv command line args
@@ -34,33 +38,17 @@ module FFI
34
38
  @arg_vector[argv.size].put_pointer(0, FFI::Pointer::NULL)
35
39
  self[:argv] = @arg_vector
36
40
  self[:argc] = argv.size
37
- self[:allocated] = 0
41
+ self[:allocated] = false # ie libfuse did not allocate
38
42
  self
39
43
  end
40
44
 
41
- # @!attribute [r] argc
42
- # @return [Integer] count of args
43
- def argc
44
- self[:argc]
45
- end
46
-
47
45
  # @!attribute [r] argv
48
46
  # @return [Array<String>] list of args
49
- def argv
47
+ ffi_attr_reader(:argv) do
50
48
  # noinspection RubyResolve
51
49
  self[:argv].get_array_of_pointer(0, argc).map(&:read_string)
52
50
  end
53
51
 
54
- # @!visibility private
55
- def allocated
56
- self[:allocated]
57
- end
58
-
59
- # @!visibility private
60
- def inspect
61
- "#{self.class.name} - #{%i[argc argv allocated].to_h { |m| [m, send(m)] }}"
62
- end
63
-
64
52
  # Add an arg to this arg list
65
53
  # @param [String] arg
66
54
  def add(arg)
@@ -151,6 +139,8 @@ module FFI
151
139
  # Valid return values from parse! block
152
140
  FUSE_OPT_PROC_RETURN = { error: -1, keep: 1, handled: 0, discard: 0 }.freeze
153
141
 
142
+ ffi_attr_reader(:argc, :allocated?)
143
+
154
144
  def fuse_opt_proc(symbols, bool_opts, param_opts, ignore, &block)
155
145
  proc do |data, arg, key, out|
156
146
  key = symbols[key]
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../accessors'
4
+ require_relative '../boolean_int'
4
5
  require_relative 'fuse_loop_config'
5
6
  module FFI
6
7
  module Libfuse
7
- #
8
8
  # struct fuse_cmdline_opts {
9
9
  # int singlethread;
10
10
  # int foreground;
@@ -16,29 +16,32 @@ module FFI
16
16
  # int clone_fd;
17
17
  # unsigned int max_idle_threads;
18
18
  # };
19
+
20
+ # Command line options
19
21
  # @!visibility private
20
22
  class FuseCmdlineOpts < FFI::Struct
21
23
  include(FFI::Accessors)
22
24
 
23
- layout(
24
- single_thread: :int,
25
- foreground: :int,
26
- debug: :int,
27
- nodefault_subtype: :int,
25
+ spec = {
26
+ single_thread: :bool_int,
27
+ foreground: :bool_int,
28
+ debug: :bool_int,
29
+ nodefault_subtype: :bool_int,
28
30
  mountpoint: :string,
29
- show_version: :int,
30
- show_help: :int,
31
- clone_fd: :int,
32
- max_idle_threads: :int
33
- )
31
+ show_version: :bool_int,
32
+ show_help: :bool_int,
33
+ clone_fd: :bool_int,
34
+ max_idle_threads: :uint
35
+ }
36
+ spec[:max_threads] = :uint if FUSE_MINOR_VERSION >= 12
37
+
38
+ layout(spec)
34
39
 
35
- # int to booleans
36
- ffi_attr_reader(:single_thread, :foreground, :debug, :nodefault_subtype, :show_version, :show_help,
37
- :clone_fd) do |v|
38
- v != 0
39
- end
40
+ bool, = spec.partition { |_, v| v == :bool_int }
41
+ ffi_attr_reader(*bool.map { |k, _| "#{k}?" })
40
42
 
41
43
  ffi_attr_reader(:max_idle_threads, :mountpoint)
44
+ ffi_attr_reader(:max_threads) if FUSE_MINOR_VERSION >= 12
42
45
  end
43
46
  end
44
47
  end
@@ -10,7 +10,7 @@ module FFI
10
10
  # This structure is initialized from the arguments passed to fuse_new(), and then passed to the file system's init()
11
11
  # handler which should ensure that the configuration is compatible with the file system implementation.
12
12
  #
13
- # Some options can only be set via the filesystem init method (use_ino etc..) because the filesystem either
13
+ # Some options can only be set via the filesystem init method (:use_ino etc..) because the filesystem either
14
14
  # supports them or it doesn't.
15
15
  class FuseConfig < FFI::Struct
16
16
  include FFI::Accessors
@@ -40,7 +40,7 @@ module FFI
40
40
  # @!attribute [rw] negative_timeout
41
41
  # The timeout in seconds for which a negative lookup will be cached.
42
42
  #
43
- # This means, that if file did not exist (lookup retuned ENOENT), the lookup will only be redone after the
43
+ # This means, that if file did not exist (lookup returned ENOENT), the lookup will only be redone after the
44
44
  # timeout, and the file/directory will be assumed to not exist until then. A value of zero means that
45
45
  # negative lookups are not cached.
46
46
  #
@@ -55,7 +55,7 @@ module FFI
55
55
  # @return [Float]
56
56
  attr_timeout: :double,
57
57
 
58
- # @!attribute [rw] intr
58
+ # @!attribute [rw] intr?
59
59
  # Allow requests to be interrupted
60
60
  # @return [Boolean]
61
61
  intr: :bool_int,
@@ -80,7 +80,7 @@ module FFI
80
80
  # @return [Integer]
81
81
  remember: :int,
82
82
 
83
- # @!attribute [rw] hard_remove
83
+ # @!attribute [rw] hard_remove?
84
84
  # should open files be removed immediately
85
85
  #
86
86
  # The default behavior is that if an open file is deleted, the file is renamed to a hidden file
@@ -95,7 +95,7 @@ module FFI
95
95
  # @return [Boolean]
96
96
  hard_remove: :bool_int,
97
97
 
98
- # @!attribute [rw] use_ino
98
+ # @!attribute [rw] use_ino?
99
99
  # use filesystem provided inode values
100
100
  #
101
101
  # Honor the st_ino field in the functions getattr() and fill_dir(). This value is used to fill in the st_ino
@@ -109,8 +109,8 @@ module FFI
109
109
  # @return [Boolean]
110
110
  use_ino: :bool_int,
111
111
 
112
- # @!attribute [rw] readdir_ino
113
- # generate inodes for readdir even if {#use_ino} is set
112
+ # @!attribute [rw] readdir_ino?
113
+ # generate inodes for readdir even if {#use_ino?} is set
114
114
  #
115
115
  # If use_ino option is not given, still try to fill in the d_ino field in readdir(2). If the name was
116
116
  # previously looked up, and is still in the cache, the inode number found there will be used. Otherwise it
@@ -118,7 +118,7 @@ module FFI
118
118
  # @return [Boolean]
119
119
  readdir_ino: :bool_int,
120
120
 
121
- # @!attribute [rw] direct_io
121
+ # @!attribute [rw] direct_io?
122
122
  # disables the use of kernel page cache (file content cache) in the kernel for this filesystem.
123
123
  #
124
124
  # This has several affects:
@@ -135,13 +135,13 @@ module FFI
135
135
  # @return [Boolean]
136
136
  direct_io: :bool_int,
137
137
 
138
- # @!attribute [rw] kernel_cache
138
+ # @!attribute [rw] kernel_cache?
139
139
  # disables flushing the cache of the file contents on every open(2).
140
140
  #
141
141
  # This should only be enabled on filesystem where the file data is never changed externally (not through the
142
142
  # mounted FUSE filesystem). Thus it is not suitable for network filesystem and other intermediate filesystem.
143
143
  #
144
- # **Note**: if neither this option or {#direct_io} is specified data is still cached after the open(2),
144
+ # **Note**: if neither this option or {#direct_io?} is specified data is still cached after the open(2),
145
145
  # so a read(2) system call will not always initiate a read operation.
146
146
  #
147
147
  # Internally, enabling this option causes fuse to set {FuseFileInfo#keep_cache} overwriting any value that was
@@ -149,7 +149,7 @@ module FFI
149
149
  # @return [Boolean]
150
150
  kernel_cache: :bool_int,
151
151
 
152
- # @!attribute [rw] auto_cache
152
+ # @!attribute [rw] auto_cache?
153
153
  # invalidate cached data on open based on changes in file attributes
154
154
  #
155
155
  # This option is an alternative to `kernel_cache`. Instead of unconditionally keeping cached data, the cached
@@ -165,7 +165,7 @@ module FFI
165
165
  ac_attr_timeout_set: :bool_int,
166
166
  ac_attr_timeout: :double,
167
167
 
168
- # @!attribute [rw] nullpath_ok
168
+ # @!attribute [rw] nullpath_ok?
169
169
  # operations on open files and directories are ok to receive nil paths
170
170
  #
171
171
  # If this option is given the file-system handlers for the following operations will not receive path
@@ -185,21 +185,24 @@ module FFI
185
185
  layout(spec)
186
186
 
187
187
  # Find the attrs that have a corresponding setter (prefix set_ or suffix _set
188
+ # map attr => setter
188
189
  setters = spec.keys
189
- .map { |k| [k, k.to_s.sub(/^set_/, '').sub(/_set$/, '').to_sym] }
190
- .reject { |(s, a)| s == a }.to_h
190
+ .map { |k| [k.to_s.sub(/^set_/, '').sub(/_set$/, '').to_sym, k] }
191
+ .reject { |(s, a)| s == a }
192
+ .to_h
191
193
 
192
- setters.each do |(setter, attr)|
193
- ffi_attr_reader(attr) { |val| self[setter] ? val : nil }
194
+ ffi_attr_reader_method(*setters.keys) do
195
+ self[setters[__method__]] ? self[__method__] : nil
196
+ end
194
197
 
195
- ffi_attr_writer(attr) do |val|
196
- self[setter] = !val.nil?
197
- val || 0
198
- end
198
+ ffi_attr_writer_method(*setters.keys) do |val|
199
+ self[setters[__method__]] = !val.nil?
200
+ self[__method__] = val || 0
199
201
  end
200
202
 
201
- remaining = (spec.keys - setters.keys - setters.values).map { |a| spec[a] == :bool_int ? "#{a}?" : a }
202
- ffi_attr_accessor(*remaining)
203
+ ffi_attr_reader(:show_help?, :debug?)
204
+ remaining = (spec.keys - setters.keys - setters.values - %i[show_help modules debug])
205
+ ffi_attr_accessor(*remaining.map { |a| spec[a] == :bool_int ? "#{a}?" : a })
203
206
  end
204
207
  end
205
208
  end
@@ -326,7 +326,7 @@ module FFI
326
326
  # or unwanted
327
327
  # @return [Array<Symbol>]
328
328
  # @see capable
329
- ffi_attr_reader(:want, simple: false) do |*caps, **h|
329
+ ffi_attr_reader_method(:want) do |*caps, **h|
330
330
  next self[:want] if caps.empty? && h.empty?
331
331
 
332
332
  h.merge!(caps.pop) if caps.last.is_a?(Hash)
@@ -15,7 +15,8 @@ module FFI
15
15
  base[:umask] = :mode_t if FUSE_VERSION >= 28
16
16
  layout base
17
17
 
18
- ffi_attr_reader(*members, simple: false) do
18
+ # Define readers, safe from null access
19
+ ffi_attr_reader_method(*members) do
19
20
  m = __method__
20
21
 
21
22
  # Use overrides if they are available, or the default context if the underlying memory is invalid