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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/ffi/accessors.rb +418 -106
- data/lib/ffi/devt.rb +33 -7
- data/lib/ffi/flock.rb +31 -27
- data/lib/ffi/libfuse/adapter/context.rb +1 -1
- data/lib/ffi/libfuse/adapter/debug.rb +1 -1
- data/lib/ffi/libfuse/adapter/fuse2_compat.rb +7 -7
- data/lib/ffi/libfuse/adapter/fuse3_support.rb +7 -7
- data/lib/ffi/libfuse/adapter/interrupt.rb +1 -1
- data/lib/ffi/libfuse/adapter/pathname.rb +1 -1
- data/lib/ffi/libfuse/adapter/ruby.rb +1 -1
- data/lib/ffi/libfuse/adapter/safe.rb +1 -1
- data/lib/ffi/libfuse/filesystem/virtual_dir.rb +2 -2
- data/lib/ffi/libfuse/filesystem/virtual_file.rb +1 -1
- data/lib/ffi/libfuse/filesystem/virtual_link.rb +1 -1
- data/lib/ffi/libfuse/fuse3.rb +5 -5
- data/lib/ffi/libfuse/fuse_args.rb +9 -19
- data/lib/ffi/libfuse/fuse_cmdline_opts.rb +19 -16
- data/lib/ffi/libfuse/fuse_config.rb +25 -22
- data/lib/ffi/libfuse/fuse_conn_info.rb +1 -1
- data/lib/ffi/libfuse/fuse_context.rb +2 -1
- data/lib/ffi/libfuse/fuse_loop_config.rb +68 -20
- data/lib/ffi/libfuse/main.rb +7 -3
- data/lib/ffi/libfuse/test_helper.rb +4 -6
- data/lib/ffi/libfuse/version.rb +1 -1
- data/lib/ffi/stat.rb +16 -9
- data/lib/ffi/stat_vfs.rb +1 -2
- data/lib/ffi/struct_wrapper.rb +6 -4
- metadata +2 -2
data/lib/ffi/flock.rb
CHANGED
@@ -18,32 +18,36 @@ module FFI
|
|
18
18
|
|
19
19
|
include(Accessors)
|
20
20
|
|
21
|
-
layout(
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
@@ -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
|
15
|
+
super
|
16
16
|
end
|
17
17
|
|
18
18
|
def truncate(path, size, fuse_file_info = nil)
|
19
|
-
super
|
19
|
+
super
|
20
20
|
end
|
21
21
|
|
22
22
|
def init(fuse_conn_info, fuse_config = nil)
|
23
|
-
super
|
23
|
+
super
|
24
24
|
end
|
25
25
|
|
26
26
|
def chown(path, uid, gid, fuse_file_info = nil)
|
27
|
-
super
|
27
|
+
super
|
28
28
|
end
|
29
29
|
|
30
30
|
def chmod(path, mode, fuse_file_info = nil)
|
31
|
-
super
|
31
|
+
super
|
32
32
|
end
|
33
33
|
|
34
34
|
def utimens(path, times, fuse_file_info = nil)
|
35
|
-
super
|
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
|
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
|
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
|
34
|
+
super
|
35
35
|
end
|
36
36
|
|
37
37
|
def chown(*args)
|
38
38
|
args.pop
|
39
|
-
super
|
39
|
+
super
|
40
40
|
end
|
41
41
|
|
42
42
|
def chmod(*args)
|
43
43
|
args.pop
|
44
|
-
super
|
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
|
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
|
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
|
74
|
+
super
|
75
75
|
end
|
76
76
|
|
77
77
|
def fuse_respond_to(fuse_callback)
|
@@ -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
|
341
|
+
o = super if fuse_super_respond_to?(:init)
|
342
342
|
handles << o if o
|
343
343
|
end
|
344
344
|
|
@@ -41,7 +41,7 @@ module FFI
|
|
41
41
|
|
42
42
|
def initialize(accounting: Accounting.new)
|
43
43
|
@entries = {}
|
44
|
-
super
|
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.
|
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)
|
data/lib/ffi/libfuse/fuse3.rb
CHANGED
@@ -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(
|
149
|
-
Libfuse.fuse_loop_mt3(@fuse, FuseLoopConfig.
|
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
|
-
|
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] =
|
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
|
-
|
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
|
-
|
24
|
-
single_thread: :
|
25
|
-
foreground: :
|
26
|
-
debug: :
|
27
|
-
nodefault_subtype: :
|
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: :
|
30
|
-
show_help: :
|
31
|
-
clone_fd: :
|
32
|
-
max_idle_threads: :
|
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
|
-
|
36
|
-
ffi_attr_reader(
|
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
|
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
|
190
|
-
.reject { |(s, a)| s == a }
|
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.
|
193
|
-
|
194
|
+
ffi_attr_reader_method(*setters.keys) do
|
195
|
+
self[setters[__method__]] ? self[__method__] : nil
|
196
|
+
end
|
194
197
|
|
195
|
-
|
196
|
-
|
197
|
-
|
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
|
-
|
202
|
-
|
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
|
-
|
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
|
-
|
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
|