mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
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:
parent
1daa624d56
commit
5a53cbe314
2 changed files with 19 additions and 5 deletions
16
file.c
16
file.c
|
@ -3943,7 +3943,7 @@ enum rb_realpath_mode {
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
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)
|
VALUE loopcheck, enum rb_realpath_mode mode, int last)
|
||||||
{
|
{
|
||||||
const char *pend = unresolved + strlen(unresolved);
|
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);
|
ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf);
|
||||||
if (ret == -1) {
|
if (ret == -1) {
|
||||||
int e = errno;
|
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 (mode == RB_REALPATH_CHECK) return -1;
|
||||||
if (e == ENOENT) {
|
if (e == ENOENT) {
|
||||||
if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
|
if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
|
||||||
|
@ -4032,7 +4038,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
|
||||||
*resolvedp = link;
|
*resolvedp = link;
|
||||||
*prefixlenp = link_prefixlen;
|
*prefixlenp = link_prefixlen;
|
||||||
}
|
}
|
||||||
if (realpath_rec(prefixlenp, resolvedp, link_names,
|
if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
|
||||||
loopcheck, mode, !*unresolved_firstsep))
|
loopcheck, mode, !*unresolved_firstsep))
|
||||||
return -1;
|
return -1;
|
||||||
RB_GC_GUARD(link_orig);
|
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();
|
loopcheck = rb_hash_new();
|
||||||
if (curdir_names) {
|
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;
|
return Qnil;
|
||||||
}
|
}
|
||||||
if (basedir_names) {
|
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;
|
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;
|
return Qnil;
|
||||||
|
|
||||||
if (origenc != rb_enc_get(resolved)) {
|
if (origenc != rb_enc_get(resolved)) {
|
||||||
|
|
|
@ -303,6 +303,14 @@ class TestFile < Test::Unit::TestCase
|
||||||
}
|
}
|
||||||
end
|
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
|
def test_realdirpath
|
||||||
Dir.mktmpdir('rubytest-realdirpath') {|tmpdir|
|
Dir.mktmpdir('rubytest-realdirpath') {|tmpdir|
|
||||||
realdir = File.realpath(tmpdir)
|
realdir = File.realpath(tmpdir)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue