summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authornagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-23 12:03:58 +0000
committernagachika <nagachika@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2018-03-23 12:03:58 +0000
commitf40c637794ebd9f20c56f51e3aa5c10130421754 (patch)
treeee54fdb7e73aed8280a5d32064c4c94b17d8ca85
parent29fa5cc869d6435a84e3f5467e89fbb8f4b5462c (diff)
merge revision(s) 62607: [Backport #14557]
file.c: realpath on special symlink * file.c (realpath_rec): fallback to symlink path when it is accessible but the link target is not actual entry on file systems. [ruby-dev:50487] [Bug #14557] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_4@62903 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--file.c16
-rw-r--r--test/ruby/test_file.rb8
-rw-r--r--version.h6
3 files changed, 22 insertions, 8 deletions
diff --git a/file.c b/file.c
index 0e67654da2..f321b57f08 100644
--- a/file.c
+++ b/file.c
@@ -3778,7 +3778,7 @@ enum rb_realpath_mode {
};
static int
-realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
+realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE fallback,
VALUE loopcheck, enum rb_realpath_mode mode, int last)
{
const char *pend = unresolved + strlen(unresolved);
@@ -3841,6 +3841,12 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
#endif
if (ret == -1) {
int e = errno;
+ if (e == ENOENT && !NIL_P(fallback)) {
+ if (rb_stat(fallback, &sbuf) == 0) {
+ rb_str_replace(*resolvedp, fallback);
+ return 0;
+ }
+ }
if (mode == RB_REALPATH_CHECK) return -1;
if (e == ENOENT) {
if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
@@ -3872,7 +3878,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
*resolvedp = link;
*prefixlenp = link_prefixlen;
}
- if (realpath_rec(prefixlenp, resolvedp, link_names,
+ if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
loopcheck, mode, !*unresolved_firstsep))
return -1;
RB_GC_GUARD(link_orig);
@@ -3960,14 +3966,14 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode
loopcheck = rb_hash_new();
if (curdir_names) {
- if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0))
+ if (realpath_rec(&prefixlen, &resolved, curdir_names, Qnil, loopcheck, mode, 0))
return Qnil;
}
if (basedir_names) {
- if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0))
+ if (realpath_rec(&prefixlen, &resolved, basedir_names, Qnil, loopcheck, mode, 0))
return Qnil;
}
- if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1))
+ if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1))
return Qnil;
if (origenc != enc && rb_enc_str_asciionly_p(resolved))
diff --git a/test/ruby/test_file.rb b/test/ruby/test_file.rb
index 58a4240391..d0d6a0ebe2 100644
--- a/test/ruby/test_file.rb
+++ b/test/ruby/test_file.rb
@@ -284,6 +284,14 @@ class TestFile < Test::Unit::TestCase
}
end
+ def test_realpath_special_symlink
+ IO.pipe do |r, w|
+ if File.pipe?(path = "/dev/fd/#{r.fileno}")
+ assert_file.identical?(File.realpath(path), path)
+ end
+ end
+ end
+
def test_realdirpath
Dir.mktmpdir('rubytest-realdirpath') {|tmpdir|
realdir = File.realpath(tmpdir)
diff --git a/version.h b/version.h
index 82cdb46aa8..1455401a54 100644
--- a/version.h
+++ b/version.h
@@ -1,10 +1,10 @@
#define RUBY_VERSION "2.4.4"
-#define RUBY_RELEASE_DATE "2018-03-22"
-#define RUBY_PATCHLEVEL 282
+#define RUBY_RELEASE_DATE "2018-03-23"
+#define RUBY_PATCHLEVEL 283
#define RUBY_RELEASE_YEAR 2018
#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 22
+#define RUBY_RELEASE_DAY 23
#include "ruby/version.h"