Skip to content

Commit 579ffd9

Browse files
committed
merge revision(s) 62606,62607: [Backport ruby#14557]
file.c: get rid of useless conversion * file.c (rb_file_s_stat): File.stat does not accept an IO object as trying conversion to path name string first. skip conversion to IO and try stat(2) only. 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 ruby#14557] git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_2_5@62632 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
1 parent 607927b commit 579ffd9

3 files changed

Lines changed: 58 additions & 21 deletions

File tree

β€Žfile.cβ€Ž

Lines changed: 46 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1081,6 +1081,17 @@ no_gvl_fstat(void *data)
10811081
return (VALUE)fstat(arg->file.fd, arg->st);
10821082
}
10831083

1084+
static int
1085+
fstat_without_gvl(int fd, struct stat *st)
1086+
{
1087+
no_gvl_stat_data data;
1088+
1089+
data.file.fd = fd;
1090+
data.st = st;
1091+
1092+
return (int)(VALUE)rb_thread_io_blocking_region(no_gvl_fstat, &data, fd);
1093+
}
1094+
10841095
static void *
10851096
no_gvl_stat(void * data)
10861097
{
@@ -1089,27 +1100,38 @@ no_gvl_stat(void * data)
10891100
}
10901101

10911102
static int
1092-
rb_stat(VALUE file, struct stat *st)
1103+
stat_without_gvl(const char *path, struct stat *st)
10931104
{
1094-
VALUE tmp;
1095-
VALUE result;
10961105
no_gvl_stat_data data;
10971106

1107+
data.file.path = path;
10981108
data.st = st;
1109+
1110+
return (int)(VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data,
1111+
RUBY_UBF_IO, NULL);
1112+
}
1113+
1114+
static int
1115+
rb_stat(VALUE file, struct stat *st)
1116+
{
1117+
VALUE tmp;
1118+
int result;
1119+
10991120
tmp = rb_check_convert_type_with_id(file, T_FILE, "IO", idTo_io);
11001121
if (!NIL_P(tmp)) {
11011122
rb_io_t *fptr;
11021123

11031124
GetOpenFile(tmp, fptr);
1104-
data.file.fd = fptr->fd;
1105-
result = rb_thread_io_blocking_region(no_gvl_fstat, &data, fptr->fd);
1106-
return (int)result;
1125+
result = fstat_without_gvl(fptr->fd, st);
1126+
file = tmp;
11071127
}
1108-
FilePathValue(file);
1109-
file = rb_str_encode_ospath(file);
1110-
data.file.path = StringValueCStr(file);
1111-
result = (VALUE)rb_thread_call_without_gvl(no_gvl_stat, &data, RUBY_UBF_IO, NULL);
1112-
return (int)result;
1128+
else {
1129+
FilePathValue(file);
1130+
file = rb_str_encode_ospath(file);
1131+
result = stat_without_gvl(RSTRING_PTR(file), st);
1132+
}
1133+
RB_GC_GUARD(file);
1134+
return result;
11131135
}
11141136

11151137
/*
@@ -1129,7 +1151,8 @@ rb_file_s_stat(VALUE klass, VALUE fname)
11291151
struct stat st;
11301152

11311153
FilePathValue(fname);
1132-
if (rb_stat(fname, &st) < 0) {
1154+
fname = rb_str_encode_ospath(fname);
1155+
if (stat_without_gvl(RSTRING_PTR(fname), &st) < 0) {
11331156
rb_sys_fail_path(fname);
11341157
}
11351158
return rb_stat_new(&st);
@@ -3919,7 +3942,7 @@ enum rb_realpath_mode {
39193942
};
39203943

39213944
static int
3922-
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
3945+
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE fallback,
39233946
VALUE loopcheck, enum rb_realpath_mode mode, int last)
39243947
{
39253948
const char *pend = unresolved + strlen(unresolved);
@@ -3977,6 +4000,12 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
39774000
ret = lstat_without_gvl(RSTRING_PTR(testpath), &sbuf);
39784001
if (ret == -1) {
39794002
int e = errno;
4003+
if (e == ENOENT && !NIL_P(fallback)) {
4004+
if (stat_without_gvl(RSTRING_PTR(fallback), &sbuf) == 0) {
4005+
rb_str_replace(*resolvedp, fallback);
4006+
return 0;
4007+
}
4008+
}
39804009
if (mode == RB_REALPATH_CHECK) return -1;
39814010
if (e == ENOENT) {
39824011
if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
@@ -4008,7 +4037,7 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
40084037
*resolvedp = link;
40094038
*prefixlenp = link_prefixlen;
40104039
}
4011-
if (realpath_rec(prefixlenp, resolvedp, link_names,
4040+
if (realpath_rec(prefixlenp, resolvedp, link_names, testpath,
40124041
loopcheck, mode, !*unresolved_firstsep))
40134042
return -1;
40144043
RB_GC_GUARD(link_orig);
@@ -4097,14 +4126,14 @@ rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode
40974126

40984127
loopcheck = rb_hash_new();
40994128
if (curdir_names) {
4100-
if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0))
4129+
if (realpath_rec(&prefixlen, &resolved, curdir_names, Qnil, loopcheck, mode, 0))
41014130
return Qnil;
41024131
}
41034132
if (basedir_names) {
4104-
if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0))
4133+
if (realpath_rec(&prefixlen, &resolved, basedir_names, Qnil, loopcheck, mode, 0))
41054134
return Qnil;
41064135
}
4107-
if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1))
4136+
if (realpath_rec(&prefixlen, &resolved, path_names, Qnil, loopcheck, mode, 1))
41084137
return Qnil;
41094138

41104139
if (origenc != rb_enc_get(resolved)) {

β€Žtest/ruby/test_file.rbβ€Ž

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,14 @@ def test_realpath_taintedness
303303
}
304304
end
305305

306+
def test_realpath_special_symlink
307+
IO.pipe do |r, w|
308+
if File.pipe?(path = "/dev/fd/#{r.fileno}")
309+
assert_file.identical?(File.realpath(path), path)
310+
end
311+
end
312+
end
313+
306314
def test_realdirpath
307315
Dir.mktmpdir('rubytest-realdirpath') {|tmpdir|
308316
realdir = File.realpath(tmpdir)

β€Žversion.hβ€Ž

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
#define RUBY_VERSION "2.5.0"
2-
#define RUBY_RELEASE_DATE "2018-02-28"
3-
#define RUBY_PATCHLEVEL 38
2+
#define RUBY_RELEASE_DATE "2018-03-02"
3+
#define RUBY_PATCHLEVEL 39
44

55
#define RUBY_RELEASE_YEAR 2018
6-
#define RUBY_RELEASE_MONTH 2
7-
#define RUBY_RELEASE_DAY 28
6+
#define RUBY_RELEASE_MONTH 3
7+
#define RUBY_RELEASE_DAY 2
88

99
#include "ruby/version.h"
1010

0 commit comments

Comments
 (0)