* file.c (rb_file_s_expand_path): scans per path element not per

byte/character, including fix of [ruby-talk:18152] and
  multi-byte pathname support.


git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@1655 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
nobu 2001-07-30 22:41:59 +00:00
parent 67d433a5e6
commit 645170199c
2 changed files with 55 additions and 32 deletions

View File

@ -1,7 +1,13 @@
Tue Jul 31 07:18:04 2001 Nobuyoshi Nakada <nobu.nokada@softhome.net>
* file.c (rb_file_s_expand_path): scans per path element not per
byte/character, including fix of [ruby-talk:18152] and
multi-byte pathname support.
Mon Jul 30 11:12:14 2001 Amos Gouaux <amos+ruby@utdallas.edu>
* lib/net/imap.rb: added new commands for managing folder quotas
and folder ACLs.
and folder ACLs.
Fri Jul 27 18:07:27 2001 Yukihiro Matsumoto <matz@ruby-lang.org>
@ -40,7 +46,7 @@ Wed Jul 25 12:15:32 2001 WATANABE Hirofumi <eban@ruby-lang.org>
* file.c (rb_find_file): ditto.
Tue Jul 24 23:10:47 2001 Nobuyoshi.Nakada <nobu.nakada@nifty.ne.jp>
Tue Jul 24 23:10:47 2001 Nobuyoshi Nakada <nobu.nakada@nifty.ne.jp>
* file.c (strrdirsep): multi-byte pathname and DOSish separater
supprot. originally comes from Patrick Cheng. [new]

77
file.c
View File

@ -1332,7 +1332,7 @@ rb_file_s_expand_path(argc, argv)
VALUE *argv;
{
VALUE fname, dname;
char *s, *p, *sbeg, *b;
char *s, *p, *b;
char buf[MAXPATHLEN+2];
char *bend = buf + sizeof(buf) - 2;
int tainted;
@ -1340,7 +1340,7 @@ rb_file_s_expand_path(argc, argv)
rb_scan_args(argc, argv, "11", &fname, &dname);
tainted = OBJ_TAINTED(fname);
s = sbeg = StringValuePtr(fname);
s = StringValuePtr(fname);
p = buf;
if (s[0] == '~') {
if (isdirsep(s[1]) || s[1] == '\0') {
@ -1417,61 +1417,78 @@ rb_file_s_expand_path(argc, argv)
}
*p = '/';
b = s;
while (*s) {
switch (*s) {
case '.':
if (*(s+1) && (s == sbeg || isdirsep(*(s - 1)))) {
switch (*++s) {
if (b == s++) { /* beginning of path element */
switch (*s) {
case '\0':
b = s;
break;
case '.':
if (*(s+1) == '\0' || isdirsep(*(s+1))) {
/* We must go back to the parent */
if (isdirsep(*p) && p > buf) p--;
while (p > buf && !isdirsep(*p)) p--;
}
else {
*++p = '.';
do {
*++p = '.';
if (p >= bend) goto toolong;
} while (*++s == '.');
--s;
*p = '\0';
if (!(b = strrdirsep(buf))) {
*p = '/';
}
else {
p = b;
}
b = ++s;
}
break;
case '/':
#if defined DOSISH
case '\\':
#endif
if (!isdirsep(*p)) *++p = '/';
b = ++s;
break;
default:
*++p = '.'; *++p = *s; break;
/* ordinary path element, beginning don't move */
break;
}
}
else {
*++p = '.';
}
break;
case '/':
#if defined DOSISH
case '\\':
#endif
if (!isdirsep(*p)) *++p = '/'; break;
if (s > b) {
if (p + (s-b+1) >= bend) goto toolong;
memcpy(++p, b, s-b);
p += s-b;
*p = '/';
}
b = ++s;
break;
default:
b = s;
s = CharNext(s);
p = CharNext(p);
if (p + (s-b) >= bend) goto toolong;
memcpy(p, b, s-b);
continue;
break;
}
s = CharNext(s);
}
/* Place a \0 at end. If path ends with a "/", delete it */
if (p == buf || !isdirsep(*p)) p++;
*p = '\0';
if (s > b) {
if (p + (s-b) >= bend) goto toolong;
memcpy(++p, b, s-b);
p += s-b;
}
else if (p == buf) {
p++;
}
#if defined(DOSISH)
else if (ISALPHA(buf[0]) && (buf[1] == ':') && isdirsep(buf[2])) {
/* root directory needs a trailing backslash,
otherwise it mean the current directory of the drive */
if (p == (buf+2)) p++;
}
else if (isdirsep(buf[0]) && isdirsep(buf[1])) {
if (p == (buf+1)) p++;
}
#endif
fname = rb_str_new2(buf);
fname = rb_str_new(buf, p - buf);
if (tainted) OBJ_TAINT(fname);
return fname;