OSDN Git Service

* java/io/natFilePosix.cc (getCanonicalPath): Handle case where
authortromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Sep 2003 16:44:39 +0000 (16:44 +0000)
committertromey <tromey@138bc75d-0d04-0410-961f-82ee72b054a4>
Thu, 11 Sep 2003 16:44:39 +0000 (16:44 +0000)
file does not exist.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71307 138bc75d-0d04-0410-961f-82ee72b054a4

libjava/ChangeLog
libjava/java/io/natFilePosix.cc

index 1021607..8a633e6 100644 (file)
@@ -1,3 +1,8 @@
+2003-09-11  Tom Tromey  <tromey@redhat.com>
+
+       * java/io/natFilePosix.cc (getCanonicalPath): Handle case where
+       file does not exist.
+
 2003-09-10  Anthony Green  <green@redhat.com>
 
        * gnu/java/net/natPlainDatagramSocketImplWin32.cc (peekData):
index 4946cfc..a1eb1c7 100644 (file)
@@ -118,7 +118,69 @@ java::io::File::getCanonicalPath (void)
 
 #ifdef HAVE_REALPATH
   if (realpath (buf, buf2) == NULL)
-    throw new IOException (JvNewStringLatin1 (strerror (errno)));
+    {
+      // If realpath failed, we have to come up with a canonical path
+      // anyway.  We do this with purely textual manipulation.
+      // FIXME: this isn't perfect.  You can construct a case where
+      // we get a different answer from the JDK:
+      // mkdir -p /tmp/a/b/c
+      // ln -s /tmp/a/b /tmp/a/z
+      // ... getCanonicalPath("/tmp/a/z/c/nosuchfile")
+      // We will give /tmp/a/z/c/nosuchfile, while the JDK will
+      // give /tmp/a/b/c/nosuchfile.
+      int out_idx;
+      if (buf[0] != '/')
+       {
+         // Not absolute, so start with current directory.
+         if (getcwd (buf2, sizeof (buf2)) == NULL)
+           throw new IOException ();
+         out_idx = strlen (buf2);
+       }
+      else
+       {
+         buf2[0] = '/';
+         out_idx = 1;
+       } 
+      int in_idx = 0;
+      while (buf[in_idx] != '\0')
+       {
+         // Skip '/'s.
+         while (buf[in_idx] == '/')
+           ++in_idx;
+         int elt_start = in_idx;
+         // Find next '/' or end of path.
+         while (buf[in_idx] != '\0' && buf[in_idx] != '/')
+           ++in_idx;
+         if (in_idx == elt_start)
+           {
+             // An empty component means we've reached the end.
+             break;
+           }
+         int len = in_idx - elt_start;
+         if (len == 1 && buf[in_idx] == '.')
+           continue;
+         if (len == 2 && buf[in_idx] == '.' && buf[in_idx + 1] == '.')
+           {
+             // Found ".." component, lop off last part from existing
+             // buffer.
+             --out_idx;
+             while (out_idx > 0 && buf[out_idx] != '/')
+               --out_idx;
+             // Can't go up past "/".
+             if (out_idx == 0)
+               ++out_idx;
+           }
+         else
+           {
+             // Append a real path component to the output.
+             if (out_idx > 1)
+               buf2[out_idx++] = '/';
+             strncpy (&buf2[out_idx], &buf[elt_start], len);
+             out_idx += len;
+           }
+       }
+      buf[out_idx] = '\0';
+    }
 
   // FIXME: what encoding to assume for file names?  This affects many
   // calls.