mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* file.c (strrdirsep): ignore trailing directory separators.
* file.c (rb_file_s_expand_path): File.expand_path(".","/") should return "/". (ruby-bugs-ja:PR#389) * file.c (rb_file_s_basename): also ignore trailing directory separators, in compliance with SUSv3. (ruby-bugs-ja:PR#390) * file.c (rb_file_s_dirname, rb_file_s_extname): ditto. * file.c (rb_file_s_split): get rid of converting twice. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@3485 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
b3ec759e4b
commit
7dd303419e
2 changed files with 121 additions and 83 deletions
14
ChangeLog
14
ChangeLog
|
@ -1,3 +1,17 @@
|
||||||
|
Wed Feb 12 23:42:10 2003 Nobuyoshi Nakada <nobu.nokada@softhome.net>
|
||||||
|
|
||||||
|
* file.c (strrdirsep): ignore trailing directory separators.
|
||||||
|
|
||||||
|
* file.c (rb_file_s_expand_path): File.expand_path(".","/") should
|
||||||
|
return "/". (ruby-bugs-ja:PR#389)
|
||||||
|
|
||||||
|
* file.c (rb_file_s_basename): also ignore trailing directory
|
||||||
|
separators, in compliance with SUSv3. (ruby-bugs-ja:PR#390)
|
||||||
|
|
||||||
|
* file.c (rb_file_s_dirname, rb_file_s_extname): ditto.
|
||||||
|
|
||||||
|
* file.c (rb_file_s_split): get rid of converting twice.
|
||||||
|
|
||||||
Mon Feb 10 20:55:15 2003 WATANABE Hirofumi <eban@ruby-lang.org>
|
Mon Feb 10 20:55:15 2003 WATANABE Hirofumi <eban@ruby-lang.org>
|
||||||
|
|
||||||
* ext/extmk.rb (parse_args): add '-n' to $mflags BEFORE "--".
|
* ext/extmk.rb (parse_args): add '-n' to $mflags BEFORE "--".
|
||||||
|
|
192
file.c
192
file.c
|
@ -1352,6 +1352,7 @@ rb_file_s_umask(argc, argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined DOSISH
|
#if defined DOSISH
|
||||||
|
#define DOSISH_UNC
|
||||||
#define isdirsep(x) ((x) == '/' || (x) == '\\')
|
#define isdirsep(x) ((x) == '/' || (x) == '\\')
|
||||||
#else
|
#else
|
||||||
#define isdirsep(x) ((x) == '/')
|
#define isdirsep(x) ((x) == '/')
|
||||||
|
@ -1364,10 +1365,16 @@ rb_file_s_umask(argc, argv)
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(DOSISH_DRIVE_LETTER) || defined(__CYGWIN__)
|
#ifdef __CYGWIN__
|
||||||
|
#undef DOSISH
|
||||||
|
#define DOSISH_UNC
|
||||||
|
#define DOSISH_DRIVE_LETTER
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
static inline int
|
static inline int
|
||||||
has_drive_letter(buf)
|
has_drive_letter(buf)
|
||||||
char *buf;
|
const char *buf;
|
||||||
{
|
{
|
||||||
if (ISALPHA(buf[0]) && buf[1] == ':') {
|
if (ISALPHA(buf[0]) && buf[1] == ':') {
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -1406,14 +1413,28 @@ getcwdofdrv(drv, buf, len)
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline char *
|
||||||
|
skiproot(path)
|
||||||
|
const char *path;
|
||||||
|
{
|
||||||
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
|
if (has_drive_letter(path)) path += 2;
|
||||||
|
#endif
|
||||||
|
while (isdirsep(*path)) path++;
|
||||||
|
return (char *)path;
|
||||||
|
}
|
||||||
|
|
||||||
static char *
|
static char *
|
||||||
strrdirsep(path)
|
strrdirsep(path)
|
||||||
char *path;
|
const char *path;
|
||||||
{
|
{
|
||||||
char *last = NULL;
|
char *last = NULL;
|
||||||
while (*path) {
|
while (*path) {
|
||||||
if (isdirsep(*path)) {
|
if (isdirsep(*path)) {
|
||||||
last = path++;
|
const char *tmp = path++;
|
||||||
|
while (isdirsep(*path)) path++;
|
||||||
|
if (!*path) break;
|
||||||
|
last = (char *)tmp;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
path = CharNext(path);
|
path = CharNext(path);
|
||||||
|
@ -1422,6 +1443,23 @@ strrdirsep(path)
|
||||||
return last;
|
return last;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static char *
|
||||||
|
chompdirsep(path)
|
||||||
|
const char *path;
|
||||||
|
{
|
||||||
|
while (*path) {
|
||||||
|
if (isdirsep(*path)) {
|
||||||
|
const char *last = path++;
|
||||||
|
while (isdirsep(*path)) path++;
|
||||||
|
if (!*path) return (char *)last;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
path = CharNext(path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (char *)path;
|
||||||
|
}
|
||||||
|
|
||||||
#define BUFCHECK(cond) while (cond) {\
|
#define BUFCHECK(cond) while (cond) {\
|
||||||
long bdiff = p - buf;\
|
long bdiff = p - buf;\
|
||||||
buflen *= 2;\
|
buflen *= 2;\
|
||||||
|
@ -1437,21 +1475,17 @@ strrdirsep(path)
|
||||||
|
|
||||||
static int is_absolute_path _((const char*));
|
static int is_absolute_path _((const char*));
|
||||||
|
|
||||||
VALUE
|
static VALUE
|
||||||
rb_file_s_expand_path(argc, argv)
|
file_expand_path(fname, dname, result)
|
||||||
int argc;
|
|
||||||
VALUE *argv;
|
|
||||||
{
|
|
||||||
VALUE fname, dname, result;
|
VALUE fname, dname, result;
|
||||||
|
{
|
||||||
char *s, *buf, *b, *p, *pend;
|
char *s, *buf, *b, *p, *pend;
|
||||||
long buflen = MAXPATHLEN;
|
long buflen;
|
||||||
int tainted;
|
int tainted;
|
||||||
|
|
||||||
rb_scan_args(argc, argv, "11", &fname, &dname);
|
|
||||||
result = rb_str_new(0, buflen + 2);
|
|
||||||
|
|
||||||
s = StringValuePtr(fname);
|
s = StringValuePtr(fname);
|
||||||
p = buf = RSTRING(result)->ptr;
|
p = buf = RSTRING(result)->ptr;
|
||||||
|
buflen = RSTRING(result)->len - 2;
|
||||||
pend = p + buflen;
|
pend = p + buflen;
|
||||||
tainted = OBJ_TAINTED(fname);
|
tainted = OBJ_TAINTED(fname);
|
||||||
|
|
||||||
|
@ -1502,7 +1536,7 @@ rb_file_s_expand_path(argc, argv)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#if defined DOSISH_DRIVE_LETTER || defined __CYGWIN__
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
/* skip drive letter */
|
/* skip drive letter */
|
||||||
else if (has_drive_letter(s)) {
|
else if (has_drive_letter(s)) {
|
||||||
if (isdirsep(s[2])) {
|
if (isdirsep(s[2])) {
|
||||||
|
@ -1520,31 +1554,23 @@ rb_file_s_expand_path(argc, argv)
|
||||||
/* specified drive, but not full path */
|
/* specified drive, but not full path */
|
||||||
int same = 0;
|
int same = 0;
|
||||||
if (!NIL_P(dname)) {
|
if (!NIL_P(dname)) {
|
||||||
dname = rb_file_s_expand_path(1, &dname);
|
dname = file_expand_path(dname, Qnil, result);
|
||||||
if (has_drive_letter(RSTRING(dname)->ptr) &&
|
if (has_drive_letter(RSTRING(dname)->ptr) &&
|
||||||
TOLOWER(*RSTRING(dname)->ptr) == TOLOWER(s[0])) {
|
TOLOWER(*RSTRING(dname)->ptr) == TOLOWER(s[0])) {
|
||||||
/* ok, same drive */
|
/* ok, same drive */
|
||||||
same = 1;
|
same = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (same) {
|
if (!same) {
|
||||||
if (OBJ_TAINTED(dname)) tainted = 1;
|
|
||||||
BUFCHECK (strlen(RSTRING(dname)->ptr) >= buflen);
|
|
||||||
strcpy(buf, RSTRING(dname)->ptr);
|
|
||||||
p = &buf[strlen(buf)];
|
|
||||||
s += 2;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
getcwdofdrv(*s, buf, MAXPATHLEN);
|
getcwdofdrv(*s, buf, MAXPATHLEN);
|
||||||
s += 2;
|
|
||||||
tainted = 1;
|
tainted = 1;
|
||||||
p = &buf[strlen(buf)];
|
|
||||||
if (strrdirsep(buf) == p - 1 && *s) p--; /* drop `/' */
|
|
||||||
}
|
}
|
||||||
|
p = chompdirsep(skiproot(buf));
|
||||||
|
s += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#if defined DOSISH && ! defined(__CYGWIN__)
|
#ifdef DOSISH
|
||||||
else if (isdirsep(*s) && !is_absolute_path(s)) {
|
else if (isdirsep(*s) && !is_absolute_path(s)) {
|
||||||
/* specified full path, but not drive letter */
|
/* specified full path, but not drive letter */
|
||||||
/* we need to get the drive letter */
|
/* we need to get the drive letter */
|
||||||
|
@ -1562,11 +1588,7 @@ rb_file_s_expand_path(argc, argv)
|
||||||
#endif
|
#endif
|
||||||
else if (!is_absolute_path(s)) {
|
else if (!is_absolute_path(s)) {
|
||||||
if (!NIL_P(dname)) {
|
if (!NIL_P(dname)) {
|
||||||
dname = rb_file_s_expand_path(1, &dname);
|
file_expand_path(dname, Qnil, result);
|
||||||
if (OBJ_TAINTED(dname)) tainted = 1;
|
|
||||||
BUFCHECK(RSTRING(dname)->len > buflen);
|
|
||||||
memcpy(buf, RSTRING(dname)->ptr, RSTRING(dname)->len);
|
|
||||||
p += RSTRING(dname)->len;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
char *dir = my_getcwd();
|
char *dir = my_getcwd();
|
||||||
|
@ -1575,9 +1597,8 @@ rb_file_s_expand_path(argc, argv)
|
||||||
BUFCHECK(strlen(dir) > buflen);
|
BUFCHECK(strlen(dir) > buflen);
|
||||||
strcpy(buf, dir);
|
strcpy(buf, dir);
|
||||||
free(dir);
|
free(dir);
|
||||||
p = &buf[strlen(buf)];
|
|
||||||
}
|
}
|
||||||
while (p > buf && strrdirsep(buf) == p - 1) p--;
|
p = chompdirsep(skiproot(buf));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (*s && isdirsep(*s)) {
|
while (*s && isdirsep(*s)) {
|
||||||
|
@ -1646,7 +1667,7 @@ rb_file_s_expand_path(argc, argv)
|
||||||
memcpy(++p, b, s-b);
|
memcpy(++p, b, s-b);
|
||||||
p += s-b;
|
p += s-b;
|
||||||
}
|
}
|
||||||
#if defined DOSISH_DRIVE_LETTER || defined __CYGWIN__
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
else if (ISALPHA(buf[0]) && (buf[1] == ':') && isdirsep(buf[2])) {
|
else if (ISALPHA(buf[0]) && (buf[1] == ':') && isdirsep(buf[2])) {
|
||||||
/* root directory needs a trailing backslash,
|
/* root directory needs a trailing backslash,
|
||||||
otherwise it mean the current directory of the drive */
|
otherwise it mean the current directory of the drive */
|
||||||
|
@ -1663,6 +1684,17 @@ rb_file_s_expand_path(argc, argv)
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VALUE
|
||||||
|
rb_file_s_expand_path(argc, argv)
|
||||||
|
int argc;
|
||||||
|
VALUE *argv;
|
||||||
|
{
|
||||||
|
VALUE fname, dname;
|
||||||
|
rb_scan_args(argc, argv, "11", &fname, &dname);
|
||||||
|
|
||||||
|
return file_expand_path(fname, dname, rb_str_new(0, MAXPATHLEN + 2));
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
rmext(p, e)
|
rmext(p, e)
|
||||||
const char *p, *e;
|
const char *p, *e;
|
||||||
|
@ -1671,7 +1703,7 @@ rmext(p, e)
|
||||||
|
|
||||||
if (!e) return 0;
|
if (!e) return 0;
|
||||||
|
|
||||||
l1 = strlen(p);
|
l1 = chompdirsep(p) - p;
|
||||||
l2 = strlen(e);
|
l2 = strlen(e);
|
||||||
if (l2 == 2 && e[1] == '*') {
|
if (l2 == 2 && e[1] == '*') {
|
||||||
e = strrchr(p, *e);
|
e = strrchr(p, *e);
|
||||||
|
@ -1680,7 +1712,7 @@ rmext(p, e)
|
||||||
}
|
}
|
||||||
if (l1 < l2) return l1;
|
if (l1 < l2) return l1;
|
||||||
|
|
||||||
if (strcmp(p+l1-l2, e) == 0) {
|
if (strncmp(p+l1-l2, e, l2) == 0) {
|
||||||
return l1-l2;
|
return l1-l2;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -1698,34 +1730,33 @@ rb_file_s_basename(argc, argv)
|
||||||
if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
|
if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
|
||||||
ext = StringValuePtr(fext);
|
ext = StringValuePtr(fext);
|
||||||
}
|
}
|
||||||
name = StringValuePtr(fname);
|
StringValue(fname);
|
||||||
p = strrdirsep(name);
|
if (RSTRING(fname)->len == 0 || !*(name = RSTRING(fname)->ptr))
|
||||||
if (!p) {
|
|
||||||
#if defined(DOSISH_DRIVE_LETTER)
|
|
||||||
if (has_drive_letter(name)) {
|
|
||||||
name += 2;
|
|
||||||
if (NIL_P(fext)) {
|
|
||||||
f = strlen(name);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
f = rmext(name, ext);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
#endif
|
|
||||||
if (NIL_P(fext) || !(f = rmext(name, ext)))
|
|
||||||
return fname;
|
return fname;
|
||||||
basename = rb_str_new(name, f);
|
if (!*(name = skiproot(name))) {
|
||||||
|
p = name - 1;
|
||||||
|
f = 1;
|
||||||
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
|
if (*p == ':') {
|
||||||
|
p++;
|
||||||
|
f = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else if (!(p = strrdirsep(name))) {
|
||||||
|
if (NIL_P(fext) || !(f = rmext(name, ext))) {
|
||||||
|
f = chompdirsep(name) - name;
|
||||||
|
if (f == RSTRING(fname)->len) return fname;
|
||||||
|
}
|
||||||
|
p = name;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
p++; /* skip last / */
|
while (isdirsep(*p)) p++; /* skip last / */
|
||||||
if (NIL_P(fext) || !(f = rmext(p, ext))) {
|
if (NIL_P(fext) || !(f = rmext(p, ext))) {
|
||||||
basename = rb_str_new2(p);
|
f = chompdirsep(p) - p;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
basename = rb_str_new(p, f);
|
basename = rb_str_new(p, f);
|
||||||
}
|
|
||||||
}
|
|
||||||
OBJ_INFECT(basename, fname);
|
OBJ_INFECT(basename, fname);
|
||||||
return basename;
|
return basename;
|
||||||
}
|
}
|
||||||
|
@ -1734,32 +1765,24 @@ static VALUE
|
||||||
rb_file_s_dirname(klass, fname)
|
rb_file_s_dirname(klass, fname)
|
||||||
VALUE klass, fname;
|
VALUE klass, fname;
|
||||||
{
|
{
|
||||||
char *name, *p;
|
char *name, *root, *p;
|
||||||
VALUE dirname;
|
VALUE dirname;
|
||||||
|
|
||||||
name = StringValuePtr(fname);
|
name = StringValuePtr(fname);
|
||||||
p = strrdirsep(name);
|
root = skiproot(name);
|
||||||
if (!p) {
|
#ifdef DOSISH_UNC
|
||||||
#if defined(DOSISH_DRIVE_LETTER)
|
if (root > name + 2 && isdirsep(*name))
|
||||||
if (has_drive_letter(name)) {
|
name = root - 2;
|
||||||
dirname = rb_str_new(name, 2);
|
#else
|
||||||
dirname = rb_str_cat2(dirname, ".");
|
if (root > name + 1)
|
||||||
OBJ_INFECT(dirname, fname);
|
name = root - 1;
|
||||||
return dirname;
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
return rb_str_new2(".");
|
p = strrdirsep(root);
|
||||||
|
if (!p) {
|
||||||
|
p = root;
|
||||||
}
|
}
|
||||||
if (p == name)
|
if (p == name)
|
||||||
p++;
|
return rb_str_new2(".");
|
||||||
#ifdef DOSISH_DRIVE_LETTER
|
|
||||||
if (has_drive_letter(name) && p == &name[2])
|
|
||||||
p++;
|
|
||||||
#endif
|
|
||||||
#ifdef DOSISH
|
|
||||||
if (isdirsep(name[0]) && isdirsep(name[1]) && p == &name[1])
|
|
||||||
p++;
|
|
||||||
#endif
|
|
||||||
dirname = rb_str_new(name, p - name);
|
dirname = rb_str_new(name, p - name);
|
||||||
OBJ_INFECT(dirname, fname);
|
OBJ_INFECT(dirname, fname);
|
||||||
return dirname;
|
return dirname;
|
||||||
|
@ -1782,7 +1805,7 @@ rb_file_s_extname(klass, fname)
|
||||||
e = strrchr(p, '.'); /* get the last dot of the last component */
|
e = strrchr(p, '.'); /* get the last dot of the last component */
|
||||||
if (!e || e == p) /* no dot, or the only dot is first? */
|
if (!e || e == p) /* no dot, or the only dot is first? */
|
||||||
return rb_str_new2("");
|
return rb_str_new2("");
|
||||||
extname = rb_str_new2(e); /* keep the dot, too! */
|
extname = rb_str_new(e, chompdirsep(e) - e); /* keep the dot, too! */
|
||||||
OBJ_INFECT(extname, fname);
|
OBJ_INFECT(extname, fname);
|
||||||
return extname;
|
return extname;
|
||||||
}
|
}
|
||||||
|
@ -1791,6 +1814,7 @@ static VALUE
|
||||||
rb_file_s_split(klass, path)
|
rb_file_s_split(klass, path)
|
||||||
VALUE klass, path;
|
VALUE klass, path;
|
||||||
{
|
{
|
||||||
|
StringValue(path); /* get rid of converting twice */
|
||||||
return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
|
return rb_assoc_new(rb_file_s_dirname(Qnil, path), rb_file_s_basename(1,&path));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1853,7 +1877,7 @@ rb_file_join(ary, sep)
|
||||||
tmp = rb_obj_as_string(tmp);
|
tmp = rb_obj_as_string(tmp);
|
||||||
}
|
}
|
||||||
name = StringValuePtr(result);
|
name = StringValuePtr(result);
|
||||||
if (i > 0 && !NIL_P(sep) && strrdirsep(name) != &name[strlen(name) - 1])
|
if (i > 0 && !NIL_P(sep) && !*chompdirsep(name))
|
||||||
rb_str_buf_append(result, sep);
|
rb_str_buf_append(result, sep);
|
||||||
rb_str_buf_append(result, tmp);
|
rb_str_buf_append(result, tmp);
|
||||||
if (OBJ_TAINTED(tmp)) taint = 1;
|
if (OBJ_TAINTED(tmp)) taint = 1;
|
||||||
|
@ -2507,10 +2531,10 @@ static int
|
||||||
is_absolute_path(path)
|
is_absolute_path(path)
|
||||||
const char *path;
|
const char *path;
|
||||||
{
|
{
|
||||||
#if defined DOSISH_DRIVE_LETTER || defined __CYGWIN__
|
#ifdef DOSISH_DRIVE_LETTER
|
||||||
if (ISALPHA(path[0]) && path[1] == ':' && isdirsep(path[2])) return 1;
|
if (ISALPHA(path[0]) && path[1] == ':' && isdirsep(path[2])) return 1;
|
||||||
#endif
|
#endif
|
||||||
#if defined DOSISH || defined __CYGWIN__
|
#ifdef DOSISH_UNC
|
||||||
if (isdirsep(path[0]) && isdirsep(path[1])) return 1;
|
if (isdirsep(path[0]) && isdirsep(path[1])) return 1;
|
||||||
#endif
|
#endif
|
||||||
#ifndef DOSISH
|
#ifndef DOSISH
|
||||||
|
@ -2817,7 +2841,7 @@ Init_File()
|
||||||
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
|
rb_define_singleton_method(rb_cFile, "split", rb_file_s_split, 1);
|
||||||
rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
|
rb_define_singleton_method(rb_cFile, "join", rb_file_s_join, -2);
|
||||||
|
|
||||||
#if defined DOSISH && !defined __CYGWIN__
|
#ifdef DOSISH
|
||||||
rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_str_new2("\\")));
|
rb_define_const(rb_cFile, "ALT_SEPARATOR", rb_obj_freeze(rb_str_new2("\\")));
|
||||||
#else
|
#else
|
||||||
rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
|
rb_define_const(rb_cFile, "ALT_SEPARATOR", Qnil);
|
||||||
|
|
Loading…
Add table
Reference in a new issue