[前][次][番号順一覧][スレッド一覧]

ruby-changes:4949

From: ko1@a...
Date: Sat, 17 May 2008 12:16:07 +0900 (JST)
Subject: [ruby-changes:4949] nobu - Ruby:r16442 (ruby_1_8_6, ruby_1_8_5): * file.c (file_expand_path): support for alternative data stream

nobu	2008-05-17 12:15:54 +0900 (Sat, 17 May 2008)

  New Revision: 16442

  Modified files:
    branches/ruby_1_8_5/ChangeLog
    branches/ruby_1_8_5/file.c
    branches/ruby_1_8_5/version.h
    branches/ruby_1_8_6/ChangeLog
    branches/ruby_1_8_6/file.c
    branches/ruby_1_8_6/version.h

  Log:
    * file.c (file_expand_path): support for alternative data stream
      and ignored trailing garbages of NTFS.
    
    * file.c (rb_file_s_basename): ditto.
    
    * file.c (rb_file_s_extname): ditto.


  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/ChangeLog?r1=16442&r2=16441&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/version.h?r1=16442&r2=16441&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_6/file.c?r1=16442&r2=16441&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_5/version.h?r1=16442&r2=16441&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_5/ChangeLog?r1=16442&r2=16441&diff_format=u
  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi/branches/ruby_1_8_5/file.c?r1=16442&r2=16441&diff_format=u

Index: ruby_1_8_5/ChangeLog
===================================================================
--- ruby_1_8_5/ChangeLog	(revision 16441)
+++ ruby_1_8_5/ChangeLog	(revision 16442)
@@ -1,3 +1,12 @@
+Sat May 17 12:15:48 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (file_expand_path): support for alternative data stream
+	  and ignored trailing garbages of NTFS.
+
+	* file.c (rb_file_s_basename): ditto.
+
+	* file.c (rb_file_s_extname): ditto.
+
 Mon Mar  3 23:36:41 2008  GOTOU Yuuzou  <gotoyuzo@n...>
 
 	* lib/webrick/httpservlet/filehandler.rb: should normalize path
Index: ruby_1_8_5/version.h
===================================================================
--- ruby_1_8_5/version.h	(revision 16441)
+++ ruby_1_8_5/version.h	(revision 16442)
@@ -1,15 +1,15 @@
 #define RUBY_VERSION "1.8.5"
-#define RUBY_RELEASE_DATE "2008-03-03"
+#define RUBY_RELEASE_DATE "2008-05-17"
 #define RUBY_VERSION_CODE 185
-#define RUBY_RELEASE_CODE 20080303
+#define RUBY_RELEASE_CODE 20080517
 #define RUBY_PATCHLEVEL 115
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
 #define RUBY_VERSION_TEENY 5
 #define RUBY_RELEASE_YEAR 2008
-#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 3
+#define RUBY_RELEASE_MONTH 5
+#define RUBY_RELEASE_DAY 17
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: ruby_1_8_5/file.c
===================================================================
--- ruby_1_8_5/file.c	(revision 16441)
+++ ruby_1_8_5/file.c	(revision 16442)
@@ -15,6 +15,10 @@
 #ifdef _WIN32
 #include "missing/file.h"
 #endif
+#ifdef __CYGWIN__
+#include <windows.h>
+#include <sys/cygwin.h>
+#endif
 
 #include "ruby.h"
 #include "rubyio.h"
@@ -2304,8 +2308,20 @@
 # else
 #   define CharNext(p) ((p) + 1)
 # endif
+#if defined _WIN32 || defined __CYGWIN__
+#define USE_NTFS 1
+#else
+#define USE_NTFS 0
 #endif
 
+#if USE_NTFS
+#define istrailinggabage(x) ((x) == '.' || (x) == ' ')
+#else
+#define istrailinggabage(x) 0
+#endif
+
+#endif
+
 #ifdef __CYGWIN__
 #undef DOSISH
 #define DOSISH_UNC
@@ -2441,6 +2457,30 @@
     return (char *)path;
 }
 
+#if USE_NTFS
+static char *
+ntfs_tail(const char *path)
+{
+    while (*path && *path != ':') {
+	if (istrailinggabage(*path)) {
+	    const char *last = path++;
+	    while (istrailinggabage(*path)) path++;
+	    if (!*path || *path == ':') return (char *)last;
+	}
+	else if (isdirsep(*path)) {
+	    const char *last = path++;
+	    while (isdirsep(*path)) path++;
+	    if (!*path) return (char *)last;
+	    if (*path == ':') path++;
+	}
+	else {
+	    path = CharNext(path);
+	}
+    }
+    return (char *)path;
+}
+#endif
+
 #define BUFCHECK(cond) do {\
     long bdiff = p - buf;\
     while (cond) {\
@@ -2467,7 +2507,8 @@
 file_expand_path(fname, dname, result)
     VALUE fname, dname, result;
 {
-    char *s, *buf, *b, *p, *pend, *root;
+    const char *s, *b;
+    char *buf, *p, *pend, *root;
     long buflen, dirlen;
     int tainted;
 
@@ -2608,15 +2649,21 @@
 		  case '.':
 		    if (*(s+1) == '\0' || isdirsep(*(s+1))) {
 			/* We must go back to the parent */
+			char *n;
 			*p = '\0';
-			if (!(b = strrdirsep(root))) {
+			if (!(n = strrdirsep(root))) {
 			    *p = '/';
 			}
 			else {
-			    p = b;
+			    p = n;
 			}
 			b = ++s;
 		    }
+#if USE_NTFS
+		    else {
+			do *++s; while (istrailinggabage(*s));
+		    }
+#endif
 		    break;
 		  case '/':
 #if defined DOSISH || defined __CYGWIN__
@@ -2629,6 +2676,19 @@
 		    break;
 		}
 	    }
+#if USE_NTFS
+	    else {
+		--s;
+	      case ' ': {
+		const char *e = s;
+		while (istrailinggabage(*s)) s++;
+		if (!*s) {
+		    s = e;
+		    goto endpath;
+		}
+	      }
+	    }
+#endif
 	    break;
 	  case '/':
 #if defined DOSISH || defined __CYGWIN__
@@ -2651,15 +2711,75 @@
     }
 
     if (s > b) {
+#if USE_NTFS
+      endpath:
+	if (s > b + 6 && strncasecmp(s - 6, ":$DATA", 6) == 0) {
+	    /* alias of stream */
+	    /* get rid of a bug of x64 VC++ */
+	    if (*(s-7) == ':') s -= 7;			/* prime */
+	    else if (memchr(b, ':', s - 6 - b)) s -= 6; /* alternative */
+	}
+#endif
 	BUFCHECK(bdiff + (s-b) >= buflen);
 	memcpy(++p, b, s-b);
 	p += s-b;
     }
     if (p == skiproot(buf) - 1) p++;
+    buflen = p - buf;
 
+#if USE_NTFS
+    *p = '\0';
+    if (!strpbrk(b = buf, "*?")) {
+	size_t len;
+	WIN32_FIND_DATA wfd;
+#ifdef __CYGWIN__
+	int lnk_added = 0;
+	struct stat st;
+	char w32buf[MAXPATHLEN], sep = 0;
+	p = 0;
+	if (lstat(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
+	    p = strrdirsep(buf);
+	    if (!p) p = skipprefix(buf);
+	    if (p) {
+		sep = *p;
+		*p = '\0';
+	    }
+	}
+	if (cygwin_conv_to_win32_path(buf, w32buf) == 0) {
+	    b = w32buf;
+	}
+	if (p) *p = sep;
+	else p = buf;
+	if (b == w32buf) {
+	    strlcat(w32buf, p, sizeof(w32buf));
+	    len = strlen(p);
+	    if (len > 4 && strcasecmp(p + len - 4, ".lnk") != 0) {
+		lnk_added = 1;
+		strlcat(w32buf, ".lnk", sizeof(w32buf));
+	    }
+	}
+#endif
+	HANDLE h = FindFirstFile(b, &wfd);
+	if (h != INVALID_HANDLE_VALUE) {
+	    FindClose(h);
+	    p = strrdirsep(buf);
+	    len = strlen(wfd.cFileName);
+#ifdef __CYGWIN__
+	    if (lnk_added && len > 4 &&
+		strcasecmp(wfd.cFileName + len - 4, ".lnk") == 0) {
+		len -= 4;
+	    }
+#endif
+	    if (!p) p = buf;
+	    buflen = ++p - buf + len;
+	    rb_str_resize(result, buflen);
+	    memcpy(p, wfd.cFileName, len + 1);
+	}
+    }
+#endif
+
     if (tainted) OBJ_TAINT(result);
-    RSTRING(result)->len = p - buf;
-    *p = '\0';
+    rb_str_set_len(result, buflen);
     return result;
 }
 
@@ -2703,18 +2823,21 @@
 }
 
 static int
-rmext(p, e)
+rmext(p, l1, e)
     const char *p, *e;
+    int l1;
 {
-    int l1, l2;
+    int l2;
 
     if (!e) return 0;
 
-    l1 = chompdirsep(p) - p;
     l2 = strlen(e);
     if (l2 == 2 && e[1] == '*') {
-	e = strrchr(p, *e);
-	if (!e) return 0;
+	unsigned char c = *e;
+	e = p + l1;
+	do {
+	    if (e <= p) return 0;
+	} while (*--e != c);
 	return e - p;
     }
     if (l1 < l2) return l1;
@@ -2749,7 +2872,7 @@
 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
     char *root;
 #endif
-    int f;
+    int f, n;
 
     if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
 	StringValue(fext);
@@ -2783,18 +2906,22 @@
 #endif
 #endif
     }
-    else if (!(p = strrdirsep(name))) {
-	if (NIL_P(fext) || !(f = rmext(name, StringValueCStr(fext)))) {
-	    f = chompdirsep(name) - name;
-	    if (f == RSTRING(fname)->len) return fname;
-	}
-	p = name;
-    }
     else {
-	while (isdirsep(*p)) p++; /* skip last / */
-	if (NIL_P(fext) || !(f = rmext(p, StringValueCStr(fext)))) {
-	    f = chompdirsep(p) - p;
+	if (!(p = strrdirsep(name))) {
+	    p = name;
 	}
+	else {
+	    while (isdirsep(*p)) p++; /* skip last / */
+	}
+#if USE_NTFS
+	n = ntfs_tail(p) - p;
+#else
+	n = chompdirsep(p) - p;
+#endif
+	if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
+	    f = n;
+	}
+	if (f == RSTRING_LEN(fname)) return fname;
     }
     basename = rb_str_new(p, f);
     OBJ_INFECT(basename, fname);
@@ -2869,22 +2996,49 @@
 rb_file_s_extname(klass, fname)
     VALUE klass, fname;
 {
-    char *name, *p, *e;
+    const char *name, *p, *e;
     VALUE extname;
 
     name = StringValueCStr(fname);
     p = strrdirsep(name);	/* get the last path component */
     if (!p)
- 	p = name;
+	p = name;
     else
- 	p++;
- 
-     e = strrchr(p, '.');	/* get the last dot of the last component */
-     if (!e || e == p || !e[1])	/* no dot, or the only dot is first or end? */
-	 return rb_str_new2("");
-     extname = rb_str_new(e, chompdirsep(e) - e);	/* keep the dot, too! */
-     OBJ_INFECT(extname, fname);
-     return extname;
+	name = ++p;
+
+    e = 0;
+    while (*p) {
+	if (*p == '.' || istrailinggabage(*p)) {
+#if USE_NTFS
+	    const char *last = p++, *dot = last;
+	    while (istrailinggabage(*p)) {
+		if (*p == '.') dot = p;
+		p++;
+	    }
+	    if (!*p || *p == ':') {
+		p = last;
+		break;
+	    }
+	    e = dot;
+	    continue;
+#else
+	    e = p;	  /* get the last dot of the last component */
+#endif
+	}
+#if USE_NTFS
+	else if (*p == ':') {
+	    break;
+	}
+#endif
+	else if (isdirsep(*p))
+	    break;
+	p = CharNext(p);
+    }
+    if (!e || e == name || e+1 == p)	/* no dot, or the only dot is first or end? */
+	return rb_str_new(0, 0);
+    extname = rb_str_new(e, p - e);	/* keep the dot, too! */
+    OBJ_INFECT(extname, fname);
+    return extname;
 }
 
 /*
Index: ruby_1_8_6/ChangeLog
===================================================================
--- ruby_1_8_6/ChangeLog	(revision 16441)
+++ ruby_1_8_6/ChangeLog	(revision 16442)
@@ -1,3 +1,12 @@
+Sat May 17 12:15:48 2008  Nobuyoshi Nakada  <nobu@r...>
+
+	* file.c (file_expand_path): support for alternative data stream
+	  and ignored trailing garbages of NTFS.
+
+	* file.c (rb_file_s_basename): ditto.
+
+	* file.c (rb_file_s_extname): ditto.
+
 Mon Mar  3 23:34:13 2008  GOTOU Yuuzou  <gotoyuzo@n...>
 
 	* lib/webrick/httpservlet/filehandler.rb: should normalize path
Index: ruby_1_8_6/version.h
===================================================================
--- ruby_1_8_6/version.h	(revision 16441)
+++ ruby_1_8_6/version.h	(revision 16442)
@@ -1,15 +1,15 @@
 #define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2008-03-03"
+#define RUBY_RELEASE_DATE "2008-05-17"
 #define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20080303
+#define RUBY_RELEASE_CODE 20080517
 #define RUBY_PATCHLEVEL 114
 
 #define RUBY_VERSION_MAJOR 1
 #define RUBY_VERSION_MINOR 8
 #define RUBY_VERSION_TEENY 6
 #define RUBY_RELEASE_YEAR 2008
-#define RUBY_RELEASE_MONTH 3
-#define RUBY_RELEASE_DAY 3
+#define RUBY_RELEASE_MONTH 5
+#define RUBY_RELEASE_DAY 17
 
 #ifdef RUBY_EXTERN
 RUBY_EXTERN const char ruby_version[];
Index: ruby_1_8_6/file.c
===================================================================
--- ruby_1_8_6/file.c	(revision 16441)
+++ ruby_1_8_6/file.c	(revision 16442)
@@ -15,6 +15,10 @@
 #ifdef _WIN32
 #include "missing/file.h"
 #endif
+#ifdef __CYGWIN__
+#include <windows.h>
+#include <sys/cygwin.h>
+#endif
 
 #include "ruby.h"
 #include "rubyio.h"
@@ -2310,8 +2314,20 @@
 # else
 #   define CharNext(p) ((p) + 1)
 # endif
+#if defined _WIN32 || defined __CYGWIN__
+#define USE_NTFS 1
+#else
+#define USE_NTFS 0
 #endif
 
+#if USE_NTFS
+#define istrailinggabage(x) ((x) == '.' || (x) == ' ')
+#else
+#define istrailinggabage(x) 0
+#endif
+
+#endif
+
 #ifdef __CYGWIN__
 #undef DOSISH
 #define DOSISH_UNC
@@ -2454,6 +2470,30 @@
     return chompdirsep(path);
 }
 
+#if USE_NTFS
+static char *
+ntfs_tail(const char *path)
+{
+    while (*path && *path != ':') {
+	if (istrailinggabage(*path)) {
+	    const char *last = path++;
+	    while (istrailinggabage(*path)) path++;
+	    if (!*path || *path == ':') return (char *)last;
+	}
+	else if (isdirsep(*path)) {
+	    const char *last = path++;
+	    while (isdirsep(*path)) path++;
+	    if (!*path) return (char *)last;
+	    if (*path == ':') path++;
+	}
+	else {
+	    path = CharNext(path);
+	}
+    }
+    return (char *)path;
+}
+#endif
+
 #define BUFCHECK(cond) do {\
     long bdiff = p - buf;\
     while (cond) {\
@@ -2480,7 +2520,8 @@
 file_expand_path(fname, dname, result)
     VALUE fname, dname, result;
 {
-    char *s, *buf, *b, *p, *pend, *root;
+    const char *s, *b;
+    char *buf, *p, *pend, *root;
     long buflen, dirlen;
     int tainted;
 
@@ -2621,15 +2662,21 @@
 		  case '.':
 		    if (*(s+1) == '\0' || isdirsep(*(s+1))) {
 			/* We must go back to the parent */
+			char *n;
 			*p = '\0';
-			if (!(b = strrdirsep(root))) {
+			if (!(n = strrdirsep(root))) {
 			    *p = '/';
 			}
 			else {
-			    p = b;
+			    p = n;
 			}
 			b = ++s;
 		    }
+#if USE_NTFS
+		    else {
+			do *++s; while (istrailinggabage(*s));
+		    }
+#endif
 		    break;
 		  case '/':
 #if defined DOSISH || defined __CYGWIN__
@@ -2642,6 +2689,19 @@
 		    break;
 		}
 	    }
+#if USE_NTFS
+	    else {
+		--s;
+	      case ' ': {
+		const char *e = s;
+		while (istrailinggabage(*s)) s++;
+		if (!*s) {
+		    s = e;
+		    goto endpath;
+		}
+	      }
+	    }
+#endif
 	    break;
 	  case '/':
 #if defined DOSISH || defined __CYGWIN__
@@ -2664,15 +2724,75 @@
     }
 
     if (s > b) {
+#if USE_NTFS
+      endpath:
+	if (s > b + 6 && strncasecmp(s - 6, ":$DATA", 6) == 0) {
+	    /* alias of stream */
+	    /* get rid of a bug of x64 VC++ */
+	    if (*(s-7) == ':') s -= 7;			/* prime */
+	    else if (memchr(b, ':', s - 6 - b)) s -= 6; /* alternative */
+	}
+#endif
 	BUFCHECK(bdiff + (s-b) >= buflen);
 	memcpy(++p, b, s-b);
 	p += s-b;
     }
     if (p == skiproot(buf) - 1) p++;
+    buflen = p - buf;
 
+#if USE_NTFS
+    *p = '\0';
+    if (!strpbrk(b = buf, "*?")) {
+	size_t len;
+	WIN32_FIND_DATA wfd;
+#ifdef __CYGWIN__
+	int lnk_added = 0;
+	struct stat st;
+	char w32buf[MAXPATHLEN], sep = 0;
+	p = 0;
+	if (lstat(buf, &st) == 0 && S_ISLNK(st.st_mode)) {
+	    p = strrdirsep(buf);
+	    if (!p) p = skipprefix(buf);
+	    if (p) {
+		sep = *p;
+		*p = '\0';
+	    }
+	}
+	if (cygwin_conv_to_win32_path(buf, w32buf) == 0) {
+	    b = w32buf;
+	}
+	if (p) *p = sep;
+	else p = buf;
+	if (b == w32buf) {
+	    strlcat(w32buf, p, sizeof(w32buf));
+	    len = strlen(p);
+	    if (len > 4 && strcasecmp(p + len - 4, ".lnk") != 0) {
+		lnk_added = 1;
+		strlcat(w32buf, ".lnk", sizeof(w32buf));
+	    }
+	}
+#endif
+	HANDLE h = FindFirstFile(b, &wfd);
+	if (h != INVALID_HANDLE_VALUE) {
+	    FindClose(h);
+	    p = strrdirsep(buf);
+	    len = strlen(wfd.cFileName);
+#ifdef __CYGWIN__
+	    if (lnk_added && len > 4 &&
+		strcasecmp(wfd.cFileName + len - 4, ".lnk") == 0) {
+		len -= 4;
+	    }
+#endif
+	    if (!p) p = buf;
+	    buflen = ++p - buf + len;
+	    rb_str_resize(result, buflen);
+	    memcpy(p, wfd.cFileName, len + 1);
+	}
+    }
+#endif
+
     if (tainted) OBJ_TAINT(result);
-    RSTRING(result)->len = p - buf;
-    *p = '\0';
+    rb_str_set_len(result, buflen);
     return result;
 }
 
@@ -2716,18 +2836,21 @@
 }
 
 static int
-rmext(p, e)
+rmext(p, l1, e)
     const char *p, *e;
+    int l1;
 {
-    int l1, l2;
+    int l2;
 
     if (!e) return 0;
 
-    l1 = chompdirsep(p) - p;
     l2 = strlen(e);
     if (l2 == 2 && e[1] == '*') {
-	e = strrchr(p, *e);
-	if (!e) return 0;
+	unsigned char c = *e;
+	e = p + l1;
+	do {
+	    if (e <= p) return 0;
+	} while (*--e != c);
 	return e - p;
     }
     if (l1 < l2) return l1;
@@ -2762,7 +2885,7 @@
 #if defined DOSISH_DRIVE_LETTER || defined DOSISH_UNC
     char *root;
 #endif
-    int f;
+    int f, n;
 
     if (rb_scan_args(argc, argv, "11", &fname, &fext) == 2) {
 	StringValue(fext);
@@ -2796,18 +2919,22 @@
 #endif
 #endif
     }
-    else if (!(p = strrdirsep(name))) {
-	if (NIL_P(fext) || !(f = rmext(name, StringValueCStr(fext)))) {
-	    f = chompdirsep(name) - name;
-	    if (f == RSTRING(fname)->len) return fname;
-	}
-	p = name;
-    }
     else {
-	while (isdirsep(*p)) p++; /* skip last / */
-	if (NIL_P(fext) || !(f = rmext(p, StringValueCStr(fext)))) {
-	    f = chompdirsep(p) - p;
+	if (!(p = strrdirsep(name))) {
+	    p = name;
 	}
+	else {
+	    while (isdirsep(*p)) p++; /* skip last / */
+	}
+#if USE_NTFS
+	n = ntfs_tail(p) - p;
+#else
+	n = chompdirsep(p) - p;
+#endif
+	if (NIL_P(fext) || !(f = rmext(p, n, StringValueCStr(fext)))) {
+	    f = n;
+	}
+	if (f == RSTRING_LEN(fname)) return fname;
     }
     basename = rb_str_new(p, f);
     OBJ_INFECT(basename, fname);
@@ -2883,22 +3010,49 @@
 rb_file_s_extname(klass, fname)
     VALUE klass, fname;
 {
-    char *name, *p, *e;
+    const char *name, *p, *e;
     VALUE extname;
 
     name = StringValueCStr(fname);
     p = strrdirsep(name);	/* get the last path component */
     if (!p)
- 	p = name;
+	p = name;
     else
- 	p++;
- 
-     e = strrchr(p, '.');	/* get the last dot of the last component */
-     if (!e || e == p || !e[1])	/* no dot, or the only dot is first or end? */
-	 return rb_str_new2("");
-     extname = rb_str_new(e, chompdirsep(e) - e);	/* keep the dot, too! */
-     OBJ_INFECT(extname, fname);
-     return extname;
+	name = ++p;
+
+    e = 0;
+    while (*p) {
+	if (*p == '.' || istrailinggabage(*p)) {
+#if USE_NTFS
+	    const char *last = p++, *dot = last;
+	    while (istrailinggabage(*p)) {
+		if (*p == '.') dot = p;
+		p++;
+	    }
+	    if (!*p || *p == ':') {
+		p = last;
+		break;
+	    }
+	    e = dot;
+	    continue;
+#else
+	    e = p;	  /* get the last dot of the last component */
+#endif
+	}
+#if USE_NTFS
+	else if (*p == ':') {
+	    break;
+	}
+#endif
+	else if (isdirsep(*p))
+	    break;
+	p = CharNext(p);
+    }
+    if (!e || e == name || e+1 == p)	/* no dot, or the only dot is first or end? */
+	return rb_str_new(0, 0);
+    extname = rb_str_new(e, p - e);	/* keep the dot, too! */
+    OBJ_INFECT(extname, fname);
+    return extname;
 }
 
 /*

--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]