[前][次][番号順一覧][スレッド一覧]

ruby-changes:50475

From: nobu <ko1@a...>
Date: Wed, 28 Feb 2018 14:44:03 +0900 (JST)
Subject: [ruby-changes:50475] nobu:r62607 (trunk): file.c: realpath on special symlink

nobu	2018-02-28 14:43:53 +0900 (Wed, 28 Feb 2018)

  New Revision: 62607

  https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=62607

  Log:
    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]

  Modified files:
    trunk/file.c
    trunk/test/ruby/test_file.rb
Index: test/ruby/test_file.rb
===================================================================
--- test/ruby/test_file.rb	(revision 62606)
+++ test/ruby/test_file.rb	(revision 62607)
@@ -303,6 +303,14 @@ class TestFile < Test::Unit::TestCase https://github.com/ruby/ruby/blob/trunk/test/ruby/test_file.rb#L303
     }
   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)
Index: file.c
===================================================================
--- file.c	(revision 62606)
+++ file.c	(revision 62607)
@@ -3943,7 +3943,7 @@ enum rb_realpath_mode { https://github.com/ruby/ruby/blob/trunk/file.c#L3943
 };
 
 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);
@@ -4001,6 +4001,12 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L4001
                 ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf);
                 if (ret == -1) {
 		    int e = errno;
+		    if (e == ENOENT && !NIL_P(fallback)) {
+			if (stat_without_gvl(RSTRING_PTR(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)
@@ -4032,7 +4038,7 @@ realpath_rec(long *prefixlenp, VALUE *re https://github.com/ruby/ruby/blob/trunk/file.c#L4038
 			*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);
@@ -4121,14 +4127,14 @@ rb_check_realpath_internal(VALUE basedir https://github.com/ruby/ruby/blob/trunk/file.c#L4127
 
     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 != rb_enc_get(resolved)) {

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]