Feature #13378 » 0001-reduce-syscalls-on-require.patch
| file.c | ||
|---|---|---|
|
VALUE
|
||
|
rb_find_file(VALUE path)
|
||
|
{
|
||
|
return rb_find_file_safe(path, rb_safe_level());
|
||
|
return rb_find_file_safe(path, rb_safe_level(), 0);
|
||
|
}
|
||
|
VALUE
|
||
|
rb_find_file_safe(VALUE path, int safe_level)
|
||
|
rb_find_file_safe(VALUE path, int safe_level, int defer_load_check)
|
||
|
{
|
||
|
VALUE tmp, load_path;
|
||
|
const char *f = StringValueCStr(path);
|
||
| ... | ... | |
|
if (safe_level >= 1 && !fpath_check(path)) {
|
||
|
rb_raise(rb_eSecurityError, "loading from unsafe path %s", f);
|
||
|
}
|
||
|
if (!rb_file_load_ok(f)) return 0;
|
||
|
if (!defer_load_check && !rb_file_load_ok(f)) {
|
||
|
return 0;
|
||
|
}
|
||
|
if (!expanded)
|
||
|
path = copy_path_class(file_expand_path_1(path), path);
|
||
|
return path;
|
||
| include/ruby/intern.h | ||
|---|---|---|
|
VALUE rb_file_absolute_path(VALUE, VALUE);
|
||
|
VALUE rb_file_dirname(VALUE fname);
|
||
|
int rb_find_file_ext_safe(VALUE*, const char* const*, int);
|
||
|
VALUE rb_find_file_safe(VALUE, int);
|
||
|
VALUE rb_find_file_safe(VALUE, int, int);
|
||
|
int rb_find_file_ext(VALUE*, const char* const*);
|
||
|
VALUE rb_find_file(VALUE);
|
||
|
VALUE rb_file_directory_p(VALUE,VALUE);
|
||
| load.c | ||
|---|---|---|
|
if (loading) *path = rb_filesystem_str_new_cstr(loading);
|
||
|
return 'r';
|
||
|
}
|
||
|
if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
|
||
|
if ((tmp = rb_find_file_safe(fname, safe_level, 1)) != 0) {
|
||
|
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
|
||
|
if (!rb_feature_p(ftptr, ext, TRUE, TRUE, &loading) || loading)
|
||
|
*path = tmp;
|
||
| ... | ... | |
|
#else
|
||
|
rb_str_cat2(tmp, DLEXT);
|
||
|
OBJ_FREEZE(tmp);
|
||
|
if ((tmp = rb_find_file_safe(tmp, safe_level)) != 0) {
|
||
|
if ((tmp = rb_find_file_safe(tmp, safe_level, 0)) != 0) {
|
||
|
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
|
||
|
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
|
||
|
*path = tmp;
|
||
| ... | ... | |
|
if (loading) *path = rb_filesystem_str_new_cstr(loading);
|
||
|
return 's';
|
||
|
}
|
||
|
if ((tmp = rb_find_file_safe(fname, safe_level)) != 0) {
|
||
|
if ((tmp = rb_find_file_safe(fname, safe_level, 0)) != 0) {
|
||
|
ext = strrchr(ftptr = RSTRING_PTR(tmp), '.');
|
||
|
if (!rb_feature_p(ftptr, ext, FALSE, TRUE, &loading) || loading)
|
||
|
*path = tmp;
|
||
| ruby.c | ||
|---|---|---|
|
}
|
||
|
static VALUE
|
||
|
open_load_file(VALUE fname_v, int *xflag)
|
||
|
open_load_file(VALUE fname_v, int *xflag, int script)
|
||
|
{
|
||
|
const char *fname = StringValueCStr(fname_v);
|
||
|
long flen = RSTRING_LEN(fname_v);
|
||
|
VALUE f;
|
||
|
int e;
|
||
|
int e = 0;
|
||
|
int fd = 0;
|
||
|
if (flen == 1 && fname[0] == '-') {
|
||
|
f = rb_stdin;
|
||
|
}
|
||
|
else {
|
||
|
int fd;
|
||
|
/* open(2) may block if fname is point to FIFO and it's empty. Let's
|
||
|
use O_NONBLOCK. */
|
||
|
#if defined O_NONBLOCK && HAVE_FCNTL && !(O_NONBLOCK & O_ACCMODE)
|
||
| ... | ... | |
|
#endif
|
||
|
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
|
||
|
int e = errno;
|
||
|
e = errno;
|
||
|
if (!rb_gc_for_fd(e)) {
|
||
|
rb_load_fail(fname_v, strerror(e));
|
||
|
goto fail;
|
||
|
}
|
||
|
if ((fd = rb_cloexec_open(fname, mode, 0)) < 0) {
|
||
|
rb_load_fail(fname_v, strerror(errno));
|
||
|
goto fail;
|
||
|
}
|
||
|
}
|
||
|
rb_update_max_fd(fd);
|
||
| ... | ... | |
|
/* disabling O_NONBLOCK */
|
||
|
if (fcntl(fd, F_SETFL, 0) < 0) {
|
||
|
e = errno;
|
||
|
(void)close(fd);
|
||
|
rb_load_fail(fname_v, strerror(e));
|
||
|
goto fail;
|
||
|
}
|
||
|
#endif
|
||
|
e = ruby_is_fd_loadable(fd);
|
||
|
if (!e) {
|
||
|
#ifdef S_ISFIFO
|
||
|
{
|
||
|
struct stat st;
|
||
|
if (fstat(fd, &st) != 0) {
|
||
|
e = errno;
|
||
|
goto fail;
|
||
|
}
|
||
|
if (S_ISFIFO(st.st_mode)) {
|
||
|
/*
|
||
|
We need to wait if FIFO is empty. It's FIFO's semantics.
|
||
|
rb_thread_wait_fd() release GVL. So, it's safe.
|
||
|
*/
|
||
|
rb_thread_wait_fd(fd);
|
||
|
} else if (S_ISDIR(st.st_mode)) {
|
||
|
e = EISDIR;
|
||
|
goto fail;
|
||
|
} else if (!S_ISREG(st.st_mode)) {
|
||
|
e = ENXIO;
|
||
|
goto fail;
|
||
|
}
|
||
|
}
|
||
|
#else
|
||
|
/* Note that we've replicated ruby_is_fd_loadable in S_ISFIFO without
|
||
|
* calling fstat64 twice. */
|
||
|
if (!ruby_is_fd_loadable(fd)) {
|
||
|
e = errno;
|
||
|
(void)close(fd);
|
||
|
rb_load_fail(fname_v, strerror(e));
|
||
|
goto fail;
|
||
|
}
|
||
|
#endif
|
||
|
f = rb_io_fdopen(fd, mode, fname);
|
||
|
if (e < 0) {
|
||
| ... | ... | |
|
}
|
||
|
}
|
||
|
return f;
|
||
|
fail:
|
||
|
if (fd > 0) (void)close(fd);
|
||
|
if (script) {
|
||
|
/* when we reach this from `$ ruby bad.rb`, show the reason */
|
||
|
rb_load_fail(fname_v, strerror(e));
|
||
|
} else {
|
||
|
/* when called from require/load/etc., just show:
|
||
|
* "cannot load such file", same as `load_failed`. */
|
||
|
rb_load_fail(fname_v, "cannot load such file");
|
||
|
}
|
||
|
}
|
||
|
static VALUE
|
||
| ... | ... | |
|
arg.script = script;
|
||
|
arg.opt = opt;
|
||
|
arg.xflag = 0;
|
||
|
arg.f = open_load_file(rb_str_encode_ospath(fname), &arg.xflag);
|
||
|
arg.f = open_load_file(rb_str_encode_ospath(fname), &arg.xflag, script);
|
||
|
return (NODE *)rb_ensure(load_file_internal, (VALUE)&arg,
|
||
|
restore_load_file, (VALUE)&arg);
|
||
|
}
|
||