ruby-changes:47588
From: sorah <ko1@a...>
Date: Thu, 31 Aug 2017 20:14:42 +0900 (JST)
Subject: [ruby-changes:47588] sorah:r59704 (trunk): File#path: Raise IOError when a file is O_TMPFILE
sorah 2017-08-31 20:14:36 +0900 (Thu, 31 Aug 2017) New Revision: 59704 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=59704 Log: File#path: Raise IOError when a file is O_TMPFILE File#path for a file opened with O_TMPFILE has no meaning. A filepath returned by this method isn't guarranteed about its accuracy, but files opened with O_TMPFILE are known its recorded path has no meaning. So let them not to return any pathname. After a discussion in ruby-core, just returning Qnil makes guessing the root cause difficult. Instead, this patch makes the method to raise an error. Other consideration is calling fnctl(2) on rb_file_path, but it adds a overhead, and it's difficult to determine O_TMPFILE status after fd has been closed. [Feature #13568] * io.c(rb_file_open_generic): Set Qnil to fptr->pathv when opening a file using O_TMPFILE * file.c(rb_file_path): Raise IOError when fptr->pathv is Qnil * file.c(rb_file_path): [DOC] Update for the new behavior Modified files: trunk/file.c trunk/io.c trunk/test/ruby/test_file.rb Index: test/ruby/test_file.rb =================================================================== --- test/ruby/test_file.rb (revision 59703) +++ test/ruby/test_file.rb (revision 59704) @@ -468,4 +468,16 @@ class TestFile < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_file.rb#L468 assert_file.not_exist?(path) end end + + def test_open_tempfile_path + Dir.mktmpdir(__method__.to_s) do |tmpdir| + File.open(tmpdir, File::RDWR | File::TMPFILE) do |io| + io.write "foo" + io.flush + assert_equal 3, io.size + assert_raise(IOError) { io.path } + end + end + end if File::Constants.const_defined?(:TMPFILE) + end Index: file.c =================================================================== --- file.c (revision 59703) +++ file.c (revision 59704) @@ -379,7 +379,10 @@ apply2files(void (*func)(const char *, V https://github.com/ruby/ruby/blob/trunk/file.c#L379 * not normalize the name. * * The pathname may not point the file corresponding to <i>file</i>. - * e.g. file has been moved, deleted, or created with <code>File::TMPFILE</code> option. + * For instance, pathname becomes inaccurate when file has been moved or deleted. + * + * This method raises <code>IOError</code> for a <i>file</i> created using + * <code>File::Constants::TMPFILE</code> because they don't have a pathname. * * File.new("testfile").path #=> "testfile" * File.new("/tmp/../tmp/xxx", "w").path #=> "/tmp/../tmp/xxx" @@ -393,7 +396,11 @@ rb_file_path(VALUE obj) https://github.com/ruby/ruby/blob/trunk/file.c#L396 fptr = RFILE(rb_io_taint_check(obj))->fptr; rb_io_check_initialized(fptr); - if (NIL_P(fptr->pathv)) return Qnil; + + if (NIL_P(fptr->pathv)) { + rb_raise(rb_eIOError, "File is unnamed (TMPFILE?)"); + } + return rb_obj_taint(rb_str_dup(fptr->pathv)); } Index: io.c =================================================================== --- io.c (revision 59703) +++ io.c (revision 59704) @@ -5833,6 +5833,7 @@ static VALUE https://github.com/ruby/ruby/blob/trunk/io.c#L5833 rb_file_open_generic(VALUE io, VALUE filename, int oflags, int fmode, const convconfig_t *convconfig, mode_t perm) { + VALUE pathv; rb_io_t *fptr; convconfig_t cc; if (!convconfig) { @@ -5848,8 +5849,15 @@ rb_file_open_generic(VALUE io, VALUE fil https://github.com/ruby/ruby/blob/trunk/io.c#L5849 MakeOpenFile(io, fptr); fptr->mode = fmode; fptr->encs = *convconfig; - fptr->pathv = rb_str_new_frozen(filename); - fptr->fd = rb_sysopen(fptr->pathv, oflags, perm); + pathv = rb_str_new_frozen(filename); +#ifdef O_TMPFILE + if (!(oflags & O_TMPFILE)) { + fptr->pathv = pathv; + } +#else + fptr->pathv = pathv; +#endif + fptr->fd = rb_sysopen(pathv, oflags, perm); io_check_tty(fptr); if (fmode & FMODE_SETENC_BY_BOM) io_set_encoding_by_bom(io); -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/