民斗です。

O_CREAT つき open() ですが、全然盛り上がってなくて、このまま忘れ
去られそうなので…
# 私は忘れかけてた…(^^;

[Subject: [ruby-dev:4196] Re: open with O_CREAT|O_EXCL]
[Date: Mon, 18 Jan 1999 11:08:09 +0900  From:Yukihiro Matsumoto]

> 3. TclみたいにopenがO_CREATなどもモードとして受け付ける
> 
> ってのもありえますよね.

この方法で実装してみました。ruby-1.3.1-990205 に対するパッチです。
Ruby 本体に手を入れるのは初めてなんで、変なことしてるかも知れません。

# 他の OS は良く知らないので、Solaris でしかコンパイルできないかも…。

問題なければ、取り込んで頂けるとありがたいです。

--
民斗 <tommy / valley.ne.jp>


--- io.c.orig	Thu Jan 28 16:55:30 1999
+++ io.c	Sun Feb  7 01:29:31 1999
@@ -1058,6 +1058,26 @@
     return flags;
 }
 
+int
+rb_open(fname, flag, mode)
+    char *fname;
+    int flag;
+    mode_t mode;
+{
+    int fd;
+    fd = open(fname, flag, mode);
+    if (fd < 0) {
+	if (errno == EMFILE || errno == ENFILE) {
+	    rb_gc();
+	    fd = open(fname, flag, mode);
+	}
+	if (fd < 0) {
+	    rb_sys_fail(fname);
+	}
+    }
+    return fd;
+}
+
 FILE *
 rb_fopen(fname, mode)
     char *fname;
--- file.c.orig	Tue Jan 26 19:08:12 1999
+++ file.c	Sun Feb  7 02:21:39 1999
@@ -53,6 +53,7 @@
 
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <fcntl.h>
 
 #ifdef USE_CWGUSI
  #include "macruby_missing.h"
@@ -82,24 +83,55 @@
     return (VALUE)port;
 }
 
+VALUE
+rb_file_sysopen(fname, flag, mode)
+    char *fname;
+    int flag, mode;
+{
+    OpenFile *fptr;
+    int fd;
+    char *m;
+    NEWOBJ(port, struct RFile);
+    OBJSETUP(port, rb_cFile, T_FILE);
+    MakeOpenFile(port, fptr);
+
+    fd = rb_open(fname, flag, mode);
+    switch (flag & (O_RDONLY|O_WRONLY|O_RDWR)) {
+    case O_WRONLY:	m = "w"; break;
+    case O_RDWR:	m = "r+"; break;
+    case O_RDONLY:	
+    default:		m = "r";
+    }
+    fptr->mode = rb_io_mode_flags(m);
+    fptr->f = rb_fdopen(fd, m);
+    fptr->path = strdup(fname);
+    rb_obj_call_init((VALUE)port);
+
+    return (VALUE)port;
+}
+
 static VALUE
 rb_file_s_open(argc, argv, klass)
     int argc;
     VALUE *argv;
     VALUE klass;
 {
-    VALUE fname, vmode, file;
+    VALUE fname, vmode, file, perm;
     char *mode;
 
-    rb_scan_args(argc, argv, "11", &fname, &vmode);
+    rb_scan_args(argc, argv, "12", &fname, &vmode, &perm);
     Check_SafeStr(fname);
-    if (!NIL_P(vmode)) {
-	mode = STR2CSTR(vmode);
-    }
-    else {
-	mode = "r";
+    if (FIXNUM_P(vmode)) {
+	file = rb_file_sysopen(RSTRING(fname)->ptr, FIX2INT(vmode), NIL_P(perm)? 0: FIX2INT(perm));
+    } else {
+	if (!NIL_P(vmode)) {
+	    mode = STR2CSTR(vmode);
+	}
+	else {
+	    mode = "r";
+	}
+	file = rb_file_open(RSTRING(fname)->ptr, mode);
     }
-    file = rb_file_open(RSTRING(fname)->ptr, mode);
 
     RBASIC(file)->klass = klass;
     rb_obj_call_init(file);
@@ -1692,11 +1724,29 @@
     rb_define_const(rb_cFile, "LOCK_EX", INT2FIX(LOCK_EX));
     rb_define_const(rb_cFile, "LOCK_UN", INT2FIX(LOCK_UN));
     rb_define_const(rb_cFile, "LOCK_NB", INT2FIX(LOCK_NB));
+    rb_define_const(rb_cFile, "O_RDONLY", INT2FIX(O_RDONLY));
+    rb_define_const(rb_cFile, "O_WRONLY", INT2FIX(O_WRONLY));
+    rb_define_const(rb_cFile, "O_RDWR", INT2FIX(O_RDWR));
+    rb_define_const(rb_cFile, "O_APPEND", INT2FIX(O_APPEND));
+    rb_define_const(rb_cFile, "O_CREAT", INT2FIX(O_CREAT));
+    rb_define_const(rb_cFile, "O_EXCL", INT2FIX(O_EXCL));
+    rb_define_const(rb_cFile, "O_NONBLOCK", INT2FIX(O_NONBLOCK));
+    rb_define_const(rb_cFile, "O_NDELAY", INT2FIX(O_NDELAY));
+    rb_define_const(rb_cFile, "O_TRUNC", INT2FIX(O_TRUNC));
 
     rb_define_const(rb_mConst, "LOCK_SH", INT2FIX(LOCK_SH));
     rb_define_const(rb_mConst, "LOCK_EX", INT2FIX(LOCK_EX));
     rb_define_const(rb_mConst, "LOCK_UN", INT2FIX(LOCK_UN));
     rb_define_const(rb_mConst, "LOCK_NB", INT2FIX(LOCK_NB));
+    rb_define_const(rb_mConst, "O_RDONLY", INT2FIX(O_RDONLY));
+    rb_define_const(rb_mConst, "O_WRONLY", INT2FIX(O_WRONLY));
+    rb_define_const(rb_mConst, "O_RDWR", INT2FIX(O_RDWR));
+    rb_define_const(rb_mConst, "O_APPEND", INT2FIX(O_APPEND));
+    rb_define_const(rb_mConst, "O_CREAT", INT2FIX(O_CREAT));
+    rb_define_const(rb_mConst, "O_EXCL", INT2FIX(O_EXCL));
+    rb_define_const(rb_mConst, "O_NONBLOCK", INT2FIX(O_NONBLOCK));
+    rb_define_const(rb_mConst, "O_NDELAY", INT2FIX(O_NDELAY));
+    rb_define_const(rb_mConst, "O_TRUNC", INT2FIX(O_TRUNC));
 
     rb_define_method(rb_cFile, "path",  rb_file_path, 0);