script_core 0.2.5 → 0.2.6

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.
Files changed (224) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +7 -1
  3. data/ext/enterprise_script_service/libseccomp/.travis.yml +3 -5
  4. data/ext/enterprise_script_service/libseccomp/CHANGELOG +10 -0
  5. data/ext/enterprise_script_service/libseccomp/CREDITS +3 -0
  6. data/ext/enterprise_script_service/libseccomp/README.md +18 -0
  7. data/ext/enterprise_script_service/libseccomp/configure.ac +1 -1
  8. data/ext/enterprise_script_service/libseccomp/include/seccomp-syscalls.h +7 -0
  9. data/ext/enterprise_script_service/libseccomp/src/arch-s390-syscalls.c +16 -0
  10. data/ext/enterprise_script_service/libseccomp/src/arch-s390x-syscalls.c +16 -0
  11. data/ext/enterprise_script_service/libseccomp/tests/.gitignore +1 -0
  12. data/ext/enterprise_script_service/libseccomp/tests/15-basic-resolver.c +3 -3
  13. data/ext/enterprise_script_service/libseccomp/tests/52-basic-load.c +48 -0
  14. data/ext/enterprise_script_service/libseccomp/tests/52-basic-load.py +38 -0
  15. data/ext/enterprise_script_service/libseccomp/tests/52-basic-load.tests +11 -0
  16. data/ext/enterprise_script_service/libseccomp/tests/Makefile.am +6 -3
  17. data/ext/enterprise_script_service/libseccomp/tests/regression +4 -0
  18. data/ext/enterprise_script_service/libseccomp/tools/Makefile.am +0 -3
  19. data/ext/enterprise_script_service/libseccomp/tools/scmp_bpf_sim.c +2 -0
  20. data/ext/enterprise_script_service/mruby/.github/workflows/build.yml +106 -0
  21. data/ext/enterprise_script_service/mruby/.github/workflows/main.yml +24 -0
  22. data/ext/enterprise_script_service/mruby/.gitignore +3 -0
  23. data/ext/enterprise_script_service/mruby/.travis.yml +6 -9
  24. data/ext/enterprise_script_service/mruby/AUTHORS +1 -0
  25. data/ext/enterprise_script_service/mruby/Doxyfile +1 -1
  26. data/ext/enterprise_script_service/mruby/LICENSE +1 -1
  27. data/ext/enterprise_script_service/mruby/README.md +6 -2
  28. data/ext/enterprise_script_service/mruby/appveyor.yml +9 -12
  29. data/ext/enterprise_script_service/mruby/appveyor_config.rb +9 -0
  30. data/ext/enterprise_script_service/mruby/build_config.rb +6 -6
  31. data/ext/enterprise_script_service/mruby/doc/guides/compile.md +6 -2
  32. data/ext/enterprise_script_service/mruby/doc/guides/debugger.md +1 -1
  33. data/ext/enterprise_script_service/mruby/doc/guides/mrbconf.md +4 -8
  34. data/ext/enterprise_script_service/mruby/doc/limitations.md +10 -10
  35. data/ext/enterprise_script_service/mruby/doc/opcode.md +108 -95
  36. data/ext/enterprise_script_service/mruby/examples/targets/build_config_ArduinoDue.rb +2 -2
  37. data/ext/enterprise_script_service/mruby/examples/targets/build_config_IntelEdison.rb +2 -2
  38. data/ext/enterprise_script_service/mruby/examples/targets/build_config_IntelGalileo.rb +2 -2
  39. data/ext/enterprise_script_service/mruby/examples/targets/build_config_RX630.rb +2 -2
  40. data/ext/enterprise_script_service/mruby/examples/targets/build_config_chipKITMax32.rb +2 -2
  41. data/ext/enterprise_script_service/mruby/examples/targets/build_config_dreamcast_shelf.rb +108 -0
  42. data/ext/enterprise_script_service/mruby/include/mrbconf.h +10 -7
  43. data/ext/enterprise_script_service/mruby/include/mruby.h +11 -9
  44. data/ext/enterprise_script_service/mruby/include/mruby/array.h +4 -0
  45. data/ext/enterprise_script_service/mruby/include/mruby/boxing_nan.h +11 -2
  46. data/ext/enterprise_script_service/mruby/include/mruby/boxing_word.h +0 -9
  47. data/ext/enterprise_script_service/mruby/include/mruby/common.h +10 -0
  48. data/ext/enterprise_script_service/mruby/include/mruby/compile.h +11 -3
  49. data/ext/enterprise_script_service/mruby/include/mruby/dump.h +1 -17
  50. data/ext/enterprise_script_service/mruby/include/mruby/irep.h +10 -0
  51. data/ext/enterprise_script_service/mruby/include/mruby/istruct.h +4 -1
  52. data/ext/enterprise_script_service/mruby/include/mruby/khash.h +23 -5
  53. data/ext/enterprise_script_service/mruby/include/mruby/numeric.h +1 -0
  54. data/ext/enterprise_script_service/mruby/include/mruby/ops.h +3 -2
  55. data/ext/enterprise_script_service/mruby/include/mruby/string.h +2 -1
  56. data/ext/enterprise_script_service/mruby/include/mruby/value.h +7 -12
  57. data/ext/enterprise_script_service/mruby/include/mruby/version.h +4 -4
  58. data/ext/enterprise_script_service/mruby/lib/mruby/build.rb +2 -30
  59. data/ext/enterprise_script_service/mruby/lib/mruby/build/command.rb +21 -46
  60. data/ext/enterprise_script_service/mruby/lib/mruby/gem.rb +9 -0
  61. data/ext/enterprise_script_service/mruby/lib/mruby/source.rb +3 -1
  62. data/ext/enterprise_script_service/mruby/mrbgems/default.gembox +7 -0
  63. data/ext/enterprise_script_service/mruby/mrbgems/mruby-array-ext/mrblib/array.rb +0 -31
  64. data/ext/enterprise_script_service/mruby/mrbgems/mruby-array-ext/test/array.rb +0 -13
  65. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-config/mrbgem.rake +5 -2
  66. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdb.c +0 -1
  67. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-debugger/tools/mrdb/mrdbconf.h +5 -1
  68. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mirb/tools/mirb/mirb.c +5 -1
  69. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mrbc/tools/mrbc/mrbc.c +7 -11
  70. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mruby/mrbgem.rake +0 -1
  71. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-mruby/tools/mruby/mruby.c +6 -2
  72. data/ext/enterprise_script_service/mruby/mrbgems/mruby-bin-strip/tools/mruby-strip/mruby-strip.c +6 -2
  73. data/ext/enterprise_script_service/mruby/mrbgems/mruby-class-ext/src/class.c +6 -1
  74. data/ext/enterprise_script_service/mruby/mrbgems/mruby-compiler/core/codegen.c +76 -48
  75. data/ext/enterprise_script_service/mruby/mrbgems/mruby-compiler/core/parse.y +107 -32
  76. data/ext/enterprise_script_service/mruby/mrbgems/mruby-compiler/core/y.tab.c +13153 -0
  77. data/ext/enterprise_script_service/mruby/mrbgems/mruby-compiler/mrbgem.rake +13 -15
  78. data/ext/enterprise_script_service/mruby/mrbgems/mruby-error/src/exception.c +3 -3
  79. data/ext/enterprise_script_service/mruby/mrbgems/mruby-eval/src/eval.c +2 -213
  80. data/ext/enterprise_script_service/mruby/mrbgems/mruby-eval/test/eval.rb +21 -0
  81. data/ext/enterprise_script_service/mruby/mrbgems/mruby-hash-ext/src/hash-ext.c +1 -3
  82. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/include/mruby/ext/io.h +39 -7
  83. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/mrbgem.rake +2 -8
  84. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/mrblib/file_constants.rb +0 -16
  85. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/mrblib/io.rb +7 -12
  86. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/file.c +76 -30
  87. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/file_test.c +9 -10
  88. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/src/io.c +323 -120
  89. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/test/file.rb +18 -12
  90. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/test/io.rb +32 -0
  91. data/ext/enterprise_script_service/mruby/mrbgems/mruby-io/test/mruby_io_test.c +57 -49
  92. data/ext/enterprise_script_service/mruby/mrbgems/mruby-metaprog/src/metaprog.c +15 -17
  93. data/ext/enterprise_script_service/mruby/mrbgems/mruby-metaprog/test/metaprog.rb +9 -0
  94. data/ext/enterprise_script_service/mruby/mrbgems/mruby-method/src/method.c +1 -1
  95. data/ext/enterprise_script_service/mruby/mrbgems/mruby-object-ext/src/object.c +3 -12
  96. data/ext/enterprise_script_service/mruby/mrbgems/mruby-pack/src/pack.c +113 -10
  97. data/ext/enterprise_script_service/mruby/mrbgems/mruby-print/src/print.c +5 -1
  98. data/ext/enterprise_script_service/mruby/mrbgems/mruby-proc-ext/src/proc.c +2 -2
  99. data/ext/enterprise_script_service/mruby/mrbgems/mruby-rational/src/rational.c +9 -9
  100. data/ext/enterprise_script_service/mruby/mrbgems/mruby-sleep/src/mrb_sleep.c +1 -1
  101. data/ext/enterprise_script_service/mruby/mrbgems/mruby-socket/mrbgem.rake +1 -1
  102. data/ext/enterprise_script_service/mruby/mrbgems/mruby-socket/test/sockettest.c +3 -2
  103. data/ext/enterprise_script_service/mruby/mrbgems/mruby-sprintf/src/sprintf.c +61 -24
  104. data/ext/enterprise_script_service/mruby/mrbgems/mruby-sprintf/test/sprintf.rb +5 -23
  105. data/ext/enterprise_script_service/mruby/mrbgems/mruby-string-ext/src/string.c +3 -3
  106. data/ext/enterprise_script_service/mruby/mrbgems/mruby-symbol-ext/src/symbol.c +1 -1
  107. data/ext/enterprise_script_service/mruby/mrbgems/mruby-test/mrbgem.rake +1 -0
  108. data/ext/enterprise_script_service/mruby/mrbgems/mruby-time/src/time.c +6 -5
  109. data/ext/enterprise_script_service/mruby/mrblib/hash.rb +3 -3
  110. data/ext/enterprise_script_service/mruby/src/array.c +11 -0
  111. data/ext/enterprise_script_service/mruby/src/backtrace.c +2 -2
  112. data/ext/enterprise_script_service/mruby/src/class.c +26 -11
  113. data/ext/enterprise_script_service/mruby/src/codedump.c +4 -0
  114. data/ext/enterprise_script_service/mruby/src/debug.c +8 -5
  115. data/ext/enterprise_script_service/mruby/src/dump.c +3 -65
  116. data/ext/enterprise_script_service/mruby/src/error.c +57 -5
  117. data/ext/enterprise_script_service/mruby/src/etc.c +13 -4
  118. data/ext/enterprise_script_service/mruby/src/fmt_fp.c +98 -21
  119. data/ext/enterprise_script_service/mruby/src/gc.c +10 -275
  120. data/ext/enterprise_script_service/mruby/src/hash.c +5 -6
  121. data/ext/enterprise_script_service/mruby/src/kernel.c +2 -2
  122. data/ext/enterprise_script_service/mruby/src/load.c +56 -30
  123. data/ext/enterprise_script_service/mruby/src/numeric.c +22 -10
  124. data/ext/enterprise_script_service/mruby/src/object.c +12 -4
  125. data/ext/enterprise_script_service/mruby/src/print.c +27 -3
  126. data/ext/enterprise_script_service/mruby/src/proc.c +21 -1
  127. data/ext/enterprise_script_service/mruby/src/state.c +34 -11
  128. data/ext/enterprise_script_service/mruby/src/string.c +69 -35
  129. data/ext/enterprise_script_service/mruby/src/symbol.c +12 -10
  130. data/ext/enterprise_script_service/mruby/src/vm.c +21 -30
  131. data/ext/enterprise_script_service/mruby/tasks/gitlab.rake +19 -22
  132. data/ext/enterprise_script_service/mruby/tasks/mrbgems.rake +1 -1
  133. data/ext/enterprise_script_service/mruby/tasks/toolchains/android.rake +46 -1
  134. data/ext/enterprise_script_service/mruby/tasks/toolchains/gcc.rake +3 -3
  135. data/ext/enterprise_script_service/mruby/tasks/toolchains/openwrt.rake +6 -6
  136. data/ext/enterprise_script_service/mruby/tasks/toolchains/visualcpp.rake +8 -8
  137. data/ext/enterprise_script_service/mruby/test/assert.rb +5 -4
  138. data/ext/enterprise_script_service/mruby/test/t/ensure.rb +8 -26
  139. data/ext/enterprise_script_service/mruby/test/t/exception.rb +2 -2
  140. data/ext/enterprise_script_service/mruby/test/t/kernel.rb +8 -24
  141. data/ext/enterprise_script_service/mruby/travis_config.rb +0 -14
  142. data/ext/enterprise_script_service/msgpack/.github/depends/boost.sh +56 -0
  143. data/ext/enterprise_script_service/msgpack/.github/workflows/coverage.yml +62 -0
  144. data/ext/enterprise_script_service/msgpack/.github/workflows/gha.yml +304 -0
  145. data/ext/enterprise_script_service/msgpack/CHANGELOG.md +11 -0
  146. data/ext/enterprise_script_service/msgpack/CMakeLists.txt +82 -39
  147. data/ext/enterprise_script_service/msgpack/Files.cmake +22 -12
  148. data/ext/enterprise_script_service/msgpack/QUICKSTART-C.md +26 -29
  149. data/ext/enterprise_script_service/msgpack/README.md +3 -2
  150. data/ext/enterprise_script_service/msgpack/appveyor.yml +6 -2
  151. data/ext/enterprise_script_service/msgpack/ci/build_cmake.sh +3 -1
  152. data/ext/enterprise_script_service/msgpack/cmake/CodeCoverage.cmake +55 -0
  153. data/ext/enterprise_script_service/msgpack/codecov.yml +36 -0
  154. data/ext/enterprise_script_service/msgpack/example/CMakeLists.txt +9 -5
  155. data/ext/enterprise_script_service/msgpack/example/boost/CMakeLists.txt +1 -1
  156. data/ext/enterprise_script_service/msgpack/example/c/CMakeLists.txt +17 -6
  157. data/ext/enterprise_script_service/msgpack/example/c/boundary.c +296 -0
  158. data/ext/enterprise_script_service/msgpack/example/c/jsonconv.c +419 -0
  159. data/ext/enterprise_script_service/msgpack/example/c/simple_c.c +1 -1
  160. data/ext/enterprise_script_service/msgpack/example/cpp03/CMakeLists.txt +3 -3
  161. data/ext/enterprise_script_service/msgpack/example/cpp11/CMakeLists.txt +2 -2
  162. data/ext/enterprise_script_service/msgpack/example/x3/CMakeLists.txt +2 -2
  163. data/ext/enterprise_script_service/msgpack/include/msgpack/pack.h +24 -1
  164. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/array_ref.hpp +5 -4
  165. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/boost/optional.hpp +4 -4
  166. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/cpp17/vector_byte.hpp +8 -8
  167. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/map.hpp +4 -4
  168. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/vector.hpp +4 -4
  169. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/vector_char.hpp +8 -8
  170. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/vector_unsigned_char.hpp +8 -8
  171. data/ext/enterprise_script_service/msgpack/include/msgpack/v1/adaptor/wstring.hpp +4 -4
  172. data/ext/enterprise_script_service/msgpack/include/msgpack/v3/unpack.hpp +6 -6
  173. data/ext/enterprise_script_service/msgpack/include/msgpack/version_master.h +2 -2
  174. data/ext/enterprise_script_service/msgpack/include/msgpack/zbuffer.h +4 -4
  175. data/ext/enterprise_script_service/msgpack/make_file_list.sh +38 -11
  176. data/ext/enterprise_script_service/msgpack/src/vrefbuffer.c +6 -0
  177. data/ext/enterprise_script_service/msgpack/test/CMakeLists.txt +86 -64
  178. data/ext/enterprise_script_service/msgpack/test/array_ref.cpp +4 -0
  179. data/ext/enterprise_script_service/msgpack/test/boost_fusion.cpp +4 -0
  180. data/ext/enterprise_script_service/msgpack/test/boost_optional.cpp +4 -0
  181. data/ext/enterprise_script_service/msgpack/test/boost_string_ref.cpp +4 -1
  182. data/ext/enterprise_script_service/msgpack/test/boost_string_view.cpp +4 -0
  183. data/ext/enterprise_script_service/msgpack/test/boost_variant.cpp +4 -0
  184. data/ext/enterprise_script_service/msgpack/test/buffer.cpp +4 -47
  185. data/ext/enterprise_script_service/msgpack/test/buffer_c.cpp +148 -0
  186. data/ext/enterprise_script_service/msgpack/test/carray.cpp +4 -0
  187. data/ext/enterprise_script_service/msgpack/test/cases.cpp +8 -4
  188. data/ext/enterprise_script_service/msgpack/test/convert.cpp +8 -4
  189. data/ext/enterprise_script_service/msgpack/test/fixint.cpp +4 -0
  190. data/ext/enterprise_script_service/msgpack/test/fixint_c.cpp +4 -0
  191. data/ext/enterprise_script_service/msgpack/test/fuzz_unpack_pack_fuzzer_cpp11.cpp +4 -0
  192. data/ext/enterprise_script_service/msgpack/test/iterator_cpp11.cpp +4 -0
  193. data/ext/enterprise_script_service/msgpack/test/json.cpp +4 -0
  194. data/ext/enterprise_script_service/msgpack/test/limit.cpp +8 -4
  195. data/ext/enterprise_script_service/msgpack/test/msgpack_basic.cpp +4 -0
  196. data/ext/enterprise_script_service/msgpack/test/msgpack_c.cpp +159 -0
  197. data/ext/enterprise_script_service/msgpack/test/msgpack_container.cpp +4 -0
  198. data/ext/enterprise_script_service/msgpack/test/msgpack_cpp11.cpp +32 -27
  199. data/ext/enterprise_script_service/msgpack/test/msgpack_cpp17.cpp +4 -0
  200. data/ext/enterprise_script_service/msgpack/test/msgpack_stream.cpp +4 -0
  201. data/ext/enterprise_script_service/msgpack/test/msgpack_tuple.cpp +4 -1
  202. data/ext/enterprise_script_service/msgpack/test/msgpack_vref.cpp +4 -0
  203. data/ext/enterprise_script_service/msgpack/test/msgpack_x3_parse.cpp +4 -0
  204. data/ext/enterprise_script_service/msgpack/test/object.cpp +4 -1
  205. data/ext/enterprise_script_service/msgpack/test/object_with_zone.cpp +12 -8
  206. data/ext/enterprise_script_service/msgpack/test/pack_unpack.cpp +30 -26
  207. data/ext/enterprise_script_service/msgpack/test/pack_unpack_c.cpp +4 -0
  208. data/ext/enterprise_script_service/msgpack/test/raw.cpp +4 -0
  209. data/ext/enterprise_script_service/msgpack/test/reference.cpp +4 -0
  210. data/ext/enterprise_script_service/msgpack/test/reference_cpp11.cpp +4 -0
  211. data/ext/enterprise_script_service/msgpack/test/reference_wrapper_cpp11.cpp +4 -0
  212. data/ext/enterprise_script_service/msgpack/test/shared_ptr_cpp11.cpp +4 -0
  213. data/ext/enterprise_script_service/msgpack/test/size_equal_only.cpp +4 -0
  214. data/ext/enterprise_script_service/msgpack/test/streaming.cpp +8 -4
  215. data/ext/enterprise_script_service/msgpack/test/streaming_c.cpp +4 -0
  216. data/ext/enterprise_script_service/msgpack/test/unique_ptr_cpp11.cpp +4 -0
  217. data/ext/enterprise_script_service/msgpack/test/user_class.cpp +16 -12
  218. data/ext/enterprise_script_service/msgpack/test/version.cpp +4 -0
  219. data/ext/enterprise_script_service/msgpack/test/visitor.cpp +4 -0
  220. data/ext/enterprise_script_service/msgpack/test/zone.cpp +4 -0
  221. data/lib/script_core/version.rb +1 -1
  222. data/script_core.gemspec +1 -1
  223. metadata +23 -9
  224. data/ext/enterprise_script_service/msgpack/.travis.yml +0 -258
@@ -170,21 +170,16 @@ def seek(i, whence = SEEK_SET)
170
170
  end
171
171
 
172
172
  def _read_buf
173
- return @buf if @buf && @buf.bytesize >= 4 # maximum UTF-8 character is 4 bytes
174
- @buf ||= ""
175
- begin
176
- @buf += sysread(BUF_SIZE)
177
- rescue EOFError => e
178
- raise e if @buf.empty?
179
- end
173
+ return @buf if @buf && @buf.bytesize > 0
174
+ sysread(BUF_SIZE, @buf)
180
175
  end
181
176
 
182
177
  def ungetc(substr)
183
178
  raise TypeError.new "expect String, got #{substr.class}" unless substr.is_a?(String)
184
179
  if @buf.empty?
185
- @buf = substr.dup
180
+ @buf.replace(substr)
186
181
  else
187
- @buf = substr + @buf
182
+ @buf[0,0] = substr
188
183
  end
189
184
  nil
190
185
  end
@@ -288,15 +283,15 @@ def gets(*args)
288
283
 
289
284
  def readchar
290
285
  _read_buf
291
- c = @buf[0]
292
- @buf[0] = ""
293
- c
286
+ _readchar(@buf)
294
287
  end
295
288
 
296
289
  def getc
297
290
  begin
298
291
  readchar
299
292
  rescue EOFError
293
+ c = @buf[0]
294
+ @buf[0,1]="" if c
300
295
  nil
301
296
  end
302
297
  end
@@ -48,6 +48,7 @@
48
48
  #if defined(_WIN32) || defined(_WIN64)
49
49
  #define PATH_SEPARATOR ";"
50
50
  #define FILE_ALT_SEPARATOR "\\"
51
+ #define VOLUME_SEPARATOR ":"
51
52
  #else
52
53
  #define PATH_SEPARATOR ":"
53
54
  #endif
@@ -88,7 +89,7 @@ flock(int fd, int operation) {
88
89
  }
89
90
  #endif
90
91
 
91
- mrb_value
92
+ static mrb_value
92
93
  mrb_file_s_umask(mrb_state *mrb, mrb_value klass)
93
94
  {
94
95
  #if defined(_WIN32) || defined(_WIN64)
@@ -264,7 +265,7 @@ mrb_file_realpath(mrb_state *mrb, mrb_value klass)
264
265
  return result;
265
266
  }
266
267
 
267
- mrb_value
268
+ static mrb_value
268
269
  mrb_file__getwd(mrb_state *mrb, mrb_value klass)
269
270
  {
270
271
  mrb_value path;
@@ -279,12 +280,59 @@ mrb_file__getwd(mrb_state *mrb, mrb_value klass)
279
280
  return path;
280
281
  }
281
282
 
283
+ #ifdef _WIN32
284
+ #define IS_FILESEP(x) (x == (*(char*)(FILE_SEPARATOR)) || x == (*(char*)(FILE_ALT_SEPARATOR)))
285
+ #define IS_VOLSEP(x) (x == (*(char*)(VOLUME_SEPARATOR)))
286
+ #define IS_DEVICEID(x) (x == '.' || x == '?')
287
+ #define CHECK_UNCDEV_PATH (IS_FILESEP(path[0]) && IS_FILESEP(path[1]))
288
+
289
+ static int
290
+ is_absolute_traditional_path(const char *path, size_t len)
291
+ {
292
+ if (len < 3) return 0;
293
+ return (ISALPHA(path[0]) && IS_VOLSEP(path[1]) && IS_FILESEP(path[2]));
294
+ }
295
+
296
+ static int
297
+ is_aboslute_unc_path(const char *path, size_t len) {
298
+ if (len < 2) return 0;
299
+ return (CHECK_UNCDEV_PATH && !IS_DEVICEID(path[2]));
300
+ }
301
+
302
+ static int
303
+ is_absolute_device_path(const char *path, size_t len) {
304
+ if (len < 4) return 0;
305
+ return (CHECK_UNCDEV_PATH && IS_DEVICEID(path[2]) && IS_FILESEP(path[3]));
306
+ }
307
+
282
308
  static int
283
309
  mrb_file_is_absolute_path(const char *path)
284
310
  {
285
- return (path[0] == '/');
311
+ size_t len = strlen(path);
312
+ if (IS_FILESEP(path[0])) return 1;
313
+ if (len > 0)
314
+ return (
315
+ is_absolute_traditional_path(path, len) ||
316
+ is_aboslute_unc_path(path, len) ||
317
+ is_absolute_device_path(path, len)
318
+ );
319
+ else
320
+ return 0;
286
321
  }
287
322
 
323
+ #undef IS_FILESEP
324
+ #undef IS_VOLSEP
325
+ #undef IS_DEVICEID
326
+ #undef CHECK_UNCDEV_PATH
327
+
328
+ #else
329
+ static int
330
+ mrb_file_is_absolute_path(const char *path)
331
+ {
332
+ return (path[0] == *(char*)(FILE_SEPARATOR));
333
+ }
334
+ #endif
335
+
288
336
  static mrb_value
289
337
  mrb_file__gethome(mrb_state *mrb, mrb_value klass)
290
338
  {
@@ -319,7 +367,7 @@ mrb_file__gethome(mrb_state *mrb, mrb_value klass)
319
367
  path = mrb_str_new_cstr(mrb, home);
320
368
  mrb_locale_free(home);
321
369
  return path;
322
- #else
370
+ #else /* _WIN32 */
323
371
  argc = mrb_get_argc(mrb);
324
372
  if (argc == 0) {
325
373
  home = getenv("USERPROFILE");
@@ -353,7 +401,7 @@ mrb_file_mtime(mrb_state *mrb, mrb_value self)
353
401
  return mrb_funcall(mrb, obj, "at", 1, mrb_fixnum_value(st.st_mtime));
354
402
  }
355
403
 
356
- mrb_value
404
+ static mrb_value
357
405
  mrb_file_flock(mrb_state *mrb, mrb_value self)
358
406
  {
359
407
  #if defined(sun)
@@ -402,15 +450,15 @@ mrb_file_size(mrb_state *mrb, mrb_value self)
402
450
  #ifdef MRB_WITHOUT_FLOAT
403
451
  mrb_raise(mrb, E_RUNTIME_ERROR, "File#size too large for MRB_WITHOUT_FLOAT");
404
452
  #else
405
- return mrb_float_value(mrb, st.st_size);
453
+ return mrb_float_value(mrb, (mrb_float)st.st_size);
406
454
  #endif
407
455
  }
408
456
 
409
- return mrb_fixnum_value(st.st_size);
457
+ return mrb_fixnum_value((mrb_int)st.st_size);
410
458
  }
411
459
 
412
460
  static int
413
- mrb_ftruncate(int fd, int64_t length)
461
+ mrb_ftruncate(int fd, mrb_int length)
414
462
  {
415
463
  #ifndef _WIN32
416
464
  return ftruncate(fd, (off_t)length);
@@ -443,32 +491,12 @@ static mrb_value
443
491
  mrb_file_truncate(mrb_state *mrb, mrb_value self)
444
492
  {
445
493
  int fd;
446
- int64_t length;
494
+ mrb_int length;
447
495
  mrb_value lenv;
448
496
 
449
497
  fd = mrb_io_fileno(mrb, self);
450
498
  mrb_get_args(mrb, "o", &lenv);
451
- switch (mrb_type(lenv)) {
452
- #ifndef MRB_WITHOUT_FLOAT
453
- case MRB_TT_FLOAT:
454
- {
455
- mrb_float lenf = mrb_float(lenv);
456
- if (lenf > INT64_MAX) {
457
- mrb_raise(mrb, E_ARGUMENT_ERROR, "length too large");
458
- }
459
- length = (int64_t)lenf;
460
- }
461
- break;
462
- #endif
463
- case MRB_TT_FIXNUM:
464
- default:
465
- {
466
- mrb_int leni = mrb_int(mrb, lenv);
467
- length = (int64_t)leni;
468
- }
469
- break;
470
- }
471
-
499
+ length = mrb_int(mrb, lenv);
472
500
  if (mrb_ftruncate(fd, length) != 0) {
473
501
  mrb_raise(mrb, E_IO_ERROR, "ftruncate failed");
474
502
  }
@@ -599,4 +627,22 @@ mrb_init_file(mrb_state *mrb)
599
627
  #endif
600
628
  mrb_define_const(mrb, cnst, "NULL", mrb_str_new_cstr(mrb, NULL_FILE));
601
629
 
630
+ mrb_define_const(mrb, cnst, "RDONLY", mrb_fixnum_value(MRB_O_RDONLY));
631
+ mrb_define_const(mrb, cnst, "WRONLY", mrb_fixnum_value(MRB_O_WRONLY));
632
+ mrb_define_const(mrb, cnst, "RDWR", mrb_fixnum_value(MRB_O_RDWR));
633
+ mrb_define_const(mrb, cnst, "APPEND", mrb_fixnum_value(MRB_O_APPEND));
634
+ mrb_define_const(mrb, cnst, "CREAT", mrb_fixnum_value(MRB_O_CREAT));
635
+ mrb_define_const(mrb, cnst, "EXCL", mrb_fixnum_value(MRB_O_EXCL));
636
+ mrb_define_const(mrb, cnst, "TRUNC", mrb_fixnum_value(MRB_O_TRUNC));
637
+ mrb_define_const(mrb, cnst, "NONBLOCK", mrb_fixnum_value(MRB_O_NONBLOCK));
638
+ mrb_define_const(mrb, cnst, "NOCTTY", mrb_fixnum_value(MRB_O_NOCTTY));
639
+ mrb_define_const(mrb, cnst, "BINARY", mrb_fixnum_value(MRB_O_BINARY));
640
+ mrb_define_const(mrb, cnst, "SHARE_DELETE", mrb_fixnum_value(MRB_O_SHARE_DELETE));
641
+ mrb_define_const(mrb, cnst, "SYNC", mrb_fixnum_value(MRB_O_SYNC));
642
+ mrb_define_const(mrb, cnst, "DSYNC", mrb_fixnum_value(MRB_O_DSYNC));
643
+ mrb_define_const(mrb, cnst, "RSYNC", mrb_fixnum_value(MRB_O_RSYNC));
644
+ mrb_define_const(mrb, cnst, "NOFOLLOW", mrb_fixnum_value(MRB_O_NOFOLLOW));
645
+ mrb_define_const(mrb, cnst, "NOATIME", mrb_fixnum_value(MRB_O_NOATIME));
646
+ mrb_define_const(mrb, cnst, "DIRECT", mrb_fixnum_value(MRB_O_DIRECT));
647
+ mrb_define_const(mrb, cnst, "TMPFILE", mrb_fixnum_value(MRB_O_TMPFILE));
602
648
  }
@@ -28,7 +28,6 @@
28
28
  #include <fcntl.h>
29
29
 
30
30
  #include <errno.h>
31
- #include <stdio.h>
32
31
  #include <stdlib.h>
33
32
  #include <string.h>
34
33
 
@@ -86,7 +85,7 @@ mrb_lstat(mrb_state *mrb, mrb_value obj, struct stat *st)
86
85
  * File.directory?(".")
87
86
  */
88
87
 
89
- mrb_value
88
+ static mrb_value
90
89
  mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
91
90
  {
92
91
  #ifndef S_ISDIR
@@ -113,7 +112,7 @@ mrb_filetest_s_directory_p(mrb_state *mrb, mrb_value klass)
113
112
  * Returns <code>true</code> if the named file is a pipe.
114
113
  */
115
114
 
116
- mrb_value
115
+ static mrb_value
117
116
  mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
118
117
  {
119
118
  #if defined(_WIN32) || defined(_WIN64)
@@ -146,7 +145,7 @@ mrb_filetest_s_pipe_p(mrb_state *mrb, mrb_value klass)
146
145
  * Returns <code>true</code> if the named file is a symbolic link.
147
146
  */
148
147
 
149
- mrb_value
148
+ static mrb_value
150
149
  mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
151
150
  {
152
151
  #if defined(_WIN32) || defined(_WIN64)
@@ -189,7 +188,7 @@ mrb_filetest_s_symlink_p(mrb_state *mrb, mrb_value klass)
189
188
  * Returns <code>true</code> if the named file is a socket.
190
189
  */
191
190
 
192
- mrb_value
191
+ static mrb_value
193
192
  mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
194
193
  {
195
194
  #if defined(_WIN32) || defined(_WIN64)
@@ -233,7 +232,7 @@ mrb_filetest_s_socket_p(mrb_state *mrb, mrb_value klass)
233
232
  * Return <code>true</code> if the named file exists.
234
233
  */
235
234
 
236
- mrb_value
235
+ static mrb_value
237
236
  mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
238
237
  {
239
238
  struct stat st;
@@ -254,7 +253,7 @@ mrb_filetest_s_exist_p(mrb_state *mrb, mrb_value klass)
254
253
  * regular file.
255
254
  */
256
255
 
257
- mrb_value
256
+ static mrb_value
258
257
  mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
259
258
  {
260
259
  #ifndef S_ISREG
@@ -282,7 +281,7 @@ mrb_filetest_s_file_p(mrb_state *mrb, mrb_value klass)
282
281
  * a zero size.
283
282
  */
284
283
 
285
- mrb_value
284
+ static mrb_value
286
285
  mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
287
286
  {
288
287
  struct stat st;
@@ -307,7 +306,7 @@ mrb_filetest_s_zero_p(mrb_state *mrb, mrb_value klass)
307
306
  * _file_name_ can be an IO object.
308
307
  */
309
308
 
310
- mrb_value
309
+ static mrb_value
311
310
  mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
312
311
  {
313
312
  struct stat st;
@@ -329,7 +328,7 @@ mrb_filetest_s_size(mrb_state *mrb, mrb_value klass)
329
328
  * file otherwise.
330
329
  */
331
330
 
332
- mrb_value
331
+ static mrb_value
333
332
  mrb_filetest_s_size_p(mrb_state *mrb, mrb_value klass)
334
333
  {
335
334
  struct stat st;
@@ -31,14 +31,21 @@
31
31
  typedef long ftime_t;
32
32
  typedef long fsuseconds_t;
33
33
  typedef int fmode_t;
34
+ typedef int mrb_io_read_write_size;
35
+
36
+ #ifndef O_TMPFILE
37
+ #define O_TMPFILE O_TEMPORARY
38
+ #endif
34
39
 
35
40
  #else
36
41
  #include <sys/wait.h>
42
+ #include <sys/time.h>
37
43
  #include <unistd.h>
38
44
  typedef size_t fsize_t;
39
45
  typedef time_t ftime_t;
40
46
  typedef suseconds_t fsuseconds_t;
41
47
  typedef mode_t fmode_t;
48
+ typedef ssize_t mrb_io_read_write_size;
42
49
  #endif
43
50
 
44
51
  #ifdef _MSC_VER
@@ -48,9 +55,14 @@ typedef mrb_int pid_t;
48
55
  #include <fcntl.h>
49
56
 
50
57
  #include <errno.h>
51
- #include <stdio.h>
52
58
  #include <string.h>
53
59
 
60
+ #define OPEN_ACCESS_MODE_FLAGS (O_RDONLY | O_WRONLY | O_RDWR)
61
+ #define OPEN_RDONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDONLY))
62
+ #define OPEN_WRONLY_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_WRONLY))
63
+ #define OPEN_RDWR_P(f) ((mrb_bool)(((f) & OPEN_ACCESS_MODE_FLAGS) == O_RDWR))
64
+ #define OPEN_READABLE_P(f) ((mrb_bool)(OPEN_RDONLY_P(f) || OPEN_RDWR_P(f)))
65
+ #define OPEN_WRITABLE_P(f) ((mrb_bool)(OPEN_WRONLY_P(f) || OPEN_RDWR_P(f)))
54
66
 
55
67
  static void mrb_io_free(mrb_state *mrb, void *ptr);
56
68
  struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
@@ -58,7 +70,7 @@ struct mrb_data_type mrb_io_type = { "IO", mrb_io_free };
58
70
 
59
71
  static struct mrb_io *io_get_open_fptr(mrb_state *mrb, mrb_value self);
60
72
  static int mrb_io_modestr_to_flags(mrb_state *mrb, const char *modestr);
61
- static int mrb_io_flags_to_modenum(mrb_state *mrb, int flags);
73
+ static int mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode);
62
74
  static void fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet);
63
75
 
64
76
  static struct mrb_io *
@@ -100,30 +112,33 @@ io_set_process_status(mrb_state *mrb, pid_t pid, int status)
100
112
  static int
101
113
  mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
102
114
  {
103
- int flags = 0;
115
+ int flags;
104
116
  const char *m = mode;
105
117
 
106
118
  switch (*m++) {
107
119
  case 'r':
108
- flags |= FMODE_READABLE;
120
+ flags = O_RDONLY;
109
121
  break;
110
122
  case 'w':
111
- flags |= FMODE_WRITABLE | FMODE_CREATE | FMODE_TRUNC;
123
+ flags = O_WRONLY | O_CREAT | O_TRUNC;
112
124
  break;
113
125
  case 'a':
114
- flags |= FMODE_WRITABLE | FMODE_APPEND | FMODE_CREATE;
126
+ flags = O_WRONLY | O_CREAT | O_APPEND;
115
127
  break;
116
128
  default:
117
129
  mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode);
130
+ flags = 0; /* not reached */
118
131
  }
119
132
 
120
133
  while (*m) {
121
134
  switch (*m++) {
122
135
  case 'b':
123
- flags |= FMODE_BINMODE;
136
+ #ifdef O_BINARY
137
+ flags |= O_BINARY;
138
+ #endif
124
139
  break;
125
140
  case '+':
126
- flags |= FMODE_READWRITE;
141
+ flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR;
127
142
  break;
128
143
  case ':':
129
144
  /* XXX: PASSTHROUGH*/
@@ -136,38 +151,72 @@ mrb_io_modestr_to_flags(mrb_state *mrb, const char *mode)
136
151
  }
137
152
 
138
153
  static int
139
- mrb_io_flags_to_modenum(mrb_state *mrb, int flags)
154
+ mrb_io_mode_to_flags(mrb_state *mrb, mrb_value mode)
140
155
  {
141
- int modenum = 0;
142
-
143
- switch(flags & (FMODE_READABLE|FMODE_WRITABLE|FMODE_READWRITE)) {
144
- case FMODE_READABLE:
145
- modenum = O_RDONLY;
146
- break;
147
- case FMODE_WRITABLE:
148
- modenum = O_WRONLY;
149
- break;
150
- case FMODE_READWRITE:
151
- modenum = O_RDWR;
152
- break;
153
- }
154
-
155
- if (flags & FMODE_APPEND) {
156
- modenum |= O_APPEND;
157
- }
158
- if (flags & FMODE_TRUNC) {
159
- modenum |= O_TRUNC;
156
+ if (mrb_nil_p(mode)) {
157
+ return mrb_io_modestr_to_flags(mrb, "r");
160
158
  }
161
- if (flags & FMODE_CREATE) {
162
- modenum |= O_CREAT;
159
+ else if (mrb_string_p(mode)) {
160
+ return mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
163
161
  }
162
+ else {
163
+ int flags = 0;
164
+ mrb_int flags0 = mrb_int(mrb, mode);
165
+
166
+ switch (flags0 & MRB_O_ACCMODE) {
167
+ case MRB_O_RDONLY:
168
+ flags |= O_RDONLY;
169
+ break;
170
+ case MRB_O_WRONLY:
171
+ flags |= O_WRONLY;
172
+ break;
173
+ case MRB_O_RDWR:
174
+ flags |= O_RDWR;
175
+ break;
176
+ default:
177
+ mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %v", mode);
178
+ }
179
+
180
+ if (flags0 & MRB_O_APPEND) flags |= O_APPEND;
181
+ if (flags0 & MRB_O_CREAT) flags |= O_CREAT;
182
+ if (flags0 & MRB_O_EXCL) flags |= O_EXCL;
183
+ if (flags0 & MRB_O_TRUNC) flags |= O_TRUNC;
184
+ #ifdef O_NONBLOCK
185
+ if (flags0 & MRB_O_NONBLOCK) flags |= O_NONBLOCK;
186
+ #endif
187
+ #ifdef O_NOCTTY
188
+ if (flags0 & MRB_O_NOCTTY) flags |= O_NOCTTY;
189
+ #endif
164
190
  #ifdef O_BINARY
165
- if (flags & FMODE_BINMODE) {
166
- modenum |= O_BINARY;
167
- }
191
+ if (flags0 & MRB_O_BINARY) flags |= O_BINARY;
192
+ #endif
193
+ #ifdef O_SHARE_DELETE
194
+ if (flags0 & MRB_O_SHARE_DELETE) flags |= O_SHARE_DELETE;
195
+ #endif
196
+ #ifdef O_SYNC
197
+ if (flags0 & MRB_O_SYNC) flags |= O_SYNC;
198
+ #endif
199
+ #ifdef O_DSYNC
200
+ if (flags0 & MRB_O_DSYNC) flags |= O_DSYNC;
201
+ #endif
202
+ #ifdef O_RSYNC
203
+ if (flags0 & MRB_O_RSYNC) flags |= O_RSYNC;
204
+ #endif
205
+ #ifdef O_NOFOLLOW
206
+ if (flags0 & MRB_O_NOFOLLOW) flags |= O_NOFOLLOW;
207
+ #endif
208
+ #ifdef O_NOATIME
209
+ if (flags0 & MRB_O_NOATIME) flags |= O_NOATIME;
210
+ #endif
211
+ #ifdef O_DIRECT
212
+ if (flags0 & MRB_O_DIRECT) flags |= O_DIRECT;
213
+ #endif
214
+ #ifdef O_TMPFILE
215
+ if (flags0 & MRB_O_TMPFILE) flags |= O_TMPFILE;
168
216
  #endif
169
217
 
170
- return modenum;
218
+ return flags;
219
+ }
171
220
  }
172
221
 
173
222
  static void
@@ -292,7 +341,7 @@ option_to_fd(mrb_state *mrb, mrb_value hash, const char *key)
292
341
  }
293
342
 
294
343
  #ifdef _WIN32
295
- mrb_value
344
+ static mrb_value
296
345
  mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
297
346
  {
298
347
  mrb_value cmd, io;
@@ -317,11 +366,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
317
366
  ofd[0] = INVALID_HANDLE_VALUE;
318
367
  ofd[1] = INVALID_HANDLE_VALUE;
319
368
 
320
- mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
369
+ mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
321
370
  io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
322
371
 
323
372
  pname = RSTRING_CSTR(mrb, cmd);
324
- flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
373
+ flags = mrb_io_mode_to_flags(mrb, mode);
325
374
 
326
375
  doexec = (strcmp("-", pname) != 0);
327
376
  opt_in = option_to_fd(mrb, opt, "in");
@@ -332,14 +381,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
332
381
  saAttr.bInheritHandle = TRUE;
333
382
  saAttr.lpSecurityDescriptor = NULL;
334
383
 
335
- if (flags & FMODE_READABLE) {
384
+ if (OPEN_READABLE_P(flags)) {
336
385
  if (!CreatePipe(&ofd[0], &ofd[1], &saAttr, 0)
337
386
  || !SetHandleInformation(ofd[0], HANDLE_FLAG_INHERIT, 0)) {
338
387
  mrb_sys_fail(mrb, "pipe");
339
388
  }
340
389
  }
341
390
 
342
- if (flags & FMODE_WRITABLE) {
391
+ if (OPEN_WRITABLE_P(flags)) {
343
392
  if (!CreatePipe(&ifd[0], &ifd[1], &saAttr, 0)
344
393
  || !SetHandleInformation(ifd[1], HANDLE_FLAG_INHERIT, 0)) {
345
394
  mrb_sys_fail(mrb, "pipe");
@@ -353,11 +402,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
353
402
  si.dwFlags |= STARTF_USESHOWWINDOW;
354
403
  si.wShowWindow = SW_HIDE;
355
404
  si.dwFlags |= STARTF_USESTDHANDLES;
356
- if (flags & FMODE_READABLE) {
405
+ if (OPEN_READABLE_P(flags)) {
357
406
  si.hStdOutput = ofd[1];
358
407
  si.hStdError = ofd[1];
359
408
  }
360
- if (flags & FMODE_WRITABLE) {
409
+ if (OPEN_WRITABLE_P(flags)) {
361
410
  si.hStdInput = ifd[0];
362
411
  }
363
412
  if (!CreateProcess(
@@ -381,8 +430,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
381
430
  fptr->fd = _open_osfhandle((intptr_t)ofd[0], 0);
382
431
  fptr->fd2 = _open_osfhandle((intptr_t)ifd[1], 0);
383
432
  fptr->pid = pid;
384
- fptr->readable = ((flags & FMODE_READABLE) != 0);
385
- fptr->writable = ((flags & FMODE_WRITABLE) != 0);
433
+ fptr->readable = OPEN_READABLE_P(flags);
434
+ fptr->writable = OPEN_WRITABLE_P(flags);
386
435
  fptr->sync = 0;
387
436
 
388
437
  DATA_TYPE(io) = &mrb_io_type;
@@ -390,14 +439,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
390
439
  return io;
391
440
  }
392
441
  #elif defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE
393
- mrb_value
442
+ static mrb_value
394
443
  mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
395
444
  {
396
445
  mrb_raise(mrb, E_NOTIMP_ERROR, "IO#popen is not supported on the platform");
397
446
  return mrb_false_value();
398
447
  }
399
448
  #else
400
- mrb_value
449
+ static mrb_value
401
450
  mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
402
451
  {
403
452
  mrb_value cmd, io, result;
@@ -413,18 +462,18 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
413
462
  int saved_errno;
414
463
  int opt_in, opt_out, opt_err;
415
464
 
416
- mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt);
465
+ mrb_get_args(mrb, "S|oH", &cmd, &mode, &opt);
417
466
  io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type));
418
467
 
419
468
  pname = RSTRING_CSTR(mrb, cmd);
420
- flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
469
+ flags = mrb_io_mode_to_flags(mrb, mode);
421
470
 
422
471
  doexec = (strcmp("-", pname) != 0);
423
472
  opt_in = option_to_fd(mrb, opt, "in");
424
473
  opt_out = option_to_fd(mrb, opt, "out");
425
474
  opt_err = option_to_fd(mrb, opt, "err");
426
475
 
427
- if (flags & FMODE_READABLE) {
476
+ if (OPEN_READABLE_P(flags)) {
428
477
  if (pipe(pr) == -1) {
429
478
  mrb_sys_fail(mrb, "pipe");
430
479
  }
@@ -432,7 +481,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
432
481
  mrb_fd_cloexec(mrb, pr[1]);
433
482
  }
434
483
 
435
- if (flags & FMODE_WRITABLE) {
484
+ if (OPEN_WRITABLE_P(flags)) {
436
485
  if (pipe(pw) == -1) {
437
486
  if (pr[0] != -1) close(pr[0]);
438
487
  if (pr[1] != -1) close(pr[1]);
@@ -461,14 +510,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
461
510
  if (opt_err != -1) {
462
511
  dup2(opt_err, 2);
463
512
  }
464
- if (flags & FMODE_READABLE) {
513
+ if (OPEN_READABLE_P(flags)) {
465
514
  close(pr[0]);
466
515
  if (pr[1] != 1) {
467
516
  dup2(pr[1], 1);
468
517
  close(pr[1]);
469
518
  }
470
519
  }
471
- if (flags & FMODE_WRITABLE) {
520
+ if (OPEN_WRITABLE_P(flags)) {
472
521
  close(pw[1]);
473
522
  if (pw[0] != 0) {
474
523
  dup2(pw[0], 0);
@@ -487,12 +536,12 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
487
536
  break;
488
537
 
489
538
  default: /* parent */
490
- if ((flags & FMODE_READABLE) && (flags & FMODE_WRITABLE)) {
539
+ if (OPEN_RDWR_P(flags)) {
491
540
  close(pr[1]);
492
541
  fd = pr[0];
493
542
  close(pw[0]);
494
543
  write_fd = pw[1];
495
- } else if (flags & FMODE_READABLE) {
544
+ } else if (OPEN_RDONLY_P(flags)) {
496
545
  close(pr[1]);
497
546
  fd = pr[0];
498
547
  } else {
@@ -506,8 +555,8 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
506
555
  fptr->fd = fd;
507
556
  fptr->fd2 = write_fd;
508
557
  fptr->pid = pid;
509
- fptr->readable = ((flags & FMODE_READABLE) != 0);
510
- fptr->writable = ((flags & FMODE_WRITABLE) != 0);
558
+ fptr->readable = OPEN_READABLE_P(flags);
559
+ fptr->writable = OPEN_WRITABLE_P(flags);
511
560
  fptr->sync = 0;
512
561
 
513
562
  DATA_TYPE(io) = &mrb_io_type;
@@ -517,11 +566,11 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass)
517
566
 
518
567
  case -1: /* error */
519
568
  saved_errno = errno;
520
- if (flags & FMODE_READABLE) {
569
+ if (OPEN_READABLE_P(flags)) {
521
570
  close(pr[0]);
522
571
  close(pr[1]);
523
572
  }
524
- if (flags & FMODE_WRITABLE) {
573
+ if (OPEN_WRITABLE_P(flags)) {
525
574
  close(pw[0]);
526
575
  close(pw[1]);
527
576
  }
@@ -547,7 +596,7 @@ mrb_dup(mrb_state *mrb, int fd, mrb_bool *failed)
547
596
  return new_fd;
548
597
  }
549
598
 
550
- mrb_value
599
+ static mrb_value
551
600
  mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
552
601
  {
553
602
  mrb_value orig;
@@ -596,7 +645,44 @@ mrb_io_initialize_copy(mrb_state *mrb, mrb_value copy)
596
645
  return copy;
597
646
  }
598
647
 
599
- mrb_value
648
+ static void
649
+ check_file_descriptor(mrb_state *mrb, mrb_int fd)
650
+ {
651
+ struct stat sb;
652
+ int fdi = (int)fd;
653
+
654
+ #if MRB_INT_MIN < INT_MIN || MRB_INT_MAX > INT_MAX
655
+ if (fdi != fd) {
656
+ goto badfd;
657
+ }
658
+ #endif
659
+
660
+ #ifdef _WIN32
661
+ {
662
+ DWORD err;
663
+ int len = sizeof(err);
664
+
665
+ if (getsockopt(fdi, SOL_SOCKET, SO_ERROR, (char*)&err, &len) == 0) {
666
+ return;
667
+ }
668
+ }
669
+
670
+ if (fdi < 0 || fdi > _getmaxstdio()) {
671
+ goto badfd;
672
+ }
673
+ #endif /* _WIN32 */
674
+
675
+ if (fstat(fdi, &sb) != 0) {
676
+ goto badfd;
677
+ }
678
+
679
+ return;
680
+
681
+ badfd:
682
+ mrb_sys_fail(mrb, "bad file descriptor");
683
+ }
684
+
685
+ static mrb_value
600
686
  mrb_io_initialize(mrb_state *mrb, mrb_value io)
601
687
  {
602
688
  struct mrb_io *fptr;
@@ -606,7 +692,8 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
606
692
 
607
693
  mode = opt = mrb_nil_value();
608
694
 
609
- mrb_get_args(mrb, "i|So", &fd, &mode, &opt);
695
+ mrb_get_args(mrb, "i|oo", &fd, &mode, &opt);
696
+ check_file_descriptor(mrb, fd);
610
697
  if (mrb_nil_p(mode)) {
611
698
  mode = mrb_str_new_cstr(mrb, "r");
612
699
  }
@@ -614,7 +701,7 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
614
701
  opt = mrb_hash_new(mrb);
615
702
  }
616
703
 
617
- flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
704
+ flags = mrb_io_mode_to_flags(mrb, mode);
618
705
 
619
706
  mrb_iv_set(mrb, io, mrb_intern_cstr(mrb, "@buf"), mrb_str_new_cstr(mrb, ""));
620
707
 
@@ -629,8 +716,8 @@ mrb_io_initialize(mrb_state *mrb, mrb_value io)
629
716
  DATA_PTR(io) = fptr;
630
717
 
631
718
  fptr->fd = (int)fd;
632
- fptr->readable = ((flags & FMODE_READABLE) != 0);
633
- fptr->writable = ((flags & FMODE_WRITABLE) != 0);
719
+ fptr->readable = OPEN_READABLE_P(flags);
720
+ fptr->writable = OPEN_WRITABLE_P(flags);
634
721
  fptr->sync = 0;
635
722
  return io;
636
723
  }
@@ -698,7 +785,7 @@ fptr_finalize(mrb_state *mrb, struct mrb_io *fptr, int quiet)
698
785
  }
699
786
  }
700
787
 
701
- mrb_value
788
+ static mrb_value
702
789
  mrb_io_check_readable(mrb_state *mrb, mrb_value self)
703
790
  {
704
791
  struct mrb_io *fptr = io_get_open_fptr(mrb, self);
@@ -708,7 +795,7 @@ mrb_io_check_readable(mrb_state *mrb, mrb_value self)
708
795
  return mrb_nil_value();
709
796
  }
710
797
 
711
- mrb_value
798
+ static mrb_value
712
799
  mrb_io_isatty(mrb_state *mrb, mrb_value self)
713
800
  {
714
801
  struct mrb_io *fptr;
@@ -719,7 +806,7 @@ mrb_io_isatty(mrb_state *mrb, mrb_value self)
719
806
  return mrb_true_value();
720
807
  }
721
808
 
722
- mrb_value
809
+ static mrb_value
723
810
  mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
724
811
  {
725
812
  struct RClass *c = mrb_class_ptr(klass);
@@ -732,7 +819,7 @@ mrb_io_s_for_fd(mrb_state *mrb, mrb_value klass)
732
819
  return mrb_io_initialize(mrb, obj);
733
820
  }
734
821
 
735
- mrb_value
822
+ static mrb_value
736
823
  mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
737
824
  {
738
825
  mrb_int fd;
@@ -743,7 +830,7 @@ mrb_io_s_sysclose(mrb_state *mrb, mrb_value klass)
743
830
  return mrb_fixnum_value(0);
744
831
  }
745
832
 
746
- int
833
+ static int
747
834
  mrb_cloexec_open(mrb_state *mrb, const char *pathname, mrb_int flags, mrb_int mode)
748
835
  {
749
836
  int fd, retry = FALSE;
@@ -778,39 +865,55 @@ reopen:
778
865
  return fd;
779
866
  }
780
867
 
781
- mrb_value
868
+ static mrb_value
782
869
  mrb_io_s_sysopen(mrb_state *mrb, mrb_value klass)
783
870
  {
784
871
  mrb_value path = mrb_nil_value();
785
872
  mrb_value mode = mrb_nil_value();
786
873
  mrb_int fd, perm = -1;
787
874
  const char *pat;
788
- int flags, modenum;
875
+ int flags;
789
876
 
790
- mrb_get_args(mrb, "S|Si", &path, &mode, &perm);
791
- if (mrb_nil_p(mode)) {
792
- mode = mrb_str_new_cstr(mrb, "r");
793
- }
877
+ mrb_get_args(mrb, "S|oi", &path, &mode, &perm);
794
878
  if (perm < 0) {
795
879
  perm = 0666;
796
880
  }
797
881
 
798
882
  pat = RSTRING_CSTR(mrb, path);
799
- flags = mrb_io_modestr_to_flags(mrb, RSTRING_CSTR(mrb, mode));
800
- modenum = mrb_io_flags_to_modenum(mrb, flags);
801
- fd = mrb_cloexec_open(mrb, pat, modenum, perm);
883
+ flags = mrb_io_mode_to_flags(mrb, mode);
884
+ fd = mrb_cloexec_open(mrb, pat, flags, perm);
802
885
  return mrb_fixnum_value(fd);
803
886
  }
804
887
 
805
- mrb_value
888
+ static mrb_value mrb_io_sysread_common(mrb_state *mrb,
889
+ mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
890
+ mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset);
891
+
892
+ static mrb_io_read_write_size
893
+ mrb_sysread_dummy(int fd, void *buf, fsize_t nbytes, off_t offset)
894
+ {
895
+ return (mrb_io_read_write_size)read(fd, buf, nbytes);
896
+ }
897
+
898
+ static mrb_value
806
899
  mrb_io_sysread(mrb_state *mrb, mrb_value io)
807
900
  {
808
- struct mrb_io *fptr;
809
901
  mrb_value buf = mrb_nil_value();
810
902
  mrb_int maxlen;
811
- int ret;
812
903
 
813
904
  mrb_get_args(mrb, "i|S", &maxlen, &buf);
905
+
906
+ return mrb_io_sysread_common(mrb, mrb_sysread_dummy, io, buf, maxlen, 0);
907
+ }
908
+
909
+ static mrb_value
910
+ mrb_io_sysread_common(mrb_state *mrb,
911
+ mrb_io_read_write_size (*readfunc)(int, void *, fsize_t, off_t),
912
+ mrb_value io, mrb_value buf, mrb_int maxlen, off_t offset)
913
+ {
914
+ struct mrb_io *fptr;
915
+ int ret;
916
+
814
917
  if (maxlen < 0) {
815
918
  mrb_raise(mrb, E_ARGUMENT_ERROR, "negative expanding string size");
816
919
  }
@@ -824,7 +927,8 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
824
927
 
825
928
  if (RSTRING_LEN(buf) != maxlen) {
826
929
  buf = mrb_str_resize(mrb, buf, maxlen);
827
- } else {
930
+ }
931
+ else {
828
932
  mrb_str_modify(mrb, RSTRING(buf));
829
933
  }
830
934
 
@@ -832,29 +936,20 @@ mrb_io_sysread(mrb_state *mrb, mrb_value io)
832
936
  if (!fptr->readable) {
833
937
  mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
834
938
  }
835
- ret = read(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen);
836
- switch (ret) {
837
- case 0: /* EOF */
838
- if (maxlen == 0) {
839
- buf = mrb_str_new_cstr(mrb, "");
840
- } else {
841
- mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
842
- }
843
- break;
844
- case -1: /* Error */
845
- mrb_sys_fail(mrb, "sysread failed");
846
- break;
847
- default:
848
- if (RSTRING_LEN(buf) != ret) {
849
- buf = mrb_str_resize(mrb, buf, ret);
850
- }
851
- break;
939
+ ret = readfunc(fptr->fd, RSTRING_PTR(buf), (fsize_t)maxlen, offset);
940
+ if (ret < 0) {
941
+ mrb_sys_fail(mrb, "sysread failed");
942
+ }
943
+ if (RSTRING_LEN(buf) != ret) {
944
+ buf = mrb_str_resize(mrb, buf, ret);
945
+ }
946
+ if (ret == 0 && maxlen > 0) {
947
+ mrb_raise(mrb, E_EOF_ERROR, "sysread failed: End of File");
852
948
  }
853
-
854
949
  return buf;
855
950
  }
856
951
 
857
- mrb_value
952
+ static mrb_value
858
953
  mrb_io_sysseek(mrb_state *mrb, mrb_value io)
859
954
  {
860
955
  struct mrb_io *fptr;
@@ -882,11 +977,12 @@ mrb_io_sysseek(mrb_state *mrb, mrb_value io)
882
977
  }
883
978
  }
884
979
 
885
- mrb_value
886
- mrb_io_syswrite(mrb_state *mrb, mrb_value io)
980
+ static mrb_value
981
+ mrb_io_syswrite_common(mrb_state *mrb,
982
+ mrb_io_read_write_size (*writefunc)(int, const void *, fsize_t, off_t),
983
+ mrb_value io, mrb_value buf, off_t offset)
887
984
  {
888
985
  struct mrb_io *fptr;
889
- mrb_value str, buf;
890
986
  int fd, length;
891
987
 
892
988
  fptr = io_get_open_fptr(mrb, io);
@@ -894,15 +990,12 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
894
990
  mrb_raise(mrb, E_IO_ERROR, "not opened for writing");
895
991
  }
896
992
 
897
- mrb_get_args(mrb, "S", &str);
898
- buf = str;
899
-
900
993
  if (fptr->fd2 == -1) {
901
994
  fd = fptr->fd;
902
995
  } else {
903
996
  fd = fptr->fd2;
904
997
  }
905
- length = write(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf));
998
+ length = writefunc(fd, RSTRING_PTR(buf), (fsize_t)RSTRING_LEN(buf), offset);
906
999
  if (length == -1) {
907
1000
  mrb_sys_fail(mrb, 0);
908
1001
  }
@@ -910,7 +1003,23 @@ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
910
1003
  return mrb_fixnum_value(length);
911
1004
  }
912
1005
 
913
- mrb_value
1006
+ static mrb_io_read_write_size
1007
+ mrb_syswrite_dummy(int fd, const void *buf, fsize_t nbytes, off_t offset)
1008
+ {
1009
+ return (mrb_io_read_write_size)write(fd, buf, nbytes);
1010
+ }
1011
+
1012
+ static mrb_value
1013
+ mrb_io_syswrite(mrb_state *mrb, mrb_value io)
1014
+ {
1015
+ mrb_value buf;
1016
+
1017
+ mrb_get_args(mrb, "S", &buf);
1018
+
1019
+ return mrb_io_syswrite_common(mrb, mrb_syswrite_dummy, io, buf, 0);
1020
+ }
1021
+
1022
+ static mrb_value
914
1023
  mrb_io_close(mrb_state *mrb, mrb_value self)
915
1024
  {
916
1025
  struct mrb_io *fptr;
@@ -919,7 +1028,7 @@ mrb_io_close(mrb_state *mrb, mrb_value self)
919
1028
  return mrb_nil_value();
920
1029
  }
921
1030
 
922
- mrb_value
1031
+ static mrb_value
923
1032
  mrb_io_close_write(mrb_state *mrb, mrb_value self)
924
1033
  {
925
1034
  struct mrb_io *fptr;
@@ -930,7 +1039,7 @@ mrb_io_close_write(mrb_state *mrb, mrb_value self)
930
1039
  return mrb_nil_value();
931
1040
  }
932
1041
 
933
- mrb_value
1042
+ static mrb_value
934
1043
  mrb_io_closed(mrb_state *mrb, mrb_value io)
935
1044
  {
936
1045
  struct mrb_io *fptr;
@@ -942,7 +1051,7 @@ mrb_io_closed(mrb_state *mrb, mrb_value io)
942
1051
  return mrb_true_value();
943
1052
  }
944
1053
 
945
- mrb_value
1054
+ static mrb_value
946
1055
  mrb_io_pid(mrb_state *mrb, mrb_value io)
947
1056
  {
948
1057
  struct mrb_io *fptr;
@@ -1076,6 +1185,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
1076
1185
  for (i = 0; i < RARRAY_LEN(read); i++) {
1077
1186
  read_io = RARRAY_PTR(read)[i];
1078
1187
  fptr = io_get_open_fptr(mrb, read_io);
1188
+ if (fptr->fd >= FD_SETSIZE) continue;
1079
1189
  FD_SET(fptr->fd, rp);
1080
1190
  if (mrb_io_read_data_pending(mrb, read_io)) {
1081
1191
  pending++;
@@ -1098,6 +1208,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
1098
1208
  FD_ZERO(wp);
1099
1209
  for (i = 0; i < RARRAY_LEN(write); i++) {
1100
1210
  fptr = io_get_open_fptr(mrb, RARRAY_PTR(write)[i]);
1211
+ if (fptr->fd >= FD_SETSIZE) continue;
1101
1212
  FD_SET(fptr->fd, wp);
1102
1213
  if (max < fptr->fd)
1103
1214
  max = fptr->fd;
@@ -1117,6 +1228,7 @@ mrb_io_s_select(mrb_state *mrb, mrb_value klass)
1117
1228
  FD_ZERO(ep);
1118
1229
  for (i = 0; i < RARRAY_LEN(except); i++) {
1119
1230
  fptr = io_get_open_fptr(mrb, RARRAY_PTR(except)[i]);
1231
+ if (fptr->fd >= FD_SETSIZE) continue;
1120
1232
  FD_SET(fptr->fd, ep);
1121
1233
  if (max < fptr->fd)
1122
1234
  max = fptr->fd;
@@ -1205,7 +1317,7 @@ mrb_io_fileno_m(mrb_state *mrb, mrb_value io)
1205
1317
  return mrb_fixnum_value(fd);
1206
1318
  }
1207
1319
 
1208
- mrb_value
1320
+ static mrb_value
1209
1321
  mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
1210
1322
  {
1211
1323
  #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
@@ -1229,7 +1341,7 @@ mrb_io_close_on_exec_p(mrb_state *mrb, mrb_value self)
1229
1341
  #endif
1230
1342
  }
1231
1343
 
1232
- mrb_value
1344
+ static mrb_value
1233
1345
  mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
1234
1346
  {
1235
1347
  #if defined(F_GETFD) && defined(F_SETFD) && defined(FD_CLOEXEC)
@@ -1265,7 +1377,7 @@ mrb_io_set_close_on_exec(mrb_state *mrb, mrb_value self)
1265
1377
  #endif
1266
1378
  }
1267
1379
 
1268
- mrb_value
1380
+ static mrb_value
1269
1381
  mrb_io_set_sync(mrb_state *mrb, mrb_value self)
1270
1382
  {
1271
1383
  struct mrb_io *fptr;
@@ -1277,7 +1389,7 @@ mrb_io_set_sync(mrb_state *mrb, mrb_value self)
1277
1389
  return mrb_bool_value(b);
1278
1390
  }
1279
1391
 
1280
- mrb_value
1392
+ static mrb_value
1281
1393
  mrb_io_sync(mrb_state *mrb, mrb_value self)
1282
1394
  {
1283
1395
  struct mrb_io *fptr;
@@ -1285,15 +1397,55 @@ mrb_io_sync(mrb_state *mrb, mrb_value self)
1285
1397
  return mrb_bool_value(fptr->sync);
1286
1398
  }
1287
1399
 
1400
+ #ifndef MRB_WITH_IO_PREAD_PWRITE
1401
+ # define mrb_io_pread mrb_notimplement_m
1402
+ # define mrb_io_pwrite mrb_notimplement_m
1403
+ #else
1404
+ static off_t
1405
+ value2off(mrb_state *mrb, mrb_value offv)
1406
+ {
1407
+ return (off_t)mrb_int(mrb, offv);
1408
+ }
1409
+
1410
+ /*
1411
+ * call-seq:
1412
+ * pread(maxlen, offset, outbuf = "") -> outbuf
1413
+ */
1414
+ static mrb_value
1415
+ mrb_io_pread(mrb_state *mrb, mrb_value io)
1416
+ {
1417
+ mrb_value buf = mrb_nil_value();
1418
+ mrb_value off;
1419
+ mrb_int maxlen;
1420
+
1421
+ mrb_get_args(mrb, "io|S!", &maxlen, &off, &buf);
1422
+
1423
+ return mrb_io_sysread_common(mrb, pread, io, buf, maxlen, value2off(mrb, off));
1424
+ }
1425
+
1426
+ /*
1427
+ * call-seq:
1428
+ * pwrite(buffer, offset) -> wrote_bytes
1429
+ */
1430
+ static mrb_value
1431
+ mrb_io_pwrite(mrb_state *mrb, mrb_value io)
1432
+ {
1433
+ mrb_value buf, off;
1434
+
1435
+ mrb_get_args(mrb, "So", &buf, &off);
1436
+
1437
+ return mrb_io_syswrite_common(mrb, pwrite, io, buf, value2off(mrb, off));
1438
+ }
1439
+ #endif /* MRB_WITH_IO_PREAD_PWRITE */
1440
+
1288
1441
  static mrb_value
1289
- io_bufread(mrb_state *mrb, mrb_value self)
1442
+ io_bufread(mrb_state *mrb, mrb_value str, mrb_int len)
1290
1443
  {
1291
- mrb_value str, str2;
1292
- mrb_int len, newlen;
1444
+ mrb_value str2;
1445
+ mrb_int newlen;
1293
1446
  struct RString *s;
1294
1447
  char *p;
1295
1448
 
1296
- mrb_get_args(mrb, "Si", &str, &len);
1297
1449
  s = RSTRING(str);
1298
1450
  mrb_str_modify(mrb, s);
1299
1451
  p = RSTR_PTR(s);
@@ -1306,6 +1458,54 @@ io_bufread(mrb_state *mrb, mrb_value self)
1306
1458
  return str2;
1307
1459
  }
1308
1460
 
1461
+ static mrb_value
1462
+ mrb_io_bufread(mrb_state *mrb, mrb_value self)
1463
+ {
1464
+ mrb_value str;
1465
+ mrb_int len;
1466
+
1467
+ mrb_get_args(mrb, "Si", &str, &len);
1468
+ return io_bufread(mrb, str, len);
1469
+ }
1470
+
1471
+ static mrb_value
1472
+ mrb_io_readchar(mrb_state *mrb, mrb_value self)
1473
+ {
1474
+ mrb_value buf;
1475
+ mrb_int len = 1;
1476
+ #ifdef MRB_UTF8_STRING
1477
+ unsigned char c;
1478
+ #endif
1479
+
1480
+ mrb_get_args(mrb, "S", &buf);
1481
+ mrb_assert(RSTRING_LEN(buf) > 0);
1482
+ mrb_assert(RSTRING_PTR(buf) != NULL);
1483
+ mrb_str_modify(mrb, RSTRING(buf));
1484
+ #ifdef MRB_UTF8_STRING
1485
+ c = RSTRING_PTR(buf)[0];
1486
+ if (c & 0x80) {
1487
+ len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
1488
+ if (len == 1 && RSTRING_LEN(buf) < 4) { /* partial UTF-8 */
1489
+ mrb_int blen = RSTRING_LEN(buf);
1490
+ ssize_t n;
1491
+
1492
+ struct mrb_io *fptr = (struct mrb_io*)io_get_open_fptr(mrb, self);
1493
+
1494
+ if (!fptr->readable) {
1495
+ mrb_raise(mrb, E_IO_ERROR, "not opened for reading");
1496
+ }
1497
+ /* refill the buffer */
1498
+ mrb_str_resize(mrb, buf, 4096);
1499
+ n = read(fptr->fd, RSTRING_PTR(buf)+blen, 4096-blen);
1500
+ if (n < 0) mrb_sys_fail(mrb, "sysread failed");
1501
+ mrb_str_resize(mrb, buf, blen+n);
1502
+ }
1503
+ len = mrb_utf8len(RSTRING_PTR(buf), RSTRING_END(buf));
1504
+ }
1505
+ #endif
1506
+ return io_bufread(mrb, buf, len);
1507
+ }
1508
+
1309
1509
  void
1310
1510
  mrb_init_io(mrb_state *mrb)
1311
1511
  {
@@ -1340,6 +1540,9 @@ mrb_init_io(mrb_state *mrb)
1340
1540
  mrb_define_method(mrb, io, "closed?", mrb_io_closed, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
1341
1541
  mrb_define_method(mrb, io, "pid", mrb_io_pid, MRB_ARGS_NONE()); /* 15.2.20.5.2 */
1342
1542
  mrb_define_method(mrb, io, "fileno", mrb_io_fileno_m, MRB_ARGS_NONE());
1543
+ mrb_define_method(mrb, io, "pread", mrb_io_pread, MRB_ARGS_ANY()); /* ruby 2.5 feature */
1544
+ mrb_define_method(mrb, io, "pwrite", mrb_io_pwrite, MRB_ARGS_ANY()); /* ruby 2.5 feature */
1343
1545
 
1344
- mrb_define_class_method(mrb, io, "_bufread", io_bufread, MRB_ARGS_REQ(2));
1546
+ mrb_define_method(mrb, io, "_readchar", mrb_io_readchar, MRB_ARGS_REQ(1));
1547
+ mrb_define_class_method(mrb, io, "_bufread", mrb_io_bufread, MRB_ARGS_REQ(2));
1345
1548
  }