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
This commit is contained in:
parent
236e2993ef
commit
842b735979
4
NEWS
4
NEWS
@ -81,6 +81,10 @@ with all sufficient information, see the ChangeLog file or Redmine
|
|||||||
* Hash#filter is a new alias for Hash#select [Feature #13784]
|
* Hash#filter is a new alias for Hash#select [Feature #13784]
|
||||||
* Hash#filter! is a new alias for Hash#select! [Feature #13784]
|
* Hash#filter! is a new alias for Hash#select! [Feature #13784]
|
||||||
|
|
||||||
|
* IO
|
||||||
|
|
||||||
|
* new mode character 'x' to open files for exclusive access [Feature #11258]
|
||||||
|
|
||||||
* Kernel
|
* Kernel
|
||||||
|
|
||||||
* Kernel#then is a new alias for Kernel#yield_self [Feature #14594]
|
* Kernel#then is a new alias for Kernel#yield_self [Feature #14594]
|
||||||
|
@ -113,6 +113,7 @@ typedef struct rb_io_t {
|
|||||||
#define FMODE_APPEND 0x00000040
|
#define FMODE_APPEND 0x00000040
|
||||||
#define FMODE_CREATE 0x00000080
|
#define FMODE_CREATE 0x00000080
|
||||||
/* #define FMODE_NOREVLOOKUP 0x00000100 */
|
/* #define FMODE_NOREVLOOKUP 0x00000100 */
|
||||||
|
#define FMODE_EXCL 0x00000400
|
||||||
#define FMODE_TRUNC 0x00000800
|
#define FMODE_TRUNC 0x00000800
|
||||||
#define FMODE_TEXTMODE 0x00001000
|
#define FMODE_TEXTMODE 0x00001000
|
||||||
/* #define FMODE_PREP 0x00010000 */
|
/* #define FMODE_PREP 0x00010000 */
|
||||||
|
32
io.c
32
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) : \
|
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
|
||||||
(fmode & FMODE_TEXTMODE) ? (c) : (a))
|
(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
|
static VALUE
|
||||||
do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
|
do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
|
||||||
{
|
{
|
||||||
@ -5360,10 +5365,10 @@ rb_io_fmode_modestr(int fmode)
|
|||||||
case FMODE_READABLE:
|
case FMODE_READABLE:
|
||||||
return MODE_BTMODE("r", "rb", "rt");
|
return MODE_BTMODE("r", "rb", "rt");
|
||||||
case FMODE_WRITABLE:
|
case FMODE_WRITABLE:
|
||||||
return MODE_BTMODE("w", "wb", "wt");
|
return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
|
||||||
case FMODE_READWRITE:
|
case FMODE_READWRITE:
|
||||||
if (fmode & FMODE_CREATE) {
|
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+");
|
return MODE_BTMODE("r+", "rb+", "rt+");
|
||||||
}
|
}
|
||||||
@ -5412,6 +5417,11 @@ rb_io_modestr_fmode(const char *modestr)
|
|||||||
case '+':
|
case '+':
|
||||||
fmode |= FMODE_READWRITE;
|
fmode |= FMODE_READWRITE;
|
||||||
break;
|
break;
|
||||||
|
case 'x':
|
||||||
|
if (modestr[0] != 'w')
|
||||||
|
goto error;
|
||||||
|
fmode |= FMODE_EXCL;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
goto error;
|
goto error;
|
||||||
case ':':
|
case ':':
|
||||||
@ -5455,6 +5465,9 @@ rb_io_oflags_fmode(int oflags)
|
|||||||
if (oflags & O_CREAT) {
|
if (oflags & O_CREAT) {
|
||||||
fmode |= FMODE_CREATE;
|
fmode |= FMODE_CREATE;
|
||||||
}
|
}
|
||||||
|
if (oflags & O_EXCL) {
|
||||||
|
fmode |= FMODE_EXCL;
|
||||||
|
}
|
||||||
#ifdef O_BINARY
|
#ifdef O_BINARY
|
||||||
if (oflags & O_BINARY) {
|
if (oflags & O_BINARY) {
|
||||||
fmode |= FMODE_BINMODE;
|
fmode |= FMODE_BINMODE;
|
||||||
@ -5490,6 +5503,9 @@ rb_io_fmode_oflags(int fmode)
|
|||||||
if (fmode & FMODE_CREATE) {
|
if (fmode & FMODE_CREATE) {
|
||||||
oflags |= O_CREAT;
|
oflags |= O_CREAT;
|
||||||
}
|
}
|
||||||
|
if (fmode & FMODE_EXCL) {
|
||||||
|
oflags |= O_EXCL;
|
||||||
|
}
|
||||||
#ifdef O_BINARY
|
#ifdef O_BINARY
|
||||||
if (fmode & FMODE_BINMODE) {
|
if (fmode & FMODE_BINMODE) {
|
||||||
oflags |= O_BINARY;
|
oflags |= O_BINARY;
|
||||||
@ -5513,7 +5529,11 @@ rb_io_oflags_modestr(int oflags)
|
|||||||
#else
|
#else
|
||||||
# define MODE_BINARY(a,b) (a)
|
# define MODE_BINARY(a,b) (a)
|
||||||
#endif
|
#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 (oflags & O_APPEND) {
|
||||||
if (accmode == O_WRONLY) {
|
if (accmode == O_WRONLY) {
|
||||||
return MODE_BINARY("a", "ab");
|
return MODE_BINARY("a", "ab");
|
||||||
@ -5522,7 +5542,7 @@ rb_io_oflags_modestr(int oflags)
|
|||||||
return MODE_BINARY("a+", "ab+");
|
return MODE_BINARY("a+", "ab+");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
|
switch (accmode) {
|
||||||
default:
|
default:
|
||||||
rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
|
rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
|
||||||
case O_RDONLY:
|
case O_RDONLY:
|
||||||
@ -8052,6 +8072,10 @@ rb_io_make_open_file(VALUE obj)
|
|||||||
*
|
*
|
||||||
* "t" Text file mode
|
* "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
|
* 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
|
* changed to be writable. Similarly, the open mode cannot be changed from
|
||||||
* write only to readable.
|
* write only to readable.
|
||||||
|
@ -3555,6 +3555,14 @@ __END__
|
|||||||
end
|
end
|
||||||
end if File::BINARY != 0
|
end if File::BINARY != 0
|
||||||
|
|
||||||
|
def test_exclusive_mode
|
||||||
|
make_tempfile do |t|
|
||||||
|
assert_raise(Errno::EEXIST){ open(t.path, 'wx'){} }
|
||||||
|
assert_raise(ArgumentError){ open(t.path, 'rx'){} }
|
||||||
|
assert_raise(ArgumentError){ open(t.path, 'ax'){} }
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_race_gets_and_close
|
def test_race_gets_and_close
|
||||||
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
|
assert_separately([], "#{<<-"begin;"}\n#{<<-"end;"}")
|
||||||
bug13076 = '[ruby-core:78845] [Bug #13076]'
|
bug13076 = '[ruby-core:78845] [Bug #13076]'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user