Project

General

Profile

Feature #13378 ยป 0001-reduce-syscalls-on-require.patch

burke (Burke Libbey), 03/28/2017 07:31 PM

View differences:

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
-