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.
@@ -1,43 +1,91 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative '../accessors'
4
+ require_relative '../boolean_int'
4
5
 
5
6
  module FFI
6
7
  module Libfuse
7
- # struct fuse_loop_config {
8
- # int clone_fd;
9
- # unsigned int max_idle_threads;
10
- # };
8
+ # For native fuse_loop_mt only
11
9
  class FuseLoopConfig < FFI::Struct
12
10
  include(FFI::Accessors)
13
11
 
14
- layout(
15
- clone_fd: :int,
16
- max_idle: :int
17
- )
18
-
19
- # @!attribute [rw] clone_fd
12
+ # @!attribute [w] clone_fd?
20
13
  # whether to use separate device fds for each thread (may increase performance)
21
14
  # Unused by ffi-libfuse as we do not call fuse_loop_mt
22
15
  # @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
16
 
31
- # @!attribute [rw] max_idle_threads
17
+ # @!attribute [w] max_idle_threads
32
18
  # The maximum number of available worker threads before they start to get deleted when they become idle. If not
33
19
  # specified, the default is 10.
34
20
  #
35
21
  # Adjusting this has performance implications; a very small number of threads in the pool will cause a lot of
36
22
  # thread creation and deletion overhead and performance may suffer. When set to 0, a new thread will be created
37
23
  # to service every operation.
38
- #
24
+ # @deprecated at Fuse 3.12. Use max_threads instead
39
25
  # @return [Integer] the maximum number of threads to leave idle
40
- ffi_attr_accessor(:max_idle)
26
+
27
+ # @!attribute [w] max_threads
28
+ # @return [Integer]
29
+ # @since Fuse 3.12
30
+
31
+ if FUSE_VERSION >= 312
32
+ layout(
33
+ version_id: :int,
34
+ clone_fd: :bool_int,
35
+ max_idle_threads: :uint,
36
+ max_threads: :uint
37
+ )
38
+
39
+ Libfuse.attach_function :fuse_loop_cfg_create, [], by_ref
40
+ Libfuse.attach_function :fuse_loop_cfg_destroy, [:pointer], :void
41
+
42
+ ffi_attr_reader(:clone_fd?)
43
+ Libfuse.attach_function :fuse_loop_cfg_set_clone_fd, %i[pointer uint], :void
44
+ def clone_fd=(bool_val)
45
+ Libfuse.fuse_loop_cfg_set_clone_fd(to_ptr, bool_val ? 1 : 0)
46
+ end
47
+
48
+ ffi_attr_reader(:max_idle_threads)
49
+ Libfuse.attach_function :fuse_loop_cfg_set_idle_threads, %i[pointer uint], :uint
50
+ def max_idle_threads=(val)
51
+ Libfuse.fuse_loop_cfg_set_idle_threads(to_ptr, val) if val
52
+ end
53
+
54
+ Libfuse.attach_function :fuse_loop_cfg_set_max_threads, %i[pointer uint], :uint
55
+ ffi_attr_reader(:max_threads)
56
+ def max_threads=(val)
57
+ Libfuse.fuse_loop_cfg_set_max_threads(to_ptr, val) if val
58
+ end
59
+
60
+ class << self
61
+ def create(max_idle_threads: nil, max_threads: 10, clone_fd: false, **_)
62
+ cfg = Libfuse.fuse_loop_cfg_create
63
+ ObjectSpace.define_finalizer(cfg, finalizer(cfg.to_ptr))
64
+ cfg.clone_fd = clone_fd
65
+ cfg.max_idle_threads = max_idle_threads if max_idle_threads
66
+ cfg.max_threads = max_threads if max_threads
67
+ cfg
68
+ end
69
+
70
+ def finalizer(ptr)
71
+ proc { |_| Libfuse.fuse_loop_cfg_destroy(ptr) }
72
+ end
73
+ end
74
+ else
75
+ layout(
76
+ clone_fd: :bool_int,
77
+ max_idle_threads: :uint
78
+ )
79
+
80
+ ffi_attr_accessor(:clone_fd?)
81
+ ffi_attr_accessor(:max_idle_threads)
82
+
83
+ class << self
84
+ def create(clone_fd: false, max_idle_threads: 10, **_)
85
+ new.fill(max_idle_threads: max_idle_threads, clone_fd: clone_fd)
86
+ end
87
+ end
88
+ end
41
89
  end
42
90
  end
43
91
  end
@@ -189,12 +189,16 @@ module FFI
189
189
  # @!method fuse_traps
190
190
  # @abstract
191
191
  # Passed to {FuseCommon#run} to allow filesystem to handle custom signal traps. These traps
192
- # are merged over those from {FuseCommon#default_traps}
193
- # @return [Hash<String|Symbol|Integer,String|Proc>]
192
+ # are merged over those from {FuseCommon#default_traps}. A nil value can be used to avoid a default trap
193
+ # being set.
194
+ # @return [Hash<String|Symbol|Integer,String|Proc|nil>]
194
195
  # map of signal name or number to signal handler as per Signal.trap
195
196
  # @example
196
197
  # def fuse_traps
197
- # { HUP: ->() { reload() }}
198
+ # {
199
+ # HUP: ->() { reload() },
200
+ # INT: nil
201
+ # }
198
202
  # end
199
203
 
200
204
  # @!method fuse_version
@@ -73,7 +73,7 @@ module FFI
73
73
  return [o, e, s.exitstatus] unless err
74
74
 
75
75
  warn "Errors\n#{e}" unless e.empty?
76
- warn "Output\n#{o}" unless o.empty? Minitest::Assertion, StandardError => e
76
+ warn "Output\n#{o}" unless o.empty?
77
77
  raise err
78
78
  end
79
79
 
@@ -87,7 +87,7 @@ module FFI
87
87
  if mac_fuse?
88
88
  system("diskutil unmount force #{mnt} >/dev/null 2>&1")
89
89
  else
90
- system("fusermount -zu #{mnt} >/dev/null 2>&1")
90
+ system("fusermount#{FUSE_MAJOR_VERSION == 3 ? '3' : ''} -zu #{mnt} >/dev/null 2>&1")
91
91
  end
92
92
  end
93
93
 
@@ -107,10 +107,8 @@ module FFI
107
107
  private
108
108
 
109
109
  def open3_filesystem(args, env, filesystem, fsname, mnt)
110
- if defined?(Bundler)
111
- Bundler.with_unbundled_env do
112
- Open3.capture3(env, 'bundle', 'exec', filesystem.to_s, mnt, "-ofsname=#{fsname}", *args, binmode: true)
113
- end
110
+ if ENV['BUNDLER_GEMFILE']
111
+ Open3.capture3(env, 'bundle', 'exec', filesystem.to_s, mnt, "-ofsname=#{fsname}", *args, binmode: true)
114
112
  else
115
113
  Open3.capture3(env, filesystem.to_s, mnt, "-ofsname=#{fsname}", *args, binmode: true)
116
114
  end
@@ -3,6 +3,6 @@
3
3
  module FFI
4
4
  # Ruby FFI Binding for [libfuse](https://github.com/libfuse/libfuse)
5
5
  module Libfuse
6
- VERSION = '0.4.0'
6
+ VERSION = '0.4.1'
7
7
  end
8
8
  end
data/lib/ffi/stat.rb CHANGED
@@ -34,9 +34,9 @@ module FFI
34
34
  int_members = Native
35
35
  .members
36
36
  .select { |m| m.to_s.start_with?('st_') && !m.to_s.end_with?('timespec') }
37
- .map { |m| m[3..].to_sym }
37
+ .to_h { |m| [:"#{m[3..]}", m] }
38
38
 
39
- ffi_attr_accessor(*int_members, format: 'st_%s')
39
+ ffi_attr_accessor(**int_members)
40
40
 
41
41
  # @!attribute [rw] atime
42
42
  # @return [Time] time of last access
@@ -47,12 +47,13 @@ module FFI
47
47
  # @!attribute [rw] ctime
48
48
  # @return [Time] time of last status change
49
49
 
50
- time_members = Native.members.select { |m| m.to_s =~ /^st_.*timespec$/ }.map { |m| m[3..-5].to_sym }
50
+ time_members = Native.members.select { |m| m.to_s =~ /^st_.*timespec$/ }.to_h { |m| [:"#{m[3..-5]}", m] }
51
51
 
52
- ffi_attr_reader(*time_members, format: 'st_%sspec', &:time)
52
+ ffi_attr_reader(**time_members, &:time)
53
53
 
54
- ffi_attr_writer(*time_members, format: 'st_%sspec', simple: false) do |sec, nsec = 0|
55
- self[__method__[0..-2].to_sym].set_time(sec, nsec)
54
+ ffi_attr_writer_method(**time_members) do |sec, nsec = 0|
55
+ _attr, member = ffi_attr_writer_member(__method__)
56
+ self[member].set_time(sec, nsec)
56
57
  end
57
58
 
58
59
  # Fill content for a regular file
@@ -164,16 +165,22 @@ module FFI
164
165
  end
165
166
 
166
167
  class << self
167
- # @!method file(stat,**fields)
168
+ # @!method file(**fields)
168
169
  # @return [Stat]
169
170
  # @raise [SystemCallError]
170
171
  # @see Stat#file
171
172
 
172
- # @!method dir(stat,**fields)
173
+ # @!method dir(**fields)
173
174
  # @return [Stat]
174
175
  # @raise [SystemCallError]
175
176
  # @see Stat#dir
176
- %i[file dir].each { |m| define_method(m) { |stat = new, **args| stat.send(m, **args) } }
177
+
178
+ # @!method symlink(**fields)
179
+ # @return [Stat]
180
+ # @raise [SystemCallError]
181
+ # @see Stat#symlink
182
+
183
+ %i[file dir symlink].each { |m| define_method(m) { |stat = new, **args| stat.send(m, **args) } }
177
184
  alias directory dir
178
185
 
179
186
  # @!method from(file, stat = new(), follow: false)
data/lib/ffi/stat_vfs.rb CHANGED
@@ -75,8 +75,7 @@ module FFI
75
75
  # @!attribute [rw] namemax
76
76
  # @return [Integer] Maximum filename length
77
77
 
78
- int_members = members.grep(/^f_/).map { |m| m[2..].to_sym }
79
- ffi_attr_accessor(*int_members, format: 'f_%s')
78
+ ffi_attr_accessor(**members.grep(/^f_/).to_h { |m| [m[2..].to_sym, m] })
80
79
 
81
80
  extend FFI::Library
82
81
  ffi_lib FFI::Library::LIBC
@@ -27,13 +27,13 @@ module FFI
27
27
  return Pointer::NULL if value.nil?
28
28
 
29
29
  value = value.native if value.is_a?(StructWrapper)
30
- super(value, ctx)
30
+ super
31
31
  end
32
32
 
33
33
  def from_native(value, ctx)
34
34
  return nil if value.null?
35
35
 
36
- native = super(value, ctx)
36
+ native = super
37
37
  @wrapper_class.new(native)
38
38
  end
39
39
  end
@@ -100,12 +100,14 @@ module FFI
100
100
 
101
101
  # Get attribute
102
102
  def [](member_or_attr)
103
- @native[self.class.ffi_attr_readers.fetch(member_or_attr, member_or_attr)]
103
+ _attr, member = ffi_attr_reader_member(member_or_attr, member_or_attr)
104
+ @native[member]
104
105
  end
105
106
 
106
107
  # Set attribute
107
108
  def []=(member_or_attr, val)
108
- @native[self.class.ffi_attr_writers.fetch(member_or_attr, member_or_attr)] = val
109
+ _attr, member = ffi_attr_writer_member(member_or_attr, member_or_attr)
110
+ @native[member] = val
109
111
  end
110
112
 
111
113
  # Pass unimplemented methods on to {#native} underlying struct
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.0
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Grant Gardner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-21 00:00:00.000000000 Z
11
+ date: 2024-10-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ffi