зеркало из https://github.com/github/ruby.git
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/trunk@62607 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
Родитель
1daa624d56
Коммит
5a53cbe314
16
file.c
16
file.c
|
@ -3943,7 +3943,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);
|
||||
|
@ -4001,6 +4001,12 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
|
|||
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 *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);
|
||||
|
@ -4121,14 +4127,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 != rb_enc_get(resolved)) {
|
||||
|
|
|
@ -303,6 +303,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)
|
||||
|
|
Загрузка…
Ссылка в новой задаче