script_core 0.2.5 → 0.2.6

Sign up to get free protection for your applications and to get access to all the features.
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
  }