virtfs 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (91) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +18 -0
  3. data/.rspec +2 -0
  4. data/.travis.yml +8 -0
  5. data/Gemfile +4 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +154 -0
  8. data/Rakefile +5 -0
  9. data/lib/virtfs-nativefs-thick.rb +1 -0
  10. data/lib/virtfs-nativefs-thin.rb +1 -0
  11. data/lib/virtfs.rb +38 -0
  12. data/lib/virtfs/activation.rb +97 -0
  13. data/lib/virtfs/block_io.rb +140 -0
  14. data/lib/virtfs/byte_range.rb +71 -0
  15. data/lib/virtfs/context.rb +300 -0
  16. data/lib/virtfs/context_manager.rb +175 -0
  17. data/lib/virtfs/context_switch_class_methods.rb +96 -0
  18. data/lib/virtfs/delegate_module.rb +40 -0
  19. data/lib/virtfs/dir_instance_delegate.rb +3 -0
  20. data/lib/virtfs/exception.rb +13 -0
  21. data/lib/virtfs/file_instance_delegate.rb +3 -0
  22. data/lib/virtfs/file_modes_and_options.rb +293 -0
  23. data/lib/virtfs/find_class_methods.rb +106 -0
  24. data/lib/virtfs/io_buffer.rb +133 -0
  25. data/lib/virtfs/io_instance_delegate.rb +3 -0
  26. data/lib/virtfs/kernel.rb +146 -0
  27. data/lib/virtfs/nativefs/thick.rb +30 -0
  28. data/lib/virtfs/nativefs/thick/dir_class_methods.rb +38 -0
  29. data/lib/virtfs/nativefs/thick/file_class_methods.rb +178 -0
  30. data/lib/virtfs/nativefs/thin.rb +32 -0
  31. data/lib/virtfs/nativefs/thin/dir.rb +30 -0
  32. data/lib/virtfs/nativefs/thin/dir_class_methods.rb +41 -0
  33. data/lib/virtfs/nativefs/thin/file.rb +112 -0
  34. data/lib/virtfs/nativefs/thin/file_class_methods.rb +181 -0
  35. data/lib/virtfs/protofs/protofs.rb +7 -0
  36. data/lib/virtfs/protofs/protofs_base.rb +12 -0
  37. data/lib/virtfs/protofs/protofs_dir.rb +13 -0
  38. data/lib/virtfs/protofs/protofs_dir_class.rb +31 -0
  39. data/lib/virtfs/protofs/protofs_file.rb +27 -0
  40. data/lib/virtfs/protofs/protofs_file_class.rb +136 -0
  41. data/lib/virtfs/stat.rb +100 -0
  42. data/lib/virtfs/thin_dir_delegator.rb +79 -0
  43. data/lib/virtfs/thin_file_delegator.rb +77 -0
  44. data/lib/virtfs/thin_io_delegator_methods.rb +301 -0
  45. data/lib/virtfs/thin_io_delegator_methods_bufferio.rb +337 -0
  46. data/lib/virtfs/v_dir.rb +238 -0
  47. data/lib/virtfs/v_file.rb +480 -0
  48. data/lib/virtfs/v_io.rb +243 -0
  49. data/lib/virtfs/v_pathname.rb +128 -0
  50. data/lib/virtfs/version.rb +3 -0
  51. data/spec/activate_spec.rb +202 -0
  52. data/spec/chroot_spec.rb +120 -0
  53. data/spec/context_manager_class_spec.rb +246 -0
  54. data/spec/context_manager_instance_spec.rb +255 -0
  55. data/spec/context_spec.rb +335 -0
  56. data/spec/data/UTF-16LE-data.txt +0 -0
  57. data/spec/data/UTF-8-data.txt +212 -0
  58. data/spec/dir_class_spec.rb +506 -0
  59. data/spec/dir_instance_spec.rb +208 -0
  60. data/spec/file_class_spec.rb +2106 -0
  61. data/spec/file_instance_spec.rb +154 -0
  62. data/spec/file_modes_and_options_spec.rb +1556 -0
  63. data/spec/find_spec.rb +142 -0
  64. data/spec/io_bufferio_size_shared_examples.rb +371 -0
  65. data/spec/io_bufferio_size_spec.rb +861 -0
  66. data/spec/io_bufferio_spec.rb +801 -0
  67. data/spec/io_class_spec.rb +145 -0
  68. data/spec/io_instance_spec.rb +516 -0
  69. data/spec/kernel_spec.rb +285 -0
  70. data/spec/mount_spec.rb +186 -0
  71. data/spec/nativefs_local_root_spec.rb +132 -0
  72. data/spec/path_spec.rb +39 -0
  73. data/spec/spec_helper.rb +126 -0
  74. data/tasks/rspec.rake +3 -0
  75. data/tasks/yard.rake +7 -0
  76. data/test/UTF-8-demo.txt +212 -0
  77. data/test/bench.rb +18 -0
  78. data/test/bio_internal_test.rb +45 -0
  79. data/test/delegate_io.rb +31 -0
  80. data/test/delegate_module.rb +62 -0
  81. data/test/encode_test.rb +42 -0
  82. data/test/enoent_test.rb +30 -0
  83. data/test/namespace_test.rb +42 -0
  84. data/test/read_block_valid_encoding.rb +44 -0
  85. data/test/read_test.rb +78 -0
  86. data/test/stream_readers.rb +46 -0
  87. data/test/utf-16-demo.txt +0 -0
  88. data/test/utf8_to_utf16.rb +77 -0
  89. data/test/wrapper_test.rb +34 -0
  90. data/virtfs.gemspec +29 -0
  91. metadata +230 -0
@@ -0,0 +1,18 @@
1
+ big_string = "0123456789" * 1000
2
+ big_string.force_encoding("ASCII-8BIT")
3
+
4
+ t0 = Time.now
5
+ (0...2_000_000).each do
6
+ s = big_string.dup
7
+ s[-1] = ""
8
+ end
9
+ t1 = Time.now
10
+ puts "Index: #{t1 - t0} seconds"
11
+
12
+ t0 = Time.now
13
+ (0...2_000_000).each do
14
+ s = big_string.dup
15
+ s.chop!
16
+ end
17
+ t1 = Time.now
18
+ puts "chop!: #{t1 - t0} seconds"
@@ -0,0 +1,45 @@
1
+ require "../lib/virtfs"
2
+ require "tempfile"
3
+
4
+ begin
5
+ @start_marker = "START OF FILE:\n"
6
+ @end_marker = ":END OF FILE"
7
+ @data1 = "0123456789"
8
+ @data2 = "abcdefghijklmnopqrstuvwxyz\n"
9
+
10
+ @temp_file = Tempfile.new("VirtFS-IO")
11
+ @temp_file.write(@start_marker)
12
+ (0..9).each do
13
+ @temp_file.write(@data1)
14
+ @temp_file.write(@data2)
15
+ end
16
+ @temp_file.write(@end_marker)
17
+ @temp_file.close
18
+
19
+ @full_path = @temp_file.path
20
+ @rel_path = File.basename(@full_path)
21
+ @parent_dir = File.dirname(@full_path)
22
+ @file_size = VfsRealFile.size(@full_path)
23
+
24
+ @utf_8_filename = VfsRealFile.join(__dir__, "UTF-8-demo.txt")
25
+
26
+ require "../lib/nativefs"
27
+ @root = File::SEPARATOR
28
+ @native_fs = NativeFS.new
29
+ VirtFS.mount(@native_fs, @root)
30
+
31
+ @vfile_read_obj = VirtFS::VFile.new(@full_path, "r:UTF-8")
32
+ @vfile_read_obj.send(:min_read_buf_sz=, 1)
33
+ range = @vfile_read_obj.read_buffer.range
34
+
35
+ puts "pos = #{@vfile_read_obj.pos}, Range(#{range.first}, #{range.end})"
36
+
37
+ char = "X"
38
+ @vfile_read_obj.ungetc(char)
39
+ puts "pos = #{@vfile_read_obj.pos}, Range(#{range.first}, #{range.end})"
40
+ @vfile_read_obj.getc
41
+
42
+ rescue => err
43
+ puts err.to_s
44
+ puts err.backtrace.join("\n")
45
+ end
@@ -0,0 +1,31 @@
1
+ require "delegate"
2
+
3
+ begin
4
+
5
+ class MyFile < DelegateClass(::File)
6
+ SUPER_CLASSES = [File, IO]
7
+
8
+ def initialize(*args)
9
+ fobj = ::File.new(*args)
10
+ super(fobj)
11
+ end
12
+
13
+ def is_a?(klass)
14
+ super(klass) || SUPER_CLASSES.include?(klass)
15
+ end
16
+ alias_method :kind_of?, :is_a?
17
+ end
18
+
19
+ f = MyFile.new(__FILE__, "r")
20
+
21
+ puts "f.is_a?(File) = #{f.is_a?(File)}"
22
+ puts "f.is_a?(IO) = #{f.is_a?(IO)}"
23
+ puts "f.is_a?(MyFile) = #{f.is_a?(MyFile)}"
24
+ puts "f.is_a?(String) = #{f.is_a?(String)}"
25
+
26
+ f.close
27
+
28
+ rescue => err
29
+ puts err.to_s
30
+ puts err.backtrace.join("\n")
31
+ end
@@ -0,0 +1,62 @@
1
+ require "delegate"
2
+
3
+ begin
4
+
5
+ def DelegateModule(superclass)
6
+ klass = Module.new
7
+ methods = superclass.instance_methods
8
+ methods -= ::Delegator.public_api
9
+ methods -= [:to_s,:inspect,:=~,:!~,:===]
10
+ klass.module_eval do
11
+ def __getobj__ # :nodoc:
12
+ unless defined?(@delegate_dc_obj)
13
+ return yield if block_given?
14
+ __raise__ ::ArgumentError, "not delegated"
15
+ end
16
+ @delegate_dc_obj
17
+ end
18
+ def __setobj__(obj) # :nodoc:
19
+ __raise__ ::ArgumentError, "cannot delegate to self" if self.equal?(obj)
20
+ @delegate_dc_obj = obj
21
+ end
22
+ methods.each do |method|
23
+ define_method(method, Delegator.delegating_block(method))
24
+ end
25
+ end
26
+ klass.define_singleton_method :public_instance_methods do |all=true|
27
+ super(all) - superclass.protected_instance_methods
28
+ end
29
+ klass.define_singleton_method :protected_instance_methods do |all=true|
30
+ super(all) | superclass.protected_instance_methods
31
+ end
32
+ return klass
33
+ end
34
+
35
+ FileDelegate = DelegateModule(File)
36
+
37
+ class MyIO
38
+ end
39
+
40
+ class MyFile < MyIO
41
+ include FileDelegate
42
+
43
+ def initialize(dobj)
44
+ __setobj__(dobj)
45
+ end
46
+ end
47
+
48
+ fobj = File.new(__FILE__, "r")
49
+
50
+ mf = MyFile.new(fobj)
51
+
52
+ puts "mf.is_a?(MyFile) = #{mf.is_a?(MyFile)}"
53
+ puts "mf.is_a?(MyIO) = #{mf.is_a?(MyIO)}"
54
+
55
+ puts
56
+ mf.each { |l| puts l }
57
+ mf.close
58
+
59
+ rescue => err
60
+ puts err.to_s
61
+ puts err.backtrace.join("\n")
62
+ end
@@ -0,0 +1,42 @@
1
+ begin
2
+ #
3
+ # Find the offset within the file of the first multi-byte character.
4
+ #
5
+ binary_string = ""
6
+ File.open("UTF-16-demo.txt", "rb") do |io|
7
+ binary_string = io.read
8
+ end
9
+ puts "\tbinary_string.encoding.name = #{binary_string.encoding.name} (valid: #{binary_string.valid_encoding?})"
10
+ puts "\tbinary_string.length = #{binary_string.length}"
11
+ puts "\tbinary_string.bytesize = #{binary_string.bytesize}"
12
+ puts
13
+
14
+ utf8_string = ""
15
+ ec = Encoding::Converter.new("UTF-16le", "UTF-8")
16
+ rv = ec.primitive_convert(binary_string, utf8_string)
17
+ puts "primitive_convert --> #{rv}"
18
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
19
+ puts "\tutf8_string.length = #{utf8_string.length}"
20
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
21
+ puts
22
+
23
+ nchunk = 0
24
+ utf8_string = ""
25
+ ec = Encoding::Converter.new("UTF-16le", "UTF-8")
26
+ File.open("UTF-16-demo.txt", "rb") do |io|
27
+ while (binary_string = io.read(99))
28
+ rv = ec.primitive_convert(binary_string, utf8_string, nil, nil, :partial_input => true)
29
+ puts "Chunk: #{nchunk}, rv = #{rv}"
30
+ nchunk += 1
31
+ end
32
+ end
33
+
34
+ puts "nchunk = #{nchunk}"
35
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
36
+ puts "\tutf8_string.length = #{utf8_string.length}"
37
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
38
+ puts
39
+ rescue => err
40
+ puts err.to_s
41
+ puts err.backtrace.join("\n")
42
+ end
@@ -0,0 +1,30 @@
1
+ require "yaml"
2
+
3
+ begin
4
+ begin
5
+ Dir.new("/not/a/dir")
6
+ rescue => err
7
+ puts " err => #{err.class.name}"
8
+ puts " err => #{err.inspect}"
9
+ puts " err.errno = #{err.errno}"
10
+ puts " err.class::Errno = #{err.class::Errno}"
11
+ err = YAML.load(YAML.dump(err))
12
+ nerr = SystemCallError.new("dir", err.class::Errno)
13
+ # nerr.message = err.message
14
+ raise nerr
15
+ end
16
+ rescue Errno::ENOENT => oerr
17
+ puts "**** Got Errno::ENOENT"
18
+ puts "oerr => #{oerr.class.name}"
19
+ puts "oerr => #{oerr.inspect}"
20
+ puts "oerr.errno = #{oerr.errno}"
21
+ puts "oerr.class::Errno = #{oerr.class::Errno}"
22
+ rescue SystemCallError => oerr
23
+ puts "**** Got SystemCallError"
24
+ rescue => oerr
25
+ puts "**** Not Errno::ENOENT"
26
+ puts "oerr => #{oerr.class.name}"
27
+ puts "oerr => #{oerr.inspect}"
28
+ puts "oerr.errno = #{oerr.errno}"
29
+ puts "oerr.class::Errno = #{oerr.class::Errno}"
30
+ end
@@ -0,0 +1,42 @@
1
+ class MyFile
2
+ def self.name
3
+ "MyFile"
4
+ end
5
+ end
6
+
7
+ class Vfs
8
+ def self.nest(ext)
9
+ ext.const_set(:File, MyFile)
10
+ end
11
+ end
12
+
13
+ begin
14
+
15
+ Module.new do
16
+ class << self
17
+ puts self.class.name
18
+ puts constants.inspect
19
+ puts File.name
20
+
21
+ Vfs.nest(self)
22
+ puts constants.inspect
23
+ puts File.name
24
+ end
25
+ end
26
+
27
+ puts
28
+
29
+ Module.new do
30
+ class << self
31
+ puts self.class.name
32
+ puts constants.inspect
33
+ puts File.name
34
+ end
35
+ end
36
+
37
+ puts File.name
38
+
39
+ rescue => err
40
+ puts err.to_s
41
+ puts err.backtrace.join("\n")
42
+ end
@@ -0,0 +1,44 @@
1
+ require "tempfile"
2
+
3
+ begin
4
+ input_file_name = "UTF-8-demo.txt"
5
+ external_encoding = Encoding.find("UTF-8")
6
+ binary_encoding = Encoding.find("ASCII-8BIT")
7
+ buffer_size = 95
8
+
9
+ temp_file = Tempfile.new("rbve")
10
+
11
+ File.open(input_file_name, "rb") do |io|
12
+ block = 0
13
+ while (binary_string = io.read(buffer_size))
14
+ binary_string.force_encoding(external_encoding)
15
+ puts "Block: #{block}, valid: #{binary_string.valid_encoding?}"
16
+ push_back = 0
17
+ (0...8).each do
18
+ break if binary_string.valid_encoding?
19
+ binary_string.force_encoding(binary_encoding)
20
+ binary_string[-1] = ""
21
+ binary_string.force_encoding(external_encoding)
22
+ push_back += 1
23
+ end
24
+ raise "Invalid byte sequence" unless binary_string.valid_encoding?
25
+ puts "Block: #{block}, valid: #{binary_string.valid_encoding?}, push_back: #{push_back}"
26
+ temp_file.write(binary_string)
27
+ io.seek(-push_back, IO::SEEK_CUR) unless push_back == 0
28
+ block += 1
29
+ end
30
+ end
31
+
32
+ temp_file.close
33
+
34
+ input = File.read(input_file_name)
35
+ output = File.read(temp_file.path)
36
+
37
+ puts
38
+ puts "Input size: #{input.bytesize}"
39
+ puts "Output size: #{output.bytesize}"
40
+ puts "Data check pass: #{input == output}"
41
+ rescue => err
42
+ puts err.to_s
43
+ puts err.backtrace.join("\n")
44
+ end
@@ -0,0 +1,78 @@
1
+ begin
2
+ #
3
+ # Find the offset within the file of the first multi-byte character.
4
+ #
5
+ first_mb_char_pos = 0
6
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
7
+ io.each_char do |c|
8
+ if c.length != c.bytesize
9
+ puts "first_mb_char_pos = #{first_mb_char_pos}, char = '#{c}' #{c.bytes.to_a.inspect}"
10
+ puts
11
+ break
12
+ end
13
+ first_mb_char_pos += 1
14
+ end
15
+ end
16
+
17
+ puts "Read whole file as binary:"
18
+ binary_string = ""
19
+ File.open("UTF-8-demo.txt", "rb") do |io|
20
+ binary_string = io.read
21
+ end
22
+ puts "\tbinary_string.encoding.name = #{binary_string.encoding.name} (valid: #{binary_string.valid_encoding?})"
23
+ puts "\tbinary_string.length = #{binary_string.length}"
24
+ puts "\tbinary_string.bytesize = #{binary_string.bytesize}"
25
+ puts
26
+
27
+ puts "Read whole file as utf-8:"
28
+ utf8_string = ""
29
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
30
+ utf8_string = io.read
31
+ end
32
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
33
+ puts "\tutf8_string.length = #{utf8_string.length}"
34
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
35
+ puts
36
+
37
+ puts "Partial read (100 bytes) as utf-8:"
38
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
39
+ utf8_string = io.read(100)
40
+ end
41
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
42
+ puts "\tutf8_string.length = #{utf8_string.length}"
43
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
44
+ puts
45
+
46
+ puts "Offset read (on char boundary) as utf-8:"
47
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
48
+ io.seek(first_mb_char_pos, IO::SEEK_SET)
49
+ utf8_string = io.read
50
+ end
51
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
52
+ puts "\tutf8_string.length = #{utf8_string.length}"
53
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
54
+ puts
55
+
56
+ puts "Offset read (not on char boundary) as utf-8:"
57
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
58
+ io.seek(first_mb_char_pos+1, IO::SEEK_SET)
59
+ utf8_string = io.read
60
+ end
61
+ puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
62
+ puts "\tutf8_string.length = #{utf8_string.length}"
63
+ puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
64
+ puts
65
+
66
+ # File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
67
+ # while utf8_string = io.gets
68
+ # puts utf8_string
69
+ # puts "\tutf8_string.encoding.name = #{utf8_string.encoding.name} (valid: #{utf8_string.valid_encoding?})"
70
+ # puts "\tutf8_string.length = #{utf8_string.length}"
71
+ # puts "\tutf8_string.bytesize = #{utf8_string.bytesize}"
72
+ # puts
73
+ # end
74
+ # end
75
+ rescue => err
76
+ puts err.to_s
77
+ puts err.backtrace.join("\n")
78
+ end
@@ -0,0 +1,46 @@
1
+ begin
2
+ first_mb_char_pos = 0
3
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
4
+ io.each_char do |c|
5
+ if c.length != c.bytesize
6
+ puts "first_mb_char_pos = #{first_mb_char_pos}, char = '#{c}' #{c.bytes.to_a.inspect}"
7
+ puts
8
+ break
9
+ end
10
+ first_mb_char_pos += 1
11
+ end
12
+ end
13
+
14
+ File.open("UTF-8-demo.txt", "r:utf-8:utf-8") do |io|
15
+ puts "File opened"
16
+ puts "\tio.pos = #{io.pos}"
17
+ puts
18
+
19
+ puts "Reading 10 bytes."
20
+ barray = io.each_byte.first(10)
21
+ puts "\tio.pos = #{io.pos}"
22
+ puts
23
+
24
+ puts "Reading 10 bytes."
25
+ barray = io.each_char.first(10)
26
+ puts "\tio.pos = #{io.pos}"
27
+ puts
28
+
29
+ puts "Reading 10 lines."
30
+ ln = 0
31
+ io.each_line do |line|
32
+ break if ln >= 10
33
+ puts "Line: #{ln}"
34
+ puts "\tline.length = #{line.length}"
35
+ puts "\tline.bytesize = #{line.bytesize}"
36
+ puts "\tline.codepoints.length = #{line.codepoints.length}"
37
+ puts "\tio.pos = #{io.pos}"
38
+ puts "\tio.lineno = #{io.lineno}"
39
+ puts
40
+ ln += 1
41
+ end
42
+ end
43
+ rescue => err
44
+ puts err.to_s
45
+ puts err.backtrace.join("\n")
46
+ end