Project

General

Profile

Feature #11258 ยป excl_mode_v2.diff

cremno (cremno phobia), 07/29/2015 06:35 PM

View differences:

NEWS
50 50
    this parameter is bitwise-ORed to oflags generated by normal mode argument.
51 51
    [Feature #11253]
52 52

  
53
  * new mode character 'x' to open files for exclusive access [Feature #11258]
54

  
53 55
* Thread
54 56
  * Thread#name, Thread#name= are added to handle thread names [Feature #11251]
55 57

  
include/ruby/io.h
109 109
#define FMODE_APPEND                0x00000040
110 110
#define FMODE_CREATE                0x00000080
111 111
/* #define FMODE_NOREVLOOKUP        0x00000100 */
112
#define FMODE_EXCL                  0x00000400
112 113
#define FMODE_TRUNC                 0x00000800
113 114
#define FMODE_TEXTMODE              0x00001000
114 115
/* #define FMODE_PREP               0x00010000 */
io.c
1360 1360

  
1361 1361
# define MODE_BTMODE(a,b,c) ((fmode & FMODE_BINMODE) ? (b) : \
1362 1362
                             (fmode & FMODE_TEXTMODE) ? (c) : (a))
1363

  
1364
#define MODE_BTXMODE(a, b, c, d ,e, f) ((fmode & FMODE_EXCL) ? \
1365
                                        MODE_BTMODE(d, e, f) : \
1366
                                        MODE_BTMODE(a, b, c))
1367

  
1363 1368
static VALUE
1364 1369
do_writeconv(VALUE str, rb_io_t *fptr, int *converted)
1365 1370
{
......
4872 4877
      case FMODE_READABLE:
4873 4878
	return MODE_BTMODE("r", "rb", "rt");
4874 4879
      case FMODE_WRITABLE:
4875
	return MODE_BTMODE("w", "wb", "wt");
4880
	return MODE_BTXMODE("w", "wb", "wt", "wx", "wbx", "wtx");
4876 4881
      case FMODE_READWRITE:
4877 4882
	if (fmode & FMODE_CREATE) {
4878
	    return MODE_BTMODE("w+", "wb+", "wt+");
4883
	    return MODE_BTXMODE("w+", "wb+", "wt+", "w+x", "wb+x", "wt+x");
4879 4884
	}
4880 4885
	return MODE_BTMODE("r+", "rb+", "rt+");
4881 4886
    }
......
4921 4926
	  case '+':
4922 4927
            fmode |= FMODE_READWRITE;
4923 4928
            break;
4929
	  case 'x':
4930
	    if (modestr[0] != 'w')
4931
		goto error;
4932
	    fmode |= FMODE_EXCL;
4933
	    break;
4924 4934
	  default:
4925 4935
            goto error;
4926 4936
	  case ':':
......
4964 4974
    if (oflags & O_CREAT) {
4965 4975
	fmode |= FMODE_CREATE;
4966 4976
    }
4977
    if (oflags & O_EXCL) {
4978
	fmode |= FMODE_EXCL;
4979
    }
4967 4980
#ifdef O_BINARY
4968 4981
    if (oflags & O_BINARY) {
4969 4982
	fmode |= FMODE_BINMODE;
......
4999 5012
    if (fmode & FMODE_CREATE) {
5000 5013
        oflags |= O_CREAT;
5001 5014
    }
5015
    if (fmode & FMODE_EXCL) {
5016
        oflags |= O_EXCL;
5017
    }
5002 5018
#ifdef O_BINARY
5003 5019
    if (fmode & FMODE_BINMODE) {
5004 5020
        oflags |= O_BINARY;
......
5022 5038
#else
5023 5039
# define MODE_BINARY(a,b) (a)
5024 5040
#endif
5025
    int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5041
    int accmode;
5042
    if (oflags & O_EXCL) {
5043
	rb_raise(rb_eArgError, "exclusive access mode is not supported");
5044
    }
5045
    accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5026 5046
    if (oflags & O_APPEND) {
5027 5047
	if (accmode == O_WRONLY) {
5028 5048
	    return MODE_BINARY("a", "ab");
......
5031 5051
	    return MODE_BINARY("a+", "ab+");
5032 5052
	}
5033 5053
    }
5034
    switch (oflags & (O_RDONLY|O_WRONLY|O_RDWR)) {
5054
    switch (accmode) {
5035 5055
      default:
5036 5056
	rb_raise(rb_eArgError, "invalid access oflags 0x%x", oflags);
5037 5057
      case O_RDONLY:
......
7496 7516
 *
7497 7517
 *  	"t"  Text file mode
7498 7518
 *
7519
 *  The exclusive access mode ("x") can be used together with "w" to ensure
7520
 *  the file is created. <code>Errno::EEXIST</code> is raised when it already
7521
 *  exists. It may not be supported with all kinds of streams (e.g. pipes).
7522
 *
7499 7523
 *  When the open mode of original IO is read only, the mode cannot be
7500 7524
 *  changed to be writable.  Similarly, the open mode cannot be changed from
7501 7525
 *  write only to readable.
test/ruby/test_io.rb
3251 3251
      end
3252 3252
    end
3253 3253
  end if File::BINARY != 0
3254

  
3255
  def test_exclusive_mode
3256
    make_tempfile do |t|
3257
      assert_raise(Errno::EEXIST){ open(t.path, 'wx'){} }
3258
      assert_raise(ArgumentError){ open(t.path, 'rx'){} }
3259
      assert_raise(ArgumentError){ open(t.path, 'ax'){} }
3260
    end
3261
  end
3254 3262
end