Project

General

Profile

Feature #11258 ยป excl_mode_v1.diff

cremno (cremno phobia), 06/16/2015 06:47 PM

View differences:

include/ruby/io.h
98 98
} rb_io_t;
99 99

  
100 100
#define HAVE_RB_IO_T 1
101

  
102 101
#define FMODE_READABLE              0x00000001
103 102
#define FMODE_WRITABLE              0x00000002
104 103
#define FMODE_READWRITE             (FMODE_READABLE|FMODE_WRITABLE)
......
109 108
#define FMODE_APPEND                0x00000040
110 109
#define FMODE_CREATE                0x00000080
111 110
/* #define FMODE_NOREVLOOKUP        0x00000100 */
111
#define FMODE_EXCL                  0x00000400
112 112
#define FMODE_TRUNC                 0x00000800
113 113
#define FMODE_TEXTMODE              0x00001000
114 114
/* #define FMODE_PREP               0x00010000 */
io.c
4879 4879
      case FMODE_READABLE:
4880 4880
	return MODE_BTMODE("r", "rb", "rt");
4881 4881
      case FMODE_WRITABLE:
4882
	if (fmode & FMODE_EXCL)
4883
	    return MODE_BTMODE("wx", "wbx", "wtx");
4882 4884
	return MODE_BTMODE("w", "wb", "wt");
4883 4885
      case FMODE_READWRITE:
4884 4886
	if (fmode & FMODE_CREATE) {
4887
	    if (fmode & FMODE_EXCL)
4888
		return MODE_BTMODE("w+x", "wb+x", "wt+x");
4885 4889
	    return MODE_BTMODE("w+", "wb+", "wt+");
4886 4890
	}
4887 4891
	return MODE_BTMODE("r+", "rb+", "rt+");
......
4928 4932
	  case '+':
4929 4933
            fmode |= FMODE_READWRITE;
4930 4934
            break;
4935
	  case 'x':
4936
	    if (!(fmode & FMODE_TRUNC))
4937
		goto error;
4938
	    fmode |= FMODE_EXCL;
4939
	    break;
4931 4940
	  default:
4932 4941
            goto error;
4933 4942
	  case ':':
......
4971 4980
    if (oflags & O_CREAT) {
4972 4981
	fmode |= FMODE_CREATE;
4973 4982
    }
4983
    if (oflags & O_EXCL) {
4984
	fmode |= FMODE_EXCL;
4985
    }
4974 4986
#ifdef O_BINARY
4975 4987
    if (oflags & O_BINARY) {
4976 4988
	fmode |= FMODE_BINMODE;
......
5006 5018
    if (fmode & FMODE_CREATE) {
5007 5019
        oflags |= O_CREAT;
5008 5020
    }
5021
    if (fmode & FMODE_EXCL) {
5022
        oflags |= O_EXCL;
5023
    }
5009 5024
#ifdef O_BINARY
5010 5025
    if (fmode & FMODE_BINMODE) {
5011 5026
        oflags |= O_BINARY;
......
5029 5044
#else
5030 5045
# define MODE_BINARY(a,b) (a)
5031 5046
#endif
5047
#define MODE_BINARY_EXCL(a,b,c,d) \
5048
 ((oflags & O_EXCL) ? MODE_BINARY(d, c) : MODE_BINARY(b, a))
5032 5049
    int accmode = oflags & (O_RDONLY|O_WRONLY|O_RDWR);
5033 5050
    if (oflags & O_APPEND) {
5034 5051
	if (accmode == O_WRONLY) {
......
5044 5061
      case O_RDONLY:
5045 5062
	return MODE_BINARY("r", "rb");
5046 5063
      case O_WRONLY:
5047
	return MODE_BINARY("w", "wb");
5064
	return MODE_BINARY_EXCL("w", "wb", "wx", "wbx");
5048 5065
      case O_RDWR:
5066
	if (oflags & O_CREAT)
5067
	    return MODE_BINARY_EXCL("w+", "wb+", "w+x", "wb+x");
5049 5068
	return MODE_BINARY("r+", "rb+");
5050 5069
    }
5051 5070
}
test/ruby/test_file.rb
437 437
      assert_file.not_exist?(path)
438 438
    end
439 439
  end
440

  
441
  def test_exclusive_mode
442
    Dir.mktmpdir('feature11258') do |tmpdir|
443
      fname = "#{tmpdir}/tmp.txt"
444
      # file must be created and not just opened
445
      assert_nothing_raised { File.new(fname, 'wx').close }
446
      assert_raise(Errno::EEXIST) { File.new(fname, 'wx') }
447
      # mode must not be read or append mode
448
      assert_raise(ArgumentError) { File.new(fname, 'rx') }
449
      assert_raise(ArgumentError) { File.new(fname, 'ax') }
450
    end
451
  end
440 452
end