--------_3B4C38AAECFA033D3FE0_MULTIPART_MIXED_
Content-Type: text/plain; charset="ISO-2022-JP"
Content-Transfer-Encoding: 7bit

こんにちは、なかむら(う)です。

Patrick Cheng氏から下記のようなパッチを頂いているので転送し
ます。

At Tue, 10 Jul 2001 00:30:49 -0700,
"Patrick Cheng" <pcyc / hotmail.com> wrote:
> Hello,
> I have made some changes to the File class to handle DOSISH file name 
> better, namely:
> 
> - basname() and dirname() can split using backslash
> - expand_path() to handle drive letter better.
> 
> hopefully, some of it you might find it useful.
> 
> Patrick Cheng

あとUNC対応が必要?
# マルチバイト対応は... まぁ「置き」ですかねぇ。

では。

--
U.Nakamura <usa / osb.att.ne.jp>

--------_3B4C38AAECFA033D3FE0_MULTIPART_MIXED_
Content-Type: text/plain; format="flowed"; name="file.patch"
Content-Disposition: attachment;
 filenameile.patch"
Content-Transfer-Encoding: 8bit

--- file.c	Tue Jul 10 00:05:49 2001
+++ new/file.c	Mon Jul  9 23:56:05 2001
@@ -75,6 +75,9 @@
static VALUE rb_cStat;

static int
+is_absolute_path(path);
+
+static int
apply2files(func, vargs, arg)
     int (*func)();
     VALUE vargs;
@@ -1345,14 +1348,62 @@
	}
     }
#if defined DOSISH
-    /* skip drive letter */
-    else if (ISALPHA(s[0]) && s[1] ':' && isdirsep(s[2])) {
-	while (*s && !isdirsep(*s)) {
-	    *p++  s++;
-	}
+    else if (ISALPHA(s[0]) && s[1] ':') {
+        if (isdirsep(s[2])) {
+            /* specified drive letter, and full path */
+            /* skip drive letter */
+            while (*s && !isdirsep(*s)) {
+                *p++  s++;
+            }
+        }
+       else {
+            /* specified drive, but not full path */
+            char drive[3];
+            char oldcwd[MAXPATHLEN+1];
+
+            drive[0]  s++;
+            drive[1]  s++;
+            drive[2]  \0';
+
+            /* the only way that I know to get the current directory
+               of a particular drive is to change chdir() to that drive,
+               so save the old cwd before chdir()
+            */
+            getcwd(oldcwd, MAXPATHLEN);
+            chdir(drive);
+
+            tainted  ;
+            getcwd(buf, MAXPATHLEN);
+            p  buf[strlen(buf)];
+            if ( *s )
+            {
+                /* need to append '/' before appending the rest of the path 
*/
+                if (! isdirsep(*(p - 1))) *p++  /';
+                while (*s && !isdirsep(*s)) {
+                    *p++  s++;
+                }
+            }
+            chdir(oldcwd);
+        }
+    }
+#endif
+#if defined DOSISH && ! defined(__CYGWIN__)
+    else if (isdirsep(*s)) {
+        /* specified full path, but not drive letter */
+        /* we need to get the drive letter */
+        tainted  ;
+#ifdef HAVE_GETCWD
+        getcwd(buf, MAXPATHLEN);
+#else
+	getwd(buf);
+#endif
+        p  buf[2];
+        while (*s && !isdirsep(*s)) {
+            *p++  s++;
+        }
     }
#endif
-    else if (!isdirsep(*s)) {
+    else if (!is_absolute_path(s)) {
	if (!NIL_P(dname)) {
	    dname  b_file_s_expand_path(1, &dname);
	    if (OBJ_TAINTED(dname)) tainted  ;
@@ -1367,7 +1418,7 @@
#endif
	}
	p  buf[strlen(buf)];
-	while (p > buf && *(p - 1) '/') p--;
+	while (p > buf && isdirsep(*(p - 1))) p--;
     }
     else {
	while (*s && isdirsep(*s)) {
@@ -1418,6 +1469,13 @@

     /* Place a \0 at end. If path ends with a "/", delete it */
     if (p buf || !isdirsep(*p)) p++;
+#if defined(DOSISH)
+    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++;
+    }
+#endif
     *p  \0';

     fname  b_str_new2(buf);
@@ -1448,6 +1506,20 @@
     return 0;
}

+
+static char *
+strrdirsep(name)
+    char *name;
+{
+    char *last  ULL;
+    do {
+        if (isdirsep(*name)) last  ame;
+        name++;
+    }
+    while( *name );
+    return last;
+}
+
static VALUE
rb_file_s_basename(argc, argv)
     int argc;
@@ -1461,7 +1533,7 @@
	ext  tringValuePtr(fext);
     }
     name  tringValuePtr(fname);
-    p  trrchr(name, '/');
+    p  trrdirsep(name);
     if (!p) {
	if (NIL_P(fext) || !(f  mext(name, ext)))
	    return fname;
@@ -1488,12 +1560,16 @@
     VALUE dirname;

     name  tringValuePtr(fname);
-    p  trrchr(name, '/');
+    p  trrdirsep(name);
     if (!p) {
	return rb_str_new2(".");
     }
     if (p name)
	p++;
+#if defined(DOSISH)
+    if ( ISALPHA(name[0]) && name[1] ':' && p &name[2])
+        p++;
+#endif
     dirname  b_str_new(name, p - name);
     if (OBJ_TAINTED(fname)) OBJ_TAINT(dirname);
     return dirname;
@@ -2121,10 +2197,11 @@
is_absolute_path(path)
     const char *path;
{
+#if ! defined(DOSISH) || defined(__CYGWIN__)
     if (path[0] '/') return 1;
+#endif
# if defined DOSISH
-    if (path[0] '\\') return 1;
-    if (strlen(path) > 2 && path[1] ':') return 1;
+    if (strlen(path) > 3 && path[1] ':' && isdirsep(path[2]) ) return 1;
# endif
     return 0;
}
@@ -2155,7 +2232,7 @@
            if (p) *p  /';
	    return 0;
	}
-	s  trrchr(path, '/');
+	s  trrdirsep(path);
	if (p) *p  /';
	if (!s || s path) return 1;
	p  ;


--------_3B4C38AAECFA033D3FE0_MULTIPART_MIXED_
Content-Type: text/plain; format="flowed"; name="testfile.rb"
Content-Disposition: attachment;
 filenameestfile.rb"
Content-Transfer-Encoding: 8bit

require 'runit/testcase'
require 'runit/cui/testrunner'
require 'rbconfig'


class TestFile_basename < RUNIT::TestCase
  def test_basename_separator
    dirname  dir'
    basename  basename.txt'

    expandpath  irname + File::SEPARATOR + basename
    assert_equal ( basename, File.basename( expandpath ) )
  end

  if ! File::ALT_SEPARATOR.nil? then
    def test_basename_alt_separator
      dirname  dir'
      basename  basename.txt'

      expandpath  irname + File::ALT_SEPARATOR + basename
      assert_equal ( basename, File.basename( expandpath ) )
    end
  end
end

class TestFile_dirname < RUNIT::TestCase
  def test_dirname_separator
    dirname  dir'
    basename  basename.txt'

    expandpath  irname + File::SEPARATOR + basename
    assert_equal ( dirname, File.dirname( expandpath ) )
  end

  if ! File::ALT_SEPARATOR.nil? then
    def test_dirname_alt_separator
      dirname  dir'
      basename  basename.txt'

      expandpath  irname + File::ALT_SEPARATOR + basename
      assert_equal ( dirname, File.dirname( expandpath ) )
    end
  end

  if  ["mswin32"].include?( Config::CONFIG["host_os"]) then
    def test_dirname_dos
      assert_equal ( "c:/winnt/system32", File.dirname( 
"c:/winnt/system32/test.txt" ) )
    end
    def test_dirname_dos_root
      assert_equal ( "c:/", File.dirname( "c:/test.txt" ) )
    end
  end

  def test_dirname_root
    assert_equal ( "/", File.dirname( "/test.txt" ) )
  end

end

class TestFile_join < RUNIT::TestCase

  def test_join_root
    assert_equal ( "/test.txt", File.join( "/", "test.txt" ) )
  end
  def test_join_non_root
    assert_equal ( "/etc/test.txt", File.join( "/etc", "test.txt" ) )
  end
  def test_join_non_root_with_trailing_slash
    assert_equal ( "/etc/test.txt", File.join( "/etc/", "test.txt" ) )
  end
end

class TestFile_expand_path < RUNIT::TestCase
  if  ! ["mswin32"].include?( Config::CONFIG["host_os"]) then
    def test_expand_path_root
      assert_equal ( "/", File::expand_path( "/" ) )
    end
  end
  if  ["mswin32"].include?( Config::CONFIG["host_os"]) then
    def test_expand_path_root
      Dir::chdir( "c:/winnt/system32" )
      assert_equal ( "c:/", File::expand_path( "/" ) )
    end
    def test_expand_path_dos_root_forward_slash
      assert_equal ( "c:/", File::expand_path( "c:/" ) )
    end
    def test_expand_path_dos_root_backward_slash
      assert_equal ( "c:/", File::expand_path( "c:\\" ) )
    end
    def test_expand_path_dos_non_root_forward_slash
      assert_equal ( "c:/winnt/system32/test.txt", File::expand_path( 
"c:/winnt/system32/test.txt" ) )
    end
    def test_expand_path_dos_non_root_backward_slash
      assert_equal ( "c:/winnt/system32/test.txt", File::expand_path( 
"c:\\winnt\\system32\\test.txt" ) )
    end
    def test_expand_path_dos_drive_only
      Dir::chdir( "c:/winnt/system32" )
      assert_equal ( "c:/winnt/system32", File::expand_path( "c:" ) )
    end
    def test_expand_path_dos_drive_relative_path
      Dir::chdir( "c:/winnt/system32" )
      assert_equal ( "c:/winnt/system32/test.txt", File::expand_path( 
"c:test.txt" ) )
    end
  end
end

  suite  UNIT::TestSuite.new
  suite.add_test(TestFile_basename.suite)
  suite.add_test(TestFile_dirname.suite)
  suite.add_test(TestFile_expand_path.suite)

  # join current does not deal with trailing separator
  #suite.add_test(TestFile_join.suite)

  RUNIT::CUI::TestRunner.quiet_mode  rue
  RUNIT::CUI::TestRunner.run(suite)


--------_3B4C38AAECFA033D3FE0_MULTIPART_MIXED_--