diff --git a/mrbgems/mruby-io/src/io.c b/mrbgems/mruby-io/src/io.c index 560acde62..eeb3c7f86 100644 --- a/mrbgems/mruby-io/src/io.c +++ b/mrbgems/mruby-io/src/io.c @@ -139,8 +139,7 @@ io_modestr_to_flags(mrb_state *mrb, const char *mode) flags = O_WRONLY | O_CREAT | O_APPEND; break; default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); - flags = 0; /* not reached */ + goto modeerr; } while (*m) { @@ -150,17 +149,25 @@ io_modestr_to_flags(mrb_state *mrb, const char *mode) flags |= O_BINARY; #endif break; + case 'x': + if (mode[0] != 'w') goto modeerr; + flags |= O_EXCL; + break; case '+': flags = (flags & ~OPEN_ACCESS_MODE_FLAGS) | O_RDWR; break; case ':': /* XXX: PASSTHROUGH*/ default: - mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); + goto modeerr; } } return flags; + + modeerr: + mrb_raisef(mrb, E_ARGUMENT_ERROR, "illegal access mode %s", mode); + return 0; /* not reached */ } static int diff --git a/mrbgems/mruby-io/test/file.rb b/mrbgems/mruby-io/test/file.rb index 419b40e23..5746986ad 100644 --- a/mrbgems/mruby-io/test/file.rb +++ b/mrbgems/mruby-io/test/file.rb @@ -260,4 +260,30 @@ assert('File.chmod') do end end +assert('File.open with "x" mode') do + File.unlink $mrbtest_io_wfname rescue nil + assert_nothing_raised do + File.open($mrbtest_io_wfname, "wx") {} + end + assert_raise(RuntimeError) do + File.open($mrbtest_io_wfname, "wx") {} + end + + File.unlink $mrbtest_io_wfname rescue nil + assert_nothing_raised do + File.open($mrbtest_io_wfname, "w+x") {} + end + assert_raise(RuntimeError) do + File.open($mrbtest_io_wfname, "w+x") {} + end + + assert_raise(ArgumentError) do + File.open($mrbtest_io_wfname, "rx") {} + end + + assert_raise(ArgumentError) do + File.open($mrbtest_io_wfname, "ax") {} + end +end + MRubyIOTestUtil.io_test_cleanup