virtfs 0.0.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 +7 -0
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +8 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +154 -0
- data/Rakefile +5 -0
- data/lib/virtfs-nativefs-thick.rb +1 -0
- data/lib/virtfs-nativefs-thin.rb +1 -0
- data/lib/virtfs.rb +38 -0
- data/lib/virtfs/activation.rb +97 -0
- data/lib/virtfs/block_io.rb +140 -0
- data/lib/virtfs/byte_range.rb +71 -0
- data/lib/virtfs/context.rb +300 -0
- data/lib/virtfs/context_manager.rb +175 -0
- data/lib/virtfs/context_switch_class_methods.rb +96 -0
- data/lib/virtfs/delegate_module.rb +40 -0
- data/lib/virtfs/dir_instance_delegate.rb +3 -0
- data/lib/virtfs/exception.rb +13 -0
- data/lib/virtfs/file_instance_delegate.rb +3 -0
- data/lib/virtfs/file_modes_and_options.rb +293 -0
- data/lib/virtfs/find_class_methods.rb +106 -0
- data/lib/virtfs/io_buffer.rb +133 -0
- data/lib/virtfs/io_instance_delegate.rb +3 -0
- data/lib/virtfs/kernel.rb +146 -0
- data/lib/virtfs/nativefs/thick.rb +30 -0
- data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
- data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
- data/lib/virtfs/nativefs/thin.rb +32 -0
- data/lib/virtfs/nativefs/thin/dir.rb +30 -0
- data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
- data/lib/virtfs/nativefs/thin/file.rb +112 -0
- data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
- data/lib/virtfs/protofs/protofs.rb +7 -0
- data/lib/virtfs/protofs/protofs_base.rb +12 -0
- data/lib/virtfs/protofs/protofs_dir.rb +13 -0
- data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
- data/lib/virtfs/protofs/protofs_file.rb +27 -0
- data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
- data/lib/virtfs/stat.rb +100 -0
- data/lib/virtfs/thin_dir_delegator.rb +79 -0
- data/lib/virtfs/thin_file_delegator.rb +77 -0
- data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
- data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
- data/lib/virtfs/v_dir.rb +238 -0
- data/lib/virtfs/v_file.rb +480 -0
- data/lib/virtfs/v_io.rb +243 -0
- data/lib/virtfs/v_pathname.rb +128 -0
- data/lib/virtfs/version.rb +3 -0
- data/spec/activate_spec.rb +202 -0
- data/spec/chroot_spec.rb +120 -0
- data/spec/context_manager_class_spec.rb +246 -0
- data/spec/context_manager_instance_spec.rb +255 -0
- data/spec/context_spec.rb +335 -0
- data/spec/data/UTF-16LE-data.txt +0 -0
- data/spec/data/UTF-8-data.txt +212 -0
- data/spec/dir_class_spec.rb +506 -0
- data/spec/dir_instance_spec.rb +208 -0
- data/spec/file_class_spec.rb +2106 -0
- data/spec/file_instance_spec.rb +154 -0
- data/spec/file_modes_and_options_spec.rb +1556 -0
- data/spec/find_spec.rb +142 -0
- data/spec/io_bufferio_size_shared_examples.rb +371 -0
- data/spec/io_bufferio_size_spec.rb +861 -0
- data/spec/io_bufferio_spec.rb +801 -0
- data/spec/io_class_spec.rb +145 -0
- data/spec/io_instance_spec.rb +516 -0
- data/spec/kernel_spec.rb +285 -0
- data/spec/mount_spec.rb +186 -0
- data/spec/nativefs_local_root_spec.rb +132 -0
- data/spec/path_spec.rb +39 -0
- data/spec/spec_helper.rb +126 -0
- data/tasks/rspec.rake +3 -0
- data/tasks/yard.rake +7 -0
- data/test/UTF-8-demo.txt +212 -0
- data/test/bench.rb +18 -0
- data/test/bio_internal_test.rb +45 -0
- data/test/delegate_io.rb +31 -0
- data/test/delegate_module.rb +62 -0
- data/test/encode_test.rb +42 -0
- data/test/enoent_test.rb +30 -0
- data/test/namespace_test.rb +42 -0
- data/test/read_block_valid_encoding.rb +44 -0
- data/test/read_test.rb +78 -0
- data/test/stream_readers.rb +46 -0
- data/test/utf-16-demo.txt +0 -0
- data/test/utf8_to_utf16.rb +77 -0
- data/test/wrapper_test.rb +34 -0
- data/virtfs.gemspec +29 -0
- metadata +230 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
module VirtFS
|
2
|
+
# VirtFS Find Class representation - implements the core Ruby Find methods,
|
3
|
+
# dispatching to underlying mounted VirtFS filesystems
|
4
|
+
module FindClassMethods
|
5
|
+
#
|
6
|
+
# Modified version of Find.find:
|
7
|
+
# - Accepts only a single path.
|
8
|
+
# - Can be restricted by depth - optimization for glob searches.
|
9
|
+
# - Will work with VirtFS, even when it's not active.
|
10
|
+
#
|
11
|
+
# @param path [String] starting directory of the find
|
12
|
+
# @param max_depth [Integer] max number of levels to decend befroelookup
|
13
|
+
# @yield files found
|
14
|
+
#
|
15
|
+
def find(path, max_depth = nil)
|
16
|
+
raise SystemCallError.new(path, Errno::ENOENT::Errno) unless VirtFS::VFile.exist?(path)
|
17
|
+
block_given? || (return enum_for(__method__, path, max_depth))
|
18
|
+
|
19
|
+
depths = [0]
|
20
|
+
paths = [path.dup]
|
21
|
+
|
22
|
+
while (file = paths.shift)
|
23
|
+
depth = depths.shift
|
24
|
+
catch(:prune) do
|
25
|
+
yield file.dup.taint
|
26
|
+
begin
|
27
|
+
s = VirtFS::VFile.lstat(file)
|
28
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
29
|
+
next
|
30
|
+
end
|
31
|
+
if s.directory?
|
32
|
+
next if depth + 1 > max_depth if max_depth
|
33
|
+
begin
|
34
|
+
fs = VirtFS::VDir.entries(file)
|
35
|
+
rescue Errno::ENOENT, Errno::EACCES, Errno::ENOTDIR, Errno::ELOOP, Errno::ENAMETOOLONG
|
36
|
+
next
|
37
|
+
end
|
38
|
+
fs.sort!
|
39
|
+
fs.reverse_each do |f|
|
40
|
+
next if f == "." || f == ".."
|
41
|
+
f = VfsRealFile.join(file, f)
|
42
|
+
paths.unshift f.untaint
|
43
|
+
depths.unshift depth + 1
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Implementation of Find.prune
|
51
|
+
#
|
52
|
+
# @raise [RuntimeError] always
|
53
|
+
def prune
|
54
|
+
throw :prune
|
55
|
+
end
|
56
|
+
|
57
|
+
GLOB_CHARS = '*?[{'
|
58
|
+
def glob_str?(str)
|
59
|
+
str.gsub(/\\./, "X").count(GLOB_CHARS) != 0
|
60
|
+
end
|
61
|
+
|
62
|
+
# Returns files matching glob pattern
|
63
|
+
#
|
64
|
+
# @api private
|
65
|
+
# @param glob_pattern [String,Regex] pattern to search for
|
66
|
+
# @return [String] paths to files found
|
67
|
+
#
|
68
|
+
def dir_and_glob(glob_pattern)
|
69
|
+
glob_path = Pathname.new(glob_pattern)
|
70
|
+
|
71
|
+
if glob_path.absolute?
|
72
|
+
search_path = VfsRealFile::SEPARATOR
|
73
|
+
specified_path = VfsRealFile::SEPARATOR
|
74
|
+
else
|
75
|
+
search_path = dir_getwd
|
76
|
+
specified_path = nil
|
77
|
+
end
|
78
|
+
|
79
|
+
components = glob_path.each_filename.to_a
|
80
|
+
while (comp = components.shift)
|
81
|
+
if glob_str?(comp)
|
82
|
+
components.unshift(comp)
|
83
|
+
break
|
84
|
+
end
|
85
|
+
search_path = VfsRealFile.join(search_path, comp)
|
86
|
+
if specified_path
|
87
|
+
specified_path = VfsRealFile.join(specified_path, comp)
|
88
|
+
else
|
89
|
+
specified_path = comp
|
90
|
+
end
|
91
|
+
end
|
92
|
+
return normalize_path(search_path), specified_path, VfsRealFile.join(components)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Return max levels which glob pattern may resolve to
|
96
|
+
#
|
97
|
+
# @api private
|
98
|
+
# @param glob_pattern [String,Regex] pattern to search for
|
99
|
+
# @return [Integer] max levels which pattern may match
|
100
|
+
def glob_depth(glob_pattern)
|
101
|
+
path_components = Pathname(glob_pattern).each_filename.to_a
|
102
|
+
return nil if path_components.include?('**')
|
103
|
+
path_components.length
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module VirtFS
|
2
|
+
# I/O Buffer utility class, provides a fixed length byte buffer
|
3
|
+
# for I/O operations
|
4
|
+
class IOBuffer
|
5
|
+
attr_accessor :min_buf_sz, :external_encoding, :sync
|
6
|
+
attr_reader :buffer, :range
|
7
|
+
|
8
|
+
MAX_CHAR_LEN = 8
|
9
|
+
|
10
|
+
def initialize(io_obj, min_buf_sz)
|
11
|
+
@io_obj = io_obj
|
12
|
+
@min_buf_sz = min_buf_sz
|
13
|
+
@binary_encoding = Encoding.find("ASCII-8BIT")
|
14
|
+
@buffer = ""
|
15
|
+
@range = ByteRange.new
|
16
|
+
@write_range = ByteRange.new
|
17
|
+
@sync = false
|
18
|
+
end
|
19
|
+
|
20
|
+
def cover_range(pos, len)
|
21
|
+
len = adjust_len_to_eof(len, pos)
|
22
|
+
end_pos = pos + len - 1
|
23
|
+
|
24
|
+
return if @range.include?(pos) && @range.include?(end_pos)
|
25
|
+
|
26
|
+
if @range.include?(pos)
|
27
|
+
truncate_left(pos)
|
28
|
+
extend_right(len)
|
29
|
+
return
|
30
|
+
end
|
31
|
+
|
32
|
+
flush # If write data, flush.
|
33
|
+
raw_read_len = adjust_len_to_eof([@min_buf_sz, len].max, pos)
|
34
|
+
@buffer = @io_obj.fs_io_obj.raw_read(pos, raw_read_len)
|
35
|
+
@range.set(pos, pos + raw_read_len - 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
def extend_right(len)
|
39
|
+
raw_read_len = adjust_len_to_eof([@min_buf_sz, len].max, @range.last)
|
40
|
+
rv = @io_obj.fs_io_obj.raw_read(@range.last + 1, raw_read_len)
|
41
|
+
@buffer << rv
|
42
|
+
@range.last += raw_read_len
|
43
|
+
end
|
44
|
+
|
45
|
+
def truncate_left(pos)
|
46
|
+
flush if @write_range.include?(pos) # If pos is within write_range, flush.
|
47
|
+
offset = buf_offset(pos)
|
48
|
+
return if offset == 0
|
49
|
+
@buffer = @buffer[offset..-1]
|
50
|
+
@range.first += offset
|
51
|
+
end
|
52
|
+
|
53
|
+
def prepend_bytes(str)
|
54
|
+
str = str.dup
|
55
|
+
str.force_encoding(@binary_encoding)
|
56
|
+
prepend(str)
|
57
|
+
end
|
58
|
+
|
59
|
+
def prepend_str(str)
|
60
|
+
str = str.dup
|
61
|
+
str.encode!(@io_obj.external_encoding) if @io_obj.external_encoding
|
62
|
+
str.force_encoding(@binary_encoding)
|
63
|
+
prepend(str)
|
64
|
+
end
|
65
|
+
|
66
|
+
# for unget, data does not get written - never in write_range.
|
67
|
+
def prepend(str)
|
68
|
+
@buffer.insert(0, str)
|
69
|
+
@range.first -= str.bytesize
|
70
|
+
str.bytesize
|
71
|
+
end
|
72
|
+
|
73
|
+
def write_to_buffer(pos, str)
|
74
|
+
len = str.bytesize
|
75
|
+
end_pos = pos + len - 1
|
76
|
+
flush unless @write_range.contiguous?(pos, end_pos)
|
77
|
+
@write_range.expand(pos, end_pos)
|
78
|
+
@range.expand(@write_range)
|
79
|
+
@buffer[buf_offset(pos), len] = str
|
80
|
+
flush if @sync
|
81
|
+
len
|
82
|
+
end
|
83
|
+
|
84
|
+
def adjust_len_to_eof(len, pos)
|
85
|
+
return @io_obj.end_byte_addr - pos + 1 if (pos + len - 1) > @io_obj.end_byte_addr
|
86
|
+
len
|
87
|
+
end
|
88
|
+
|
89
|
+
def get_byte(pos)
|
90
|
+
cover_range(pos, 1)
|
91
|
+
@buffer.getbyte(buf_offset(pos))
|
92
|
+
end
|
93
|
+
|
94
|
+
def get_char(pos)
|
95
|
+
max_char_len = adjust_len_to_eof(MAX_CHAR_LEN, pos)
|
96
|
+
cover_range(pos, max_char_len)
|
97
|
+
offset = buf_offset(pos)
|
98
|
+
(1..max_char_len).each do |len|
|
99
|
+
char = @buffer[offset, len]
|
100
|
+
char.force_encoding(@io_obj.external_encoding)
|
101
|
+
return char if char.valid_encoding?
|
102
|
+
end
|
103
|
+
raise "Invalid byte sequence"
|
104
|
+
end
|
105
|
+
|
106
|
+
def get_str(pos, len)
|
107
|
+
len = adjust_len_to_eof(len, pos)
|
108
|
+
cover_range(pos, len)
|
109
|
+
@buffer[buf_offset(pos), len]
|
110
|
+
end
|
111
|
+
|
112
|
+
def flush
|
113
|
+
return if @write_range.empty?
|
114
|
+
offset = buf_offset(@write_range.first)
|
115
|
+
length = @write_range.length
|
116
|
+
rv = @io_obj.fs_io_obj.raw_write(@write_range.first, @buffer[offset, length])
|
117
|
+
@write_range.clear
|
118
|
+
rv
|
119
|
+
end
|
120
|
+
|
121
|
+
def available_bytes(pos)
|
122
|
+
@range.last - pos + 1
|
123
|
+
end
|
124
|
+
|
125
|
+
def at_eof?
|
126
|
+
@range.last >= @io_obj.end_byte_addr
|
127
|
+
end
|
128
|
+
|
129
|
+
def buf_offset(pos)
|
130
|
+
pos - @range.first
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,146 @@
|
|
1
|
+
require "pathname"
|
2
|
+
|
3
|
+
module VirtFS
|
4
|
+
module Kernel # rubocop:disable ModuleLength
|
5
|
+
@kernel_mutex = Mutex.new
|
6
|
+
|
7
|
+
def self.inject # rubocop:disable AbcSize
|
8
|
+
@kernel_mutex.synchronize do
|
9
|
+
return false if @injected
|
10
|
+
|
11
|
+
#
|
12
|
+
# If the 'require' method is implemented in ruby (method(:require).source_location != nil)
|
13
|
+
# and 'gem_original_require' is defined, then rubygems is active. Replace gem_original_require
|
14
|
+
# with our VirtFS aware implementation of require - the rubygems require will call us.
|
15
|
+
#
|
16
|
+
# If the 'require' method is implemented in 'C' (method(:require).source_location == nil)
|
17
|
+
# then rubygems is not active (even if 'gem_original_require' is defined). Replace 'require'
|
18
|
+
# with our VirtFS aware implementation of require
|
19
|
+
#
|
20
|
+
@rubygems_active = method(:require).source_location && private_method_defined?(:gem_original_require)
|
21
|
+
|
22
|
+
::Kernel.module_exec(@rubygems_active) do |gems_active|
|
23
|
+
if gems_active
|
24
|
+
alias_method :virtfs_original_require, :gem_original_require
|
25
|
+
else
|
26
|
+
alias_method :virtfs_original_require, :require
|
27
|
+
end
|
28
|
+
private :virtfs_original_require
|
29
|
+
|
30
|
+
alias_method :virtfs_original_load, :load
|
31
|
+
private :virtfs_original_load
|
32
|
+
|
33
|
+
define_method(:virtfs_require) do |file_name|
|
34
|
+
VirtFS::Kernel.virtfs_require(file_name)
|
35
|
+
end
|
36
|
+
private :virtfs_require
|
37
|
+
|
38
|
+
define_method(:virtfs_load) do |file_name, wrap = false|
|
39
|
+
VirtFS::Kernel.virtfs_load(file_name, wrap)
|
40
|
+
end
|
41
|
+
private :virtfs_load
|
42
|
+
end
|
43
|
+
@injected = true
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def self.withdraw
|
48
|
+
@kernel_mutex.synchronize do
|
49
|
+
return false unless @injected
|
50
|
+
raise "Cannot withdraw while VirtFS::Kernel is enabled" if @enabled
|
51
|
+
|
52
|
+
::Kernel.module_eval do
|
53
|
+
remove_method :virtfs_original_require
|
54
|
+
remove_method :virtfs_original_load
|
55
|
+
remove_method :virtfs_require
|
56
|
+
remove_method :virtfs_load
|
57
|
+
end
|
58
|
+
@injected = false
|
59
|
+
end
|
60
|
+
true
|
61
|
+
end
|
62
|
+
|
63
|
+
def self.enable
|
64
|
+
@kernel_mutex.synchronize do
|
65
|
+
return false if @enabled
|
66
|
+
|
67
|
+
inject unless @injected
|
68
|
+
|
69
|
+
::Kernel.module_exec(@rubygems_active) do |gems_active|
|
70
|
+
if gems_active
|
71
|
+
alias_method :gem_original_require, :virtfs_require
|
72
|
+
else
|
73
|
+
alias_method :require, :virtfs_require
|
74
|
+
end
|
75
|
+
|
76
|
+
alias_method :load, :virtfs_load
|
77
|
+
end
|
78
|
+
@enabled = true
|
79
|
+
end
|
80
|
+
true
|
81
|
+
end
|
82
|
+
|
83
|
+
def self.disable
|
84
|
+
@kernel_mutex.synchronize do
|
85
|
+
return false unless @enabled
|
86
|
+
|
87
|
+
::Kernel.module_exec(@rubygems_active) do |gems_active|
|
88
|
+
if gems_active
|
89
|
+
alias_method :gem_original_require, :virtfs_original_require
|
90
|
+
else
|
91
|
+
alias_method :require, :virtfs_original_require
|
92
|
+
end
|
93
|
+
|
94
|
+
alias_method :load, :virtfs_original_load
|
95
|
+
end
|
96
|
+
@enabled = false
|
97
|
+
end
|
98
|
+
true
|
99
|
+
end
|
100
|
+
|
101
|
+
def self.virtfs_load(file_name, wrap)
|
102
|
+
file_path = ::Pathname.new(file_name)
|
103
|
+
return virtfs_original_load(file_name, wrap) unless file_path.extname == ".rb"
|
104
|
+
file_path = canonical_path(file_path)
|
105
|
+
raise LoadError, "cannot load such file -- #{file_name}" unless file_path
|
106
|
+
eval_file(file_path, wrap)
|
107
|
+
true
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.virtfs_require(lib_name)
|
111
|
+
lib_path = canonical_path(::Pathname.new(lib_name))
|
112
|
+
raise LoadError, "cannot load such file -- #{lib_name}" unless lib_path
|
113
|
+
return virtfs_original_require(lib_name) unless lib_path.extname == ".rb"
|
114
|
+
return false if already_loaded(lib_path)
|
115
|
+
eval_file(lib_path, false)
|
116
|
+
$LOADED_FEATURES << lib_path.to_path
|
117
|
+
true
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.canonical_path(path)
|
121
|
+
has_ext = path.extname != ""
|
122
|
+
return path if path.absolute?
|
123
|
+
$LOAD_PATH.each do |dir|
|
124
|
+
full_path = path.expand_path(dir)
|
125
|
+
if has_ext
|
126
|
+
return full_path if full_path.file?
|
127
|
+
else
|
128
|
+
%w(.rb .so .o .dll).each do |ext|
|
129
|
+
ext_path = full_path.sub_ext(ext)
|
130
|
+
return ext_path if ext_path.file?
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.already_loaded(canonical_name)
|
138
|
+
$LOADED_FEATURES.include?(canonical_name.to_path)
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.eval_file(file_path, wrap)
|
142
|
+
eval_binding = wrap ? Module.new.send(:binding) : TOPLEVEL_BINDING
|
143
|
+
eval(file_path.read, eval_binding, file_path.to_path) # rubocop:disable Lint/Eval
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'thick/file_class_methods'
|
2
|
+
require_relative 'thick/dir_class_methods'
|
3
|
+
|
4
|
+
module VirtFS::NativeFS # rubocop:disable Style/ClassAndModuleChildren
|
5
|
+
class Thick
|
6
|
+
attr_accessor :mount_point, :name
|
7
|
+
|
8
|
+
include FileClassMethods
|
9
|
+
include DirClassMethods
|
10
|
+
|
11
|
+
def initialize(root = VfsRealFile::SEPARATOR)
|
12
|
+
@mount_point = nil
|
13
|
+
@name = self.class.name
|
14
|
+
@root = root
|
15
|
+
end
|
16
|
+
|
17
|
+
def thin_interface?
|
18
|
+
false
|
19
|
+
end
|
20
|
+
|
21
|
+
def umount
|
22
|
+
@mount_point = nil
|
23
|
+
end
|
24
|
+
|
25
|
+
def apply_root(path)
|
26
|
+
VfsRealFile.join(@root, path)
|
27
|
+
end
|
28
|
+
private :apply_root
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
#
|
2
|
+
# Dir class methods - are instance methods of filesystem instance.
|
3
|
+
#
|
4
|
+
module VirtFS::NativeFS # rubocop:disable Style/ClassAndModuleChildren
|
5
|
+
class Thick
|
6
|
+
module DirClassMethods
|
7
|
+
def dir_delete(p)
|
8
|
+
VfsRealDir.delete(apply_root(p))
|
9
|
+
end
|
10
|
+
|
11
|
+
def dir_entries(p)
|
12
|
+
VfsRealDir.entries(apply_root(p))
|
13
|
+
end
|
14
|
+
|
15
|
+
def dir_exist?(p)
|
16
|
+
VfsRealDir.exist?(apply_root(p))
|
17
|
+
end
|
18
|
+
|
19
|
+
def dir_foreach(p, &block)
|
20
|
+
VfsRealDir.foreach(apply_root(p), &block)
|
21
|
+
end
|
22
|
+
|
23
|
+
def dir_mkdir(p, permissions)
|
24
|
+
VfsRealDir.mkdir(apply_root(p), permissions)
|
25
|
+
end
|
26
|
+
|
27
|
+
def dir_new(fs_rel_path, hash_args, _open_path, cwd)
|
28
|
+
owd = VfsRealDir.getwd
|
29
|
+
begin
|
30
|
+
VfsRealDir.chdir(cwd)
|
31
|
+
return VfsRealDir.new(apply_root(fs_rel_path), hash_args)
|
32
|
+
ensure
|
33
|
+
VfsRealDir.chdir(owd)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|