summaryrefslogtreecommitdiff
path: root/io.c
diff options
context:
space:
mode:
authorkazu <kazu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-09 08:49:09 (GMT)
committerkazu <kazu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-08-09 08:49:09 (GMT)
commit842b735979f41169900af88a50e24d0d5e698a44 (patch)
tree5833eef0f25afb31e6be33e98e660f42f42ff600 /io.c
parent236e2993ef7667912f8dfb1b1de2d1d60a82127d (diff)
add 'x' mode character for O_EXCL
[Feature #11258] Patch by cremno (cremno phobia) git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64245 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
Diffstat (limited to 'io.c')
-rw-r--r--io.c32
1 files changed, 28 insertions, 4 deletions
diff --git a/io.c b/io.c
index 9c8d5de..944beb7 100644
--- a/io.c
+++ b/io.c
@@ -1369,6 +1369,11 @@ io_binwrite(VALUE str, const char *ptr, long len, rb_io_t *fptr, int nosync)
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
(fmode & FMODE_TEXTMODE) ? (c) : (a))
+
+#define MODE_BTXMODE(a, b, c, d, e, f) ((fmode & FMODE_EXCL) ? \
+ MODE_BTMODE(d, e, f) : \
+ MODE_BTMODE(a, b, c))
+
static VALUE
do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
{
@@ -5360,10 +5365,10 @@ rb_io_fmode_modestr(int fmode)
case FMODE_READABLE:
return MODE_BTMODE("r", "rb", "rt");
case FMODE_WRITABLE:
- return MODE_BTMODE("w", "wb", "wt");
+ return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
case FMODE_READWRITE:
if (fmode & FMODE_CREATE) {
- return MODE_BTMODE("w+", "wb+", "wt+");
+ return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
}
return MODE_BTMODE("r+", "rb+", "rt+");
}
@@ -5412,6 +5417,11 @@ rb_io_modestr_fmode(const char *modestr)
case '+':
fmode |= FMODE_READWRITE;
break;
+ case 'x':
+ if (modestr[0] != 'w')
+ goto error;
+ fmode |= FMODE_EXCL;
+ break;
default:
goto error;
case ':':
@@ -5455,6 +5465,9 @@ rb_io_oflags_fmode(int oflags)
if (oflags & O_CREAT) {
fmode |= FMODE_CREATE;
}
+ if (oflags & O_EXCL) {
+ fmode |= FMODE_EXCL;
+ }
#ifdef O_BINARY
if (oflags & O_BINARY) {
fmode |= FMODE_BINMODE;
@@ -5490,6 +5503,9 @@ rb_io_fmode_oflags(int fmode)
if (fmode & FMODE_CREATE) {
oflags |= O_CREAT;
}
+ if (fmode & FMODE_EXCL) {
+ oflags |= O_EXCL;
+ }
#ifdef O_BINARY
if (fmode & FMODE_BINMODE) {
oflags |= O_BINARY;
@@ -5513,7 +5529,11 @@ rb_io_oflags_modestr(int oflags)
#else
# define MODE_BINARY(a,b) (a)
#endif
- int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
+ int accmode;
+ if (oflags & O_EXCL) {
+ rb_raise(rb_eArgError, "exclusive access mode is not supported");
+ }
+ accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
if (oflags & O_APPEND) {
if (accmode == O_WRONLY) {
return MODE_BINARY("a", "ab");
@@ -5522,7 +5542,7 @@ rb_io_oflags_modestr(int oflags)
return MODE_BINARY("a+", "ab+");
}
}
- switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
+ switch (accmode) {
default:
rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
case O_RDONLY:
@@ -8052,6 +8072,10 @@ rb_io_make_open_file(VALUE obj)
*
* "t" Text file mode
*
+ * The exclusive access mode ("x") can be used together with "w" to ensure
+ * the file is created. <code>Errno::EEXIST</code> is raised when it already
+ * exists. It may not be supported with all kinds of streams (e.g. pipes).
+ *
* When the open mode of original IO is read only, the mode cannot be
* changed to be writable. Similarly, the open mode cannot be changed from
* write only to readable.