1
0
Fork 0
mirror of https://github.com/ruby/ruby.git synced 2022-11-09 12:17:21 -05:00

file.c: rb_check_realpath

* file.c (rb_check_realpath): returns real path which has no
  symbolic links.  similar to rb_realpath except for returning
  Qnil if any parts did not exist.

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@59983 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2017-09-21 07:29:16 +00:00
parent 5193ad1319
commit 5754f15975
2 changed files with 60 additions and 18 deletions

77
file.c
View file

@ -3775,8 +3775,29 @@ rb_file_s_absolute_path(int argc, const VALUE *argv)
return rb_file_absolute_path(argv[0], argc > 1 ? argv[1] : Qnil); return rb_file_absolute_path(argv[0], argc > 1 ? argv[1] : Qnil);
} }
static void #ifdef __native_client__
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE loopcheck, int strict, int last) VALUE
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
return path;
}
VALUE
rb_check_realpath(VALUE basedir, VALUE path)
{
return path;
}
#else
enum rb_realpath_mode {
RB_REALPATH_CHECK,
RB_REALPATH_DIR,
RB_REALPATH_STRICT,
RB_REALPATH_MODE_MAX
};
static int
realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved,
VALUE loopcheck, enum rb_realpath_mode mode, int last)
{ {
const char *pend = unresolved + strlen(unresolved); const char *pend = unresolved + strlen(unresolved);
rb_encoding *enc = rb_enc_get(*resolvedp); rb_encoding *enc = rb_enc_get(*resolvedp);
@ -3817,6 +3838,10 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l
checkval = rb_hash_aref(loopcheck, testpath); checkval = rb_hash_aref(loopcheck, testpath);
if (!NIL_P(checkval)) { if (!NIL_P(checkval)) {
if (checkval == ID2SYM(resolving)) { if (checkval == ID2SYM(resolving)) {
if (mode == RB_REALPATH_CHECK) {
errno = ELOOP;
return -1;
}
rb_syserr_fail_path(ELOOP, testpath); rb_syserr_fail_path(ELOOP, testpath);
} }
else { else {
@ -3833,8 +3858,9 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l
#endif #endif
if (ret == -1) { if (ret == -1) {
int e = errno; int e = errno;
if (mode == RB_REALPATH_CHECK) return -1;
if (e == ENOENT) { if (e == ENOENT) {
if (strict || !last || *unresolved_firstsep) if (mode == RB_REALPATH_STRICT || !last || *unresolved_firstsep)
rb_syserr_fail_path(e, testpath); rb_syserr_fail_path(e, testpath);
*resolvedp = testpath; *resolvedp = testpath;
break; break;
@ -3863,7 +3889,9 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l
*resolvedp = link; *resolvedp = link;
*prefixlenp = link_prefixlen; *prefixlenp = link_prefixlen;
} }
realpath_rec(prefixlenp, resolvedp, link_names, loopcheck, strict, *unresolved_firstsep == '\0'); if (realpath_rec(prefixlenp, resolvedp, link_names,
loopcheck, mode, !*unresolved_firstsep))
return -1;
RB_GC_GUARD(link_orig); RB_GC_GUARD(link_orig);
rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp)); rb_hash_aset(loopcheck, testpath, rb_str_dup_frozen(*resolvedp));
} }
@ -3877,17 +3905,11 @@ realpath_rec(long *prefixlenp, VALUE *resolvedp, const char *unresolved, VALUE l
} }
} }
} }
return 0;
} }
#ifdef __native_client__ static VALUE
VALUE rb_check_realpath_internal(VALUE basedir, VALUE path, enum rb_realpath_mode mode)
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
return path;
}
#else
VALUE
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{ {
long prefixlen; long prefixlen;
VALUE resolved; VALUE resolved;
@ -3955,11 +3977,16 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
} }
loopcheck = rb_hash_new(); loopcheck = rb_hash_new();
if (curdir_names) if (curdir_names) {
realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, 1, 0); if (realpath_rec(&prefixlen, &resolved, curdir_names, loopcheck, mode, 0))
if (basedir_names) return Qnil;
realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, 1, 0); }
realpath_rec(&prefixlen, &resolved, path_names, loopcheck, strict, 1); if (basedir_names) {
if (realpath_rec(&prefixlen, &resolved, basedir_names, loopcheck, mode, 0))
return Qnil;
}
if (realpath_rec(&prefixlen, &resolved, path_names, loopcheck, mode, 1))
return Qnil;
if (origenc != rb_enc_get(resolved)) { if (origenc != rb_enc_get(resolved)) {
if (rb_enc_str_asciionly_p(resolved)) { if (rb_enc_str_asciionly_p(resolved)) {
@ -3973,6 +4000,20 @@ rb_realpath_internal(VALUE basedir, VALUE path, int strict)
OBJ_TAINT(resolved); OBJ_TAINT(resolved);
return resolved; return resolved;
} }
VALUE
rb_realpath_internal(VALUE basedir, VALUE path, int strict)
{
const enum rb_realpath_mode mode =
strict ? RB_REALPATH_STRICT : RB_REALPATH_DIR;
return rb_check_realpath_internal(basedir, path, mode);
}
VALUE
rb_check_realpath(VALUE basedir, VALUE path)
{
return rb_check_realpath_internal(basedir, path, RB_REALPATH_CHECK);
}
#endif #endif
/* /*

View file

@ -1179,6 +1179,7 @@ void rb_mark_end_proc(void);
VALUE rb_home_dir_of(VALUE user, VALUE result); VALUE rb_home_dir_of(VALUE user, VALUE result);
VALUE rb_default_home_dir(VALUE result); VALUE rb_default_home_dir(VALUE result);
VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict); VALUE rb_realpath_internal(VALUE basedir, VALUE path, int strict);
VALUE rb_check_realpath(VALUE basedir, VALUE path);
void rb_file_const(const char*, VALUE); void rb_file_const(const char*, VALUE);
int rb_file_load_ok(const char *); int rb_file_load_ok(const char *);
VALUE rb_file_expand_path_fast(VALUE, VALUE); VALUE rb_file_expand_path_fast(VALUE, VALUE);