From 645170199ca8d9f7eaa8f928519897d2d1ed709d Mon Sep 17 00:00:00 2001 From: nobu Date: Mon, 30 Jul 2001 22:41:59 +0000 Subject: [PATCH] * 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 --- ChangeLog | 10 ++++++-- file.c | 77 +++++++++++++++++++++++++++++++++---------------------- 2 files changed, 55 insertions(+), 32 deletions(-) diff --git a/ChangeLog b/ChangeLog index 3f09afa70a7d6b..cde19e45d32436 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,7 +1,13 @@ +Tue Jul 31 07:18:04 2001 Nobuyoshi Nakada + + * 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 * 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 @@ -40,7 +46,7 @@ Wed Jul 25 12:15:32 2001 WATANABE Hirofumi * file.c (rb_find_file): ditto. -Tue Jul 24 23:10:47 2001 Nobuyoshi.Nakada +Tue Jul 24 23:10:47 2001 Nobuyoshi Nakada * file.c (strrdirsep): multi-byte pathname and DOSish separater supprot. originally comes from Patrick Cheng. [new] diff --git a/file.c b/file.c index 67ad58df4d7c10..76076e47a2fc97 100644 --- a/file.c +++ b/file.c @@ -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;