Project

General

Profile

Actions

Feature #11253

closed

rb_io_modestr_oflags for Ruby API

Added by naruse (Yui NARUSE) almost 9 years ago. Updated over 8 years ago.

Status:
Closed
Target version:
-
[ruby-core:69539]

Description

If you have a wrapper of IO.open, you may handle mode.
For example on Windows, you may want to add 'b' / OBINARY to given mode.

But some modes has only integer form like O_CLOEXEC, O_EXCL.
If so you need to convert from modestr to oflags

Therefore how about adding a Ruby API version of rb_io_modestr_oflags

Updated by akr (Akira Tanaka) almost 9 years ago

This issue is discussed at DevelopersMeeting20150612Japan.

We found "flags" keyword argument would be better for the intent.

open(filename, "w", flags: File::EXCL)
open(filename, "w", flags: File::SHARE_DELETE)

The argument will be bitwise-ORed to oflag for open system call.

If a wrapper of open method want to add flags, it can add flags using integer.

Updated by naruse (Yui NARUSE) over 8 years ago

a patch is following:

diff --git a/ChangeLog b/ChangeLog
index 23f82a7..83ae426 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+Sat Jul 25 22:33:40 2015  NARUSE, Yui  <naruse@ruby-lang.org>
+
+	* io.c (rb_io_extract_modeenc): add option parameter `flags'
+	  to append extra oflags to normal mode.
+	  [Feature #11253] [ruby-core:69539]
+
 Sat Jul 25 21:03:45 2015  Nobuyoshi Nakada  <nobu@ruby-lang.org>
 
 	* random.c (fill_random_bytes_syscall): get rid of blocking when
diff --git a/NEWS b/NEWS
index 62ddaec..3295c94 100644
--- a/NEWS
+++ b/NEWS
@@ -46,6 +46,10 @@ with all sufficient information, see the ChangeLog file.
     this flag means to permit deleting opened file on Windows, but currently
     this affect only files opened as binary.  [Feature #11218]
 
+  * new option parameter `flags' is added.
+    this parameter is bitwise-ORed to oflags generated by normal mode argument.
+    [Feature #11253]
+
 * Thread
   * Thread#name, Thread#name= are added to handle thread names [Feature #11251]
 
diff --git a/io.c b/io.c
index 24fe983..104f521 100644
--- a/io.c
+++ b/io.c
@@ -173,7 +173,7 @@ static VALUE argf;
 
 #define id_exception idException
 static ID id_write, id_read, id_getc, id_flush, id_readpartial, id_set_encoding;
-static VALUE sym_mode, sym_perm, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
+static VALUE sym_mode, sym_perm, sym_flags, sym_extenc, sym_intenc, sym_encoding, sym_open_args;
 static VALUE sym_textmode, sym_binmode, sym_autoclose;
 static VALUE sym_SET, sym_CUR, sym_END;
 static VALUE sym_wait_readable, sym_wait_writable;
@@ -5340,19 +5340,6 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
     }
     else {
 	VALUE v;
-	extract_binmode(opthash, &fmode);
-	if (fmode & FMODE_BINMODE) {
-#ifdef O_BINARY
-            oflags |= O_BINARY;
-#endif
-	    if (!has_enc)
-		rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
-	}
-#if DEFAULT_TEXTMODE
-	else if (NIL_P(vmode)) {
-	    fmode |= DEFAULT_TEXTMODE;
-	}
-#endif
 	if (!has_vmode) {
 	    v = rb_hash_aref(opthash, sym_mode);
 	    if (!NIL_P(v)) {
@@ -5364,6 +5351,26 @@ rb_io_extract_modeenc(VALUE *vmode_p, VALUE *vperm_p, VALUE opthash,
 		goto vmode_handle;
 	    }
 	}
+	v = rb_hash_aref(opthash, sym_flags);
+	if (!NIL_P(v)) {
+	    v = rb_to_int(v);
+	    oflags |= NUM2INT(v);
+	    vmode = INT2NUM(oflags);
+	    fmode = rb_io_oflags_fmode(oflags);
+	}
+	extract_binmode(opthash, &fmode);
+	if (fmode & FMODE_BINMODE) {
+#ifdef O_BINARY
+            oflags |= O_BINARY;
+#endif
+	    if (!has_enc)
+		rb_io_ext_int_to_encs(rb_ascii8bit_encoding(), NULL, &enc, &enc2, fmode);
+	}
+#if DEFAULT_TEXTMODE
+	else if (NIL_P(vmode)) {
+	    fmode |= DEFAULT_TEXTMODE;
+	}
+#endif
 	v = rb_hash_aref(opthash, sym_perm);
 	if (!NIL_P(v)) {
 	    if (vperm_p) {
@@ -7522,6 +7529,10 @@ rb_io_make_open_file(VALUE obj)
  *  :mode ::
  *    Same as +mode+ parameter
  *
+ *  :flags ::
+ *    Specifies file open flags as integer.
+ *    If +mode+ parameter is given, this parameter will be bitwise-ORed.
+ *
  *  :\external_encoding ::
  *    External encoding for the IO.  "-" is a synonym for the default external
  *    encoding.
@@ -12493,6 +12504,7 @@ Init_IO(void)
 
     sym_mode = ID2SYM(rb_intern("mode"));
     sym_perm = ID2SYM(rb_intern("perm"));
+    sym_flags = ID2SYM(rb_intern("flags"));
     sym_extenc = ID2SYM(rb_intern("external_encoding"));
     sym_intenc = ID2SYM(rb_intern("internal_encoding"));
     sym_encoding = ID2SYM(rb_intern("encoding"));
diff --git a/test/ruby/test_io.rb b/test/ruby/test_io.rb
index 51b67f3..7adeae4 100644
--- a/test/ruby/test_io.rb
+++ b/test/ruby/test_io.rb
@@ -3230,4 +3230,25 @@ End
     }
   end if /mswin|mingw|bccwin/ !~ RUBY_PLATFORM
 
+  def test_open_flag
+    make_tempfile do |t|
+      assert_raise(Errno::EEXIST){ open(t, File::WRONLY|File::CREAT, flags: File::EXCL){} }
+      assert_raise(Errno::EEXIST){ open(t, 'w', flags: File::EXCL){} }
+      assert_raise(Errno::EEXIST){ open(t, mode: 'w', flags: File::EXCL){} }
+    end
+  end
+
+  def test_open_flag_binar
+    make_tempfile do |t|
+      open(t, File::RDONLY, flags: File::BINARY) do |f|
+        assert_equal true, f.binmode
+      end
+      open(t, 'r', flags: File::BINARY) do |f|
+        assert_equal true, f.binmode
+      end
+      open(t, mode: 'r', flags: File::BINARY) do |f|
+        assert_equal true, f.binmode
+      end
+    end
+  end if File::BINARY != 0
 end

Updated by matz (Yukihiro Matsumoto) over 8 years ago

It looks good to me.

Matz.

Actions #4

Updated by naruse (Yui NARUSE) over 8 years ago

  • Status changed from Assigned to Closed

Applied in changeset r51416.


  • io.c (rb_io_extract_modeenc): add option parameter `flags'
    to append extra oflags to normal mode.
    [Feature #11253] [ruby-core:69539]
Actions

Also available in: Atom PDF

Like0
Like0Like0Like0Like0