1
0
Fork 0
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:
nobu 2003-02-12 14:56:45 +00:00
parent b3ec759e4b
commit 7dd303419e
2 changed files with 121 additions and 83 deletions

View file

@ -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
View file

@ -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);