Feature #13378 ยป 0001-reduce-syscalls-on-require.patch
file.c | ||
---|---|---|
5826 | 5826 |
VALUE |
5827 | 5827 |
rb_find_file(VALUE path) |
5828 | 5828 |
{ |
5829 |
return rb_find_file_safe(path, rb_safe_level()); |
|
5829 |
return rb_find_file_safe(path, rb_safe_level(), 0);
|
|
5830 | 5830 |
} |
5831 | 5831 | |
5832 | 5832 |
VALUE |
5833 |
rb_find_file_safe(VALUE path, int safe_level) |
|
5833 |
rb_find_file_safe(VALUE path, int safe_level, int defer_load_check)
|
|
5834 | 5834 |
{ |
5835 | 5835 |
VALUE tmp, load_path; |
5836 | 5836 |
const char *f = StringValueCStr(path); |
... | ... | |
5850 | 5850 |
if (safe_level >= 1 && !fpath_check(path)) { |
5851 | 5851 |
rb_raise(rb_eSecurityError, "loading from unsafe path %s", f); |
5852 | 5852 |
} |
5853 |
if (!rb_file_load_ok(f)) return 0; |
|
5853 |
if (!defer_load_check && !rb_file_load_ok(f)) { |
|
5854 |
return 0; |
|
5855 |
} |
|
5854 | 5856 |
if (!expanded) |
5855 | 5857 |
path = copy_path_class(file_expand_path_1(path), path); |
5856 | 5858 |
return path; |
include/ruby/intern.h | ||
---|---|---|
456 | 456 |
VALUE rb_file_absolute_path(VALUE, VALUE); |
457 | 457 |
VALUE rb_file_dirname(VALUE fname); |
458 | 458 |
int rb_find_file_ext_safe(VALUE*, const char* const*, int); |
459 |
VALUE rb_find_file_safe(VALUE, int); |
|
459 |
VALUE rb_find_file_safe(VALUE, int, int);
|
|
460 | 460 |
int rb_find_file_ext(VALUE*, const char* const*); |
461 | 461 |
VALUE rb_find_file(VALUE); |
462 | 462 |
VALUE rb_file_directory_p(VALUE,VALUE); |
load.c | ||
---|---|---|
859 | 859 |
if (loading) *path = rb_filesystem_str_new_cstr(loading); |
860 | 860 |
return 'r'; |
861 | 861 |
} |
862 |
if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { |
|
862 |
if ((tmp = rb_find_file_safe(fname, safe_level, 1)) != 0) {
|
|
863 | 863 |
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); |
864 | 864 |
if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading) |
865 | 865 |
*path = tmp; |
... | ... | |
884 | 884 |
#else |
885 | 885 |
rb_str_cat2(tmp, DLEXT); |
886 | 886 |
OBJ_FREEZE(tmp); |
887 |
if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) { |
|
887 |
if ((tmp = rb_find_file_safe(tmp, safe_level, 0)) != 0) {
|
|
888 | 888 |
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); |
889 | 889 |
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) |
890 | 890 |
*path = tmp; |
... | ... | |
897 | 897 |
if (loading) *path = rb_filesystem_str_new_cstr(loading); |
898 | 898 |
return 's'; |
899 | 899 |
} |
900 |
if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) { |
|
900 |
if ((tmp = rb_find_file_safe(fname, safe_level, 0)) != 0) {
|
|
901 | 901 |
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.'); |
902 | 902 |
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading) |
903 | 903 |
*path = tmp; |
ruby.c | ||
---|---|---|
1883 | 1883 |
} |
1884 | 1884 | |
1885 | 1885 |
static VALUE |
1886 |
open_load_file(VALUE fname_v, int *xflag) |
|
1886 |
open_load_file(VALUE fname_v, int *xflag, int script)
|
|
1887 | 1887 |
{ |
1888 | 1888 |
const char *fname = StringValueCStr(fname_v); |
1889 | 1889 |
long flen = RSTRING_LEN(fname_v); |
1890 | 1890 |
VALUE f; |
1891 |
int e; |
|
1891 |
int e = 0; |
|
1892 |
int fd = 0; |
|
1892 | 1893 | |
1893 | 1894 |
if (flen == 1 && fname[0] == '-') { |
1894 | 1895 |
f = rb_stdin; |
1895 | 1896 |
} |
1896 | 1897 |
else { |
1897 |
int fd; |
|
1898 | 1898 |
/* open(2) may block if fname is point to FIFO and it's empty. Let's |
1899 | 1899 |
use O_NONBLOCK. */ |
1900 | 1900 |
#if defined O_NONBLOCK && HAVE_FCNTL && !(O_NONBLOCK & O_ACCMODE) |
... | ... | |
1920 | 1920 |
#endif |
1921 | 1921 | |
1922 | 1922 |
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) { |
1923 |
int e = errno;
|
|
1923 |
e = errno; |
|
1924 | 1924 |
if (!rb_gc_for_fd(e)) { |
1925 |
rb_load_fail(fname_v, strerror(e));
|
|
1925 |
goto fail;
|
|
1926 | 1926 |
} |
1927 | 1927 |
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) { |
1928 |
rb_load_fail(fname_v, strerror(errno));
|
|
1928 |
goto fail;
|
|
1929 | 1929 |
} |
1930 | 1930 |
} |
1931 | 1931 |
rb_update_max_fd(fd); |
... | ... | |
1934 | 1934 |
/* disabling O_NONBLOCK */ |
1935 | 1935 |
if (fcntl(fd, F_SETFL, 0) < 0) { |
1936 | 1936 |
e = errno; |
1937 |
(void)close(fd); |
|
1938 |
rb_load_fail(fname_v, strerror(e)); |
|
1937 |
goto fail; |
|
1939 | 1938 |
} |
1940 | 1939 |
#endif |
1941 | 1940 | |
1942 |
e = ruby_is_fd_loadable(fd); |
|
1943 |
if (!e) { |
|
1941 |
#ifdef S_ISFIFO |
|
1942 |
{ |
|
1943 |
struct stat st; |
|
1944 |
if (fstat(fd, &st) != 0) { |
|
1945 |
e = errno; |
|
1946 |
goto fail; |
|
1947 |
} |
|
1948 |
if (S_ISFIFO(st.st_mode)) { |
|
1949 |
/* |
|
1950 |
We need to wait if FIFO is empty. It's FIFO's semantics. |
|
1951 |
rb_thread_wait_fd() release GVL. So, it's safe. |
|
1952 |
*/ |
|
1953 |
rb_thread_wait_fd(fd); |
|
1954 |
} else if (S_ISDIR(st.st_mode)) { |
|
1955 |
e = EISDIR; |
|
1956 |
goto fail; |
|
1957 |
} else if (!S_ISREG(st.st_mode)) { |
|
1958 |
e = ENXIO; |
|
1959 |
goto fail; |
|
1960 |
} |
|
1961 |
} |
|
1962 |
#else |
|
1963 |
/* Note that we've replicated ruby_is_fd_loadable in S_ISFIFO without |
|
1964 |
* calling fstat64 twice. */ |
|
1965 |
if (!ruby_is_fd_loadable(fd)) { |
|
1944 | 1966 |
e = errno; |
1945 |
(void)close(fd); |
|
1946 |
rb_load_fail(fname_v, strerror(e)); |
|
1967 |
goto fail; |
|
1947 | 1968 |
} |
1969 |
#endif |
|
1948 | 1970 | |
1949 | 1971 |
f = rb_io_fdopen(fd, mode, fname); |
1950 | 1972 |
if (e < 0) { |
... | ... | |
1956 | 1978 |
} |
1957 | 1979 |
} |
1958 | 1980 |
return f; |
1981 |
fail: |
|
1982 |
if (fd > 0) (void)close(fd); |
|
1983 |
if (script) { |
|
1984 |
/* when we reach this from `$ ruby bad.rb`, show the reason */ |
|
1985 |
rb_load_fail(fname_v, strerror(e)); |
|
1986 |
} else { |
|
1987 |
/* when called from require/load/etc., just show: |
|
1988 |
* "cannot load such file", same as `load_failed`. */ |
|
1989 |
rb_load_fail(fname_v, "cannot load such file"); |
|
1990 |
} |
|
1959 | 1991 |
} |
1960 | 1992 | |
1961 | 1993 |
static VALUE |
... | ... | |
1979 | 2011 |
arg.script = script; |
1980 | 2012 |
arg.opt = opt; |
1981 | 2013 |
arg.xflag = 0; |
1982 |
arg.f = open_load_file(rb_str_encode_ospath(fname), &arg.xflag); |
|
2014 |
arg.f = open_load_file(rb_str_encode_ospath(fname), &arg.xflag, script);
|
|
1983 | 2015 |
return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg, |
1984 | 2016 |
restore_load_file, (VALUE)&arg); |
1985 | 2017 |
} |
1986 |
- |