Index: libjava/java/io/File.java =================================================================== RCS file: /cvsroot/gcc/gcc/libjava/java/io/File.java,v retrieving revision 1.37 diff -u -B -c -3 -p -r1.37 File.java *** libjava/java/io/File.java 22 Oct 2003 08:47:12 -0000 1.37 --- libjava/java/io/File.java 27 Nov 2003 15:03:48 -0000 *************** public class File implements Serializabl *** 319,326 **** while (p.charAt(dupIndex) == separatorChar) { dupIndex++; ! if (dupIndex == plen) return newpath.toString(); } newpath.append(separatorChar); last = dupIndex; --- 319,330 ---- while (p.charAt(dupIndex) == separatorChar) { dupIndex++; ! if (dupIndex == plen) { ! // In the case of the p == "//", "///", ... ! if (last == 0) ! newpath.append(separatorChar); return newpath.toString(); + } } newpath.append(separatorChar); last = dupIndex; *************** public class File implements Serializabl *** 399,404 **** --- 403,414 ---- { if (isAbsolute()) return path; + + // special handling for the empty path to avoid a trailing + // separator char + if (path.length () == 0) + return System.getProperty ("user.dir"); + else if (separatorChar == '\\' && path.length() > 0 && path.charAt (0) == '\\') { Index: libjava/java/io/natFileDescriptorPosix.cc =================================================================== RCS file: /cvsroot/gcc/gcc/libjava/java/io/natFileDescriptorPosix.cc,v retrieving revision 1.29 diff -u -B -c -3 -p -r1.29 natFileDescriptorPosix.cc *** libjava/java/io/natFileDescriptorPosix.cc 26 Jul 2003 00:40:50 -0000 1.29 --- libjava/java/io/natFileDescriptorPosix.cc 27 Nov 2003 15:03:48 -0000 *************** details. */ *** 44,49 **** --- 44,68 ---- #define NO_FSYNC_MESSAGE "sync unsupported" + #define FILENAME_ENCODING_UTF8 0 + #if FILENAME_ENCODING_UTF8 + #define DEFINE_BUF_AND_TOTAL() \ + char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); \ + jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); \ + buf[total] = '\0' + #else + #define DEFINE_BUF_AND_TOTAL() \ + jsize total = 0; char * buf = NULL; \ + { \ + jbyteArray byteArray = path->getBytes (); \ + total = byteArray->length; \ + buf = (char *) __builtin_alloca (total + 1); \ + memcpy (buf, elements (byteArray), total); \ + } \ + buf[total] = '\0' + #endif + + void java::io::FileDescriptor::init (void) { *************** java::io::FileDescriptor::sync (void) *** 75,83 **** jint java::io::FileDescriptor::open (jstring path, jint jflags) { ! char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; int flags = 0; #ifdef O_BINARY flags |= O_BINARY; --- 94,103 ---- jint java::io::FileDescriptor::open (jstring path, jint jflags) { ! DEFINE_BUF_AND_TOTAL(); ! //char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1); ! //jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! //buf[total] = '\0'; int flags = 0; #ifdef O_BINARY flags |= O_BINARY; Index: libjava/java/io/natFilePosix.cc =================================================================== RCS file: /cvsroot/gcc/gcc/libjava/java/io/natFilePosix.cc,v retrieving revision 1.5 diff -u -B -c -3 -p -r1.5 natFilePosix.cc *** libjava/java/io/natFilePosix.cc 12 Sep 2003 01:08:18 -0000 1.5 --- libjava/java/io/natFilePosix.cc 27 Nov 2003 15:03:48 -0000 *************** details. */ *** 36,47 **** #include #include jboolean java::io::File::_access (jint query) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; JvAssert (query == READ || query == WRITE || query == EXISTS); #ifdef HAVE_ACCESS int mode; --- 36,83 ---- #include #include + #define FILENAME_ENCODING_UTF8 0 + #if FILENAME_ENCODING_UTF8 + #define DEFINE_BUF_AND_TOTAL() \ + char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); \ + jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); \ + buf[total] = '\0' + + #define NEW_STRING(buf) JvNewStringUTF (buf) + + #else + + #define DEFINE_BUF_AND_TOTAL() \ + jsize total = 0; char * buf = NULL; \ + { \ + jbyteArray byteArray = path->getBytes (); \ + total = byteArray->length; \ + buf = (char *) __builtin_alloca (total + 1); \ + memcpy (buf, elements (byteArray), total); \ + } \ + buf[total] = '\0' + + #define NEW_STRING(buf) newString (buf) + + static inline jstring + newString (char * buf) + { + size_t len = strlen (buf); + jbyteArray byteArray = JvNewByteArray (len); + memcpy (elements (byteArray), buf, len); + return new ::java::lang::String (byteArray); + } + + #endif + + jboolean java::io::File::_access (jint query) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; JvAssert (query == READ || query == WRITE || query == EXISTS); #ifdef HAVE_ACCESS int mode; *************** java::io::File::_stat (jint query) *** 64,72 **** return getName()->charAt(0) == '.'; #ifdef HAVE_STAT ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; struct stat sb; if (::stat (buf, &sb)) --- 100,109 ---- return getName()->charAt(0) == '.'; #ifdef HAVE_STAT ! DEFINE_BUF_AND_TOTAL(); ! //char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! //jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! //buf[total] = '\0'; struct stat sb; if (::stat (buf, &sb)) *************** java::io::File::_stat (jint query) *** 83,91 **** jlong java::io::File::attr (jint query) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; #ifdef HAVE_STAT struct stat sb; --- 120,129 ---- jlong java::io::File::attr (jint query) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; #ifdef HAVE_STAT struct stat sb; *************** java::io::File::attr (jint query) *** 104,194 **** jstring java::io::File::getCanonicalPath (void) { ! // We use `+2' here because we might need to use `.' for our special ! // case. ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 2); ! char buf2[MAXPATHLEN]; ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // Special case: treat "" the same as ".". ! if (total == 0) ! buf[total++] = '.'; buf[total] = '\0'; #ifdef HAVE_REALPATH ! if (realpath (buf, buf2) == NULL) ! { ! // 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 && buf2[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; ! } ! } ! buf2[out_idx] = '\0'; } ! // FIXME: what encoding to assume for file names? This affects many ! // calls. ! return JvNewStringUTF (buf2); ! #else ! return JvNewStringUTF (buf); ! #endif } jboolean --- 142,310 ---- jstring java::io::File::getCanonicalPath (void) { ! // canonicalize the path in three steps: ! // 1.: make the path absolute ! // 2.: use realpath to canonicalize the longest possible part of ! // the path ! // 3.: perform pure textual transformations to remove ! // "." and ".." components from the rest. ! // Note: redundant separator chars and trailing separator chars ! // are removed by the normalizePath-method (implemented in Java)). ! ! jsize total = 0; ! char *buf = NULL; ! ! #if FILENAME_ENCODING_UTF8 ! size_t bufSize = JvGetStringUTFLength (path) + 1; ! jstring userPath = NULL; ! if (! isAbsolute ()) { ! userPath = ::java::lang::System::getProperty (JvNewStringUTF ("user.dir")); ! // +1, because we might need an additional separator byte ! bufSize += JvGetStringUTFLength (userPath) +1 ; ! } ! ! buf = (char *) __builtin_alloca (bufSize); ! ! if (! isAbsolute ()) { ! total = JvGetStringUTFRegion (userPath, 0, userPath->length(), buf); ! if (buf[total - 1] != '/') ! buf[total++] = '/'; // there is enough space, see above ! } ! ! total += JvGetStringUTFRegion (path, 0, path->length(), buf+total); ! #else ! jbyteArray byteArrayBuf = path->getBytes (); ! size_t bufSize = byteArrayBuf->length + 1; ! jbyteArray byteArrayUserdir = NULL; ! if (! isAbsolute ()) { ! byteArrayUserdir = ::java::lang::System::getProperty (JvNewStringUTF ("user.dir"))->getBytes (); ! // +1, because we might need an additional separator byte ! bufSize += byteArrayUserdir->length + 1; ! } ! ! buf = (char *) __builtin_alloca (bufSize); \ ! if (! isAbsolute ()) { ! total = byteArrayUserdir->length; ! memcpy (buf, elements (byteArrayUserdir), total); ! if (buf[total - 1] != '/') ! buf[total++] = '/'; // there is enough space, see above ! } ! memcpy (buf+total, elements (byteArrayBuf), byteArrayBuf->length); ! total += byteArrayBuf->length; + #endif buf[total] = '\0'; + // now buf contains an absolute path. + //fprintf(stderr, "After stage 1: '%s'\n", buf ); + + // remove symlinks #ifdef HAVE_REALPATH ! char * rest = NULL; ! char buf2[MAXPATHLEN]; ! while(realpath (buf, buf2) == NULL) { ! // The spec allows a different result if the file does not exist ! // In this case, we should not thow an exception. ! if (! ( errno == ENOENT || errno == ENOTDIR || errno == EACCES)) ! throw new IOException (JvNewStringLatin1 (strerror (errno))); ! ! char * p = strrchr(buf,'/'); ! if (rest) ! *rest = '/'; ! if (p == buf || p == NULL) { ! goto stage3; ! } ! rest = p; ! *rest = '\0'; ! } ! //fprintf(stderr, "In stage 2, buf: '%s'\n", buf ); ! ! // now buf2 contains a canonicalized first part and rest may point to ! // the rest. ! if (rest) { ! *rest = '/'; ! //fprintf(stderr, "In stage 2, rest: '%s'\n", rest ); ! total = strlen(buf2); ! if (buf2[total-1] == '/') ! rest++; ! if (total + strlen (rest) >= MAXPATHLEN) { ! errno = ENAMETOOLONG; ! throw new IOException (JvNewStringLatin1 (strerror (errno))); ! } ! strcpy (buf2+total, rest); ! } ! buf = buf2; ! ! #endif ! stage3: ! //fprintf(stderr, "After stage 2: '%s'\n", buf ); ! ! // Now perform textual transformations on buf ! char *left; char *right; char *p; ! left=buf; ! while( *left == '/' ) { ! //fprintf(stderr, "In stage 3, new left: '%s'\n", left ); ! ! right = left; ! ! while(*right == '/') { ! //fprintf(stderr, "In stage 3, new right: '%s'\n", right ); ! // multiple '/' or trailing '/' ! if (right[1] == '/' || right[1] == '\0') { ! right++; ! continue; ! } ! ! // single '.' ! if (right[1] == '.' && ( right[2] == '/' || right[2] == '\0' )) { ! right+=2; ! continue; ! } ! ! // double '..' ! if (right[1] == '.' && right[2] == '.' && ! ( right[3] == '/' || right[3] == '\0' )) { ! right+=3; ! // move left one component back ! if (left > buf) { ! do { ! left--; ! } while (*left != '/'); // will terminate, because *buf == '/' } + continue; + } + + // no elements to skip + break; + } + + // move the string + if( right != left ) { + p=left; + while (*right) { + *p++ = *right++; + } + // reserve the first '/' + if (p > buf) + *p = *right; else ! p[1] = '\0'; ! } ! // advance to the next component ! while(*left) { ! left++; ! if( *left == '/' ) ! break; } + } + + // Now buf contains a normalized path without '.' or '..' + // components + //fprintf(stderr, "After stage 3: '%s'\n", buf ); ! return NEW_STRING (buf); } jboolean *************** java::io::File::performList (java::io::F *** 205,213 **** /* Some systems have dirent.h, but no directory reading functions like opendir. */ #if defined(HAVE_DIRENT_H) && defined(HAVE_OPENDIR) ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; DIR *dir = opendir (buf); if (! dir) --- 321,330 ---- /* Some systems have dirent.h, but no directory reading functions like opendir. */ #if defined(HAVE_DIRENT_H) && defined(HAVE_OPENDIR) ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; DIR *dir = opendir (buf); if (! dir) *************** java::io::File::performList (java::io::F *** 229,235 **** || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; ! jstring name = JvNewStringUTF (d->d_name); if (filter && ! filter->accept(this, name)) continue; --- 346,352 ---- || (d->d_name[1] == '.' && d->d_name[2] == '\0'))) continue; ! jstring name = NEW_STRING (d->d_name); if (filter && ! filter->accept(this, name)) continue; *************** java::io::File::performList (java::io::F *** 258,266 **** jboolean java::io::File::performMkdir (void) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; #ifdef HAVE_MKDIR return ::mkdir (buf, 0755) == 0; --- 375,384 ---- jboolean java::io::File::performMkdir (void) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; #ifdef HAVE_MKDIR return ::mkdir (buf, 0755) == 0; *************** java::io::File::performMkdir (void) *** 272,280 **** jboolean java::io::File::performSetReadOnly (void) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; #if defined (HAVE_STAT) && defined (HAVE_CHMOD) struct stat sb; --- 390,399 ---- jboolean java::io::File::performSetReadOnly (void) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; #if defined (HAVE_STAT) && defined (HAVE_CHMOD) struct stat sb; *************** java::io::File::performListRoots () *** 303,314 **** jboolean java::io::File::performRenameTo (File *dest) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; char *buf2 = (char *) __builtin_alloca (JvGetStringUTFLength (dest->path) + 1); total = JvGetStringUTFRegion (dest->path, 0, dest->path->length(), buf2); buf2[total] = '\0'; #ifdef HAVE_RENAME --- 422,444 ---- jboolean java::io::File::performRenameTo (File *dest) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; ! #if FILENAME_ENCODING_UTF8 char *buf2 = (char *) __builtin_alloca (JvGetStringUTFLength (dest->path) + 1); total = JvGetStringUTFRegion (dest->path, 0, dest->path->length(), buf2); + #else + char *buf2 = NULL; + { + jbyteArray byteArray = path->getBytes (); + total = byteArray->length; + buf2 = (char *) __builtin_alloca (total + 1); + memcpy (buf2, elements (byteArray), total); + } + #endif buf2[total] = '\0'; #ifdef HAVE_RENAME *************** java::io::File::performSetLastModified ( *** 324,332 **** #ifdef HAVE_UTIME utimbuf tb; ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; tb.actime = time / 1000; tb.modtime = time / 1000; --- 454,463 ---- #ifdef HAVE_UTIME utimbuf tb; ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; tb.actime = time / 1000; tb.modtime = time / 1000; *************** java::io::File::performSetLastModified ( *** 339,347 **** jboolean java::io::File::performCreate (void) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; int fd = ::open (buf, O_CREAT | O_EXCL, 0644); --- 470,479 ---- jboolean java::io::File::performCreate (void) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; int fd = ::open (buf, O_CREAT | O_EXCL, 0644); *************** java::io::File::performCreate (void) *** 361,369 **** jboolean java::io::File::performDelete (void) { ! char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! buf[total] = '\0'; #ifdef HAVE_UNLINK #ifdef HAVE_RMDIR --- 493,502 ---- jboolean java::io::File::performDelete (void) { ! DEFINE_BUF_AND_TOTAL(); ! // char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1); ! // jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf); ! // buf[total] = '\0'; #ifdef HAVE_UNLINK #ifdef HAVE_RMDIR