Module: InVFS

Defined in:
lib/invfs.rb,
lib/invfs.rb,
lib/invfs.rb,
lib/invfs.rb,
lib/invfs/zip.rb,
lib/invfs/unionfs.rb,
lib/invfs/extensions.rb,
lib/invfs/stringmapfs.rb

Defined Under Namespace

Modules: Extensions, Kernel Classes: StringMapFS, UnionFS, Zip

Constant Summary collapse

TOPLEVEL_BINDING =
binding.freeze
DEFAULT_MAX_LOADSIZE =
2.MiB
MINIMAL_MAX_LOADSIZE =
256.KiB
MAXIMAM_MAX_LOADSIZE =
64.MiB
MAX_LOADSIZE =
maxloadsize.clamp(MINIMAL_MAX_LOADSIZE, MAXIMAM_MAX_LOADSIZE)
LOADED_PREFIX =

$LOADED_FEATURES に追加される接頭辞

"<inVFS>:".freeze
MultipleDirectory =
UnionFS

Class Method Summary collapse

Class Method Details

.findlib(vfs, lib, relative) ⇒ Object



26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
# File 'lib/invfs.rb', line 26

def InVFS.findlib(vfs, lib, relative)
  if relative
    if vfs.file?(lib)
      lib
    else
      nil
    end
  else
    case
    when vfs.file?(lib)
      lib
    when vfs.file?(librb = lib + ".rb")
      librb
    when vfs.file?(libso = lib + ".so")
      libso
    else
      nil
    end
  end
end

.findpath(lib, relative) ⇒ Object

call-seq:

findpath(absolute_lib_path, relative) { |vfs, subpath| ... }


60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/invfs.rb', line 60

def InVFS.findpath(lib, relative)
  if relative || Pathname(lib).absolute?
    # 絶対パス表記でのライブラリ指定、または require_relative の呼び出し元

    # NOTE: LOAD_PATH ($:) の順序を優先するか?
    # NOTE: 一致するティレクトリ階層の深さを優先するか?
    # NOTE: => とりあえずは順序を優先しておく

    $:.each do |vfs|
      #__BREAKHERE__
      dir = String(vfs.to_path)
      dir += "/" unless dir.empty? || dir[-1] == "/"
      (a, b, c) = lib.partition(dir)
      next unless a.empty? && !b.empty? && !c.empty?
      next unless vfs = mapvfs(vfs)
      yield(vfs, c)
    end
  else
    $:.each do |vfs|
      next unless vfs = mapvfs(vfs)
      yield(vfs, lib)
    end
  end

  nil
end

.findvfs(lib, relative) ⇒ Object



47
48
49
50
51
52
53
54
# File 'lib/invfs.rb', line 47

def InVFS.findvfs(lib, relative)
  findpath(lib, relative) do |vfs, sub|
    next unless sub = findlib(vfs, sub, relative)
    return nil if vfs.__native_file_path?
    next if vfs.size(sub) > MAX_LOADSIZE
    return [vfs, sub]
  end
end

.loaded?(vfs, lib) ⇒ Boolean

Returns:

  • (Boolean)


116
117
118
# File 'lib/invfs.rb', line 116

def InVFS.loaded?(vfs, lib)
  !!$".include?(LOADED_PREFIX + File.join(vfs, lib))
end

.mapvfs(vfs) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
# File 'lib/invfs.rb', line 102

def InVFS.mapvfs(vfs)
  return vfs unless vfs.it_a_file?

  v = @mapped_list[vfs]
  return v if v

  @handler_list.each do |handler|
    next unless handler.probe(vfs)
    return @mapped_list[vfs] = handler.open(vfs)
  end

  nil
end

.regist(handler) ⇒ Object



90
91
92
93
94
95
96
97
98
99
100
# File 'lib/invfs.rb', line 90

def InVFS.regist(handler)
  unless handler.respond_to?(:probe) && handler.respond_to?(:open)
    raise "%s - #<%s:0x08x>" %
      ["need ``.probe'' and ``.open'' methods for vfs handler",
       handler.class, handler.object_id]
  end

  @handler_list << handler

  nil
end

.require_in(vfs, path) ⇒ Object



120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
# File 'lib/invfs.rb', line 120

def InVFS.require_in(vfs, path)
  code = String(vfs.read(path))
  loadpath = File.join(vfs, path)
  unless File.extname(path) == ".so"
    unless code.encoding == Encoding::UTF_8
      code = code.dup if code.frozen?
      code.force_encoding(Encoding::UTF_8)
    end

    eval code, InVFS::TOPLEVEL_BINDING.dup, loadpath, 1
  else
    Dir.mktmpdir do |dir|
      tempname = File.join(dir, File.basename(path))
      mode = File::CREAT | File::WRONLY | File::EXCL | File::BINARY
      File.open(tempname, mode, 0700) { |fd| fd << code }
      require! tempname
      $".pop # 偽装したライブラリパスであるため、削除
    end
  end

  $" << (LOADED_PREFIX + loadpath)

  true
end

.stringmap(*map) ⇒ Object



183
184
185
186
187
# File 'lib/invfs.rb', line 183

def InVFS.stringmap(*map)
  require_relative "invfs/stringmapfs"

  StringMapFS.new(*map)
end

.union(*dirs) ⇒ Object



177
178
179
180
181
# File 'lib/invfs.rb', line 177

def InVFS.union(*dirs)
  require_relative "invfs/unionfs"

  UnionFS.new(*dirs)
end

.zip(*args) ⇒ Object



189
190
191
192
193
# File 'lib/invfs.rb', line 189

def InVFS.zip(*args)
  require_relative "invfs/zip"

  Zip.new(*args)
end