diff options
Diffstat (limited to 'libjava/classpath/native/jni/java-io')
-rw-r--r-- | libjava/classpath/native/jni/java-io/Makefile.in | 10 | ||||
-rw-r--r-- | libjava/classpath/native/jni/java-io/java_io_VMFile.c | 236 |
2 files changed, 245 insertions, 1 deletions
diff --git a/libjava/classpath/native/jni/java-io/Makefile.in b/libjava/classpath/native/jni/java-io/Makefile.in index ca4b8a4728f..e997fd26039 100644 --- a/libjava/classpath/native/jni/java-io/Makefile.in +++ b/libjava/classpath/native/jni/java-io/Makefile.in @@ -112,6 +112,8 @@ CREATE_CORE_JNI_LIBRARIES_FALSE = @CREATE_CORE_JNI_LIBRARIES_FALSE@ CREATE_CORE_JNI_LIBRARIES_TRUE = @CREATE_CORE_JNI_LIBRARIES_TRUE@ CREATE_DSSI_LIBRARIES_FALSE = @CREATE_DSSI_LIBRARIES_FALSE@ CREATE_DSSI_LIBRARIES_TRUE = @CREATE_DSSI_LIBRARIES_TRUE@ +CREATE_GCONF_PEER_LIBRARIES_FALSE = @CREATE_GCONF_PEER_LIBRARIES_FALSE@ +CREATE_GCONF_PEER_LIBRARIES_TRUE = @CREATE_GCONF_PEER_LIBRARIES_TRUE@ CREATE_GTK_PEER_LIBRARIES_FALSE = @CREATE_GTK_PEER_LIBRARIES_FALSE@ CREATE_GTK_PEER_LIBRARIES_TRUE = @CREATE_GTK_PEER_LIBRARIES_TRUE@ CREATE_JNI_HEADERS_FALSE = @CREATE_JNI_HEADERS_FALSE@ @@ -132,6 +134,7 @@ CXXDEPMODE = @CXXDEPMODE@ CXXFLAGS = @CXXFLAGS@ CYGPATH_W = @CYGPATH_W@ DATE = @DATE@ +DEFAULT_PREFS_PEER = @DEFAULT_PREFS_PEER@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ ECHO_C = @ECHO_C@ @@ -162,6 +165,10 @@ FREETYPE2_CFLAGS = @FREETYPE2_CFLAGS@ FREETYPE2_LIBS = @FREETYPE2_LIBS@ GCJ = @GCJ@ GCJX = @GCJX@ +GCONF_CFLAGS = @GCONF_CFLAGS@ +GCONF_LIBS = @GCONF_LIBS@ +GDK_CFLAGS = @GDK_CFLAGS@ +GDK_LIBS = @GDK_LIBS@ GJDOC = @GJDOC@ GLIB_CFLAGS = @GLIB_CFLAGS@ GLIB_LIBS = @GLIB_LIBS@ @@ -212,6 +219,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@ PANGOFT2_CFLAGS = @PANGOFT2_CFLAGS@ PANGOFT2_LIBS = @PANGOFT2_LIBS@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PATH_TO_ESCHER = @PATH_TO_ESCHER@ PATH_TO_GLIBJ_ZIP = @PATH_TO_GLIBJ_ZIP@ PERL = @PERL@ PKG_CONFIG = @PKG_CONFIG@ @@ -232,6 +240,8 @@ USER_SPECIFIED_CLASSLIB_FALSE = @USER_SPECIFIED_CLASSLIB_FALSE@ USER_SPECIFIED_CLASSLIB_TRUE = @USER_SPECIFIED_CLASSLIB_TRUE@ USER_SPECIFIED_JAVAH_FALSE = @USER_SPECIFIED_JAVAH_FALSE@ USER_SPECIFIED_JAVAH_TRUE = @USER_SPECIFIED_JAVAH_TRUE@ +USE_ESCHER_FALSE = @USE_ESCHER_FALSE@ +USE_ESCHER_TRUE = @USE_ESCHER_TRUE@ USE_PREBUILT_GLIBJ_ZIP_FALSE = @USE_PREBUILT_GLIBJ_ZIP_FALSE@ USE_PREBUILT_GLIBJ_ZIP_TRUE = @USE_PREBUILT_GLIBJ_ZIP_TRUE@ VERSION = @VERSION@ diff --git a/libjava/classpath/native/jni/java-io/java_io_VMFile.c b/libjava/classpath/native/jni/java-io/java_io_VMFile.c index 354df04ed35..7a3fdaf43a8 100644 --- a/libjava/classpath/native/jni/java-io/java_io_VMFile.c +++ b/libjava/classpath/native/jni/java-io/java_io_VMFile.c @@ -1,5 +1,5 @@ /* java_io_VMFile.c - Native methods for java.io.File class - Copyright (C) 1998, 2004 Free Software Foundation, Inc. + Copyright (C) 1998, 2004, 2006 Free Software Foundation, Inc. This file is part of GNU Classpath. @@ -730,3 +730,237 @@ Java_java_io_VMFile_list (JNIEnv * env, jobject obj return (0); #endif /* not WITHOUT_FILESYSTEM */ } + +/*************************************************************************/ + +/* + * These two methods are used to maintain dynamically allocated + * buffers for getCanonicalPath without the overhead of calling + * realloc every time a buffer is modified. Buffers are sized + * at the smallest multiple of CHUNKSIZ that is greater than or + * equal to the desired length. The default CHUNKSIZ is 256, + * longer than most paths, so in most cases a getCanonicalPath + * will require only one malloc per buffer. + */ + +#define CHUNKLOG 8 +#define CHUNKSIZ (1 << CHUNKLOG) + +static int +nextChunkSize (int size) +{ + return ((size >> CHUNKLOG) + ((size & (CHUNKSIZ - 1)) ? 1 : 0)) << CHUNKLOG; +} + +static char * +maybeGrowBuf (JNIEnv *env, char *buf, int *size, int required) +{ + if (required > *size) + { + *size = nextChunkSize (required); + buf = JCL_realloc (env, buf, *size); + } + return buf; +} + +/*************************************************************************/ + +/* + * This method converts a path to canonical form on GNU/Posix systems. + * This involves the removal of redundant separators, references to + * "." and "..", and symbolic links. + * + * The conversion proceeds on a component-by-component basis: symbolic + * links and references to ".." are resolved as and when they occur. + * This means that if "/foo/bar" is a symbolic link to "/baz" then the + * canonical form of "/foo/bar/.." is "/" and not "/foo". + * + * In order to mimic the behaviour of proprietary JVMs, non-existant + * path components are allowed (a departure from the normal GNU system + * convention). This means that if "/foo/bar" is a symbolic link to + * "/baz", the canonical form of "/non-existant-directory/../foo/bar" + * is "/baz". + * + * Class: java_io_VMFile + * Method: toCanonicalForm + * Signature: (Ljava/lang/String)Ljava/lang/String + */ + +JNIEXPORT jstring JNICALL +Java_java_io_VMFile_toCanonicalForm (JNIEnv *env, + jclass class __attribute__ ((__unused__)), + jstring jpath) +{ +#ifndef WITHOUT_FILESYSTEM + const char *path; + char *src, *dst; + int srci, dsti; + int srcl, dstl; + int len; + int fschecks; +#if defined (HAVE_LSTAT) && defined (HAVE_READLINK) + struct stat sb; +#endif /* HAVE_LSTAT && HAVE_READLINK */ + + path = JCL_jstring_to_cstring (env, jpath); + if (path == NULL) + return NULL; + + /* It is the caller's responsibility to ensure the path is absolute. */ + if (path[0] == 0 || path[0] != '/') + { + JCL_free_cstring (env, jpath, path); + JCL_ThrowException (env, "java/lang/RuntimeException", "Not absolute"); + return NULL; + } + + len = strlen (path); + srcl = nextChunkSize (len + 1); + src = JCL_malloc (env, srcl); + if (src == NULL) + { + JCL_free_cstring (env, jpath, path); + return NULL; + } + strcpy (src, path); + JCL_free_cstring (env, jpath, path); + srci = 1; + + dstl = nextChunkSize (2); + dst = JCL_malloc (env, dstl); + if (dst == NULL) + { + JCL_free (env, src); + return NULL; + } + dst[0] = '/'; + dsti = 1; + + fschecks = JNI_TRUE; + + while (src[srci] != '\0') + { + int tmpi, dsti_save; + + /* Skip slashes. */ + while (src[srci] == '/') + srci++; + tmpi = srci; + /* Find next slash. */ + while (src[srci] != '/' && src[srci] != '\0') + srci++; + if (srci == tmpi) + /* We hit the end. */ + break; + len = srci - tmpi; + + /* Handle "." and "..". */ + if (len == 1 && src[tmpi] == '.') + continue; + if (len == 2 && src[tmpi] == '.' && src[tmpi + 1] == '.') + { + while (dsti > 1 && dst[dsti - 1] != '/') + dsti--; + if (dsti != 1) + dsti--; + /* Reenable filesystem checking if disabled, as we might + * have reversed over whatever caused the problem before. + * At least one proprietary JVM has inconsistencies because + * it does not do this. + */ + fschecks = JNI_TRUE; + continue; + } + + /* Handle real path components. */ + dst = maybeGrowBuf (env, + dst, &dstl, dsti + (dsti > 1 ? 1 : 0) + len + 1); + if (dst == NULL) + { + JCL_free (env, src); + return NULL; + } + dsti_save = dsti; + if (dsti > 1) + dst[dsti++] = '/'; + strncpy (&dst[dsti], &src[tmpi], len); + dsti += len; + if (fschecks == JNI_FALSE) + continue; + +#if defined (HAVE_LSTAT) && defined (HAVE_READLINK) + dst[dsti] = '\0'; + if (lstat (dst, &sb) == 0) + { + if (S_ISLNK (sb.st_mode)) + { + int tmpl = CHUNKSIZ; + char *tmp = JCL_malloc (env, tmpl); + if (tmp == NULL) + { + JCL_free (env, src); + JCL_free (env, dst); + return NULL; + } + + while (1) + { + tmpi = readlink (dst, tmp, tmpl); + if (tmpi < 1) + { + JCL_free (env, src); + JCL_free (env, dst); + JCL_free (env, tmp); + JCL_ThrowException (env, "java/io/IOException", + "readlink failed"); + return NULL; + } + if (tmpi < tmpl) + break; + tmpl += CHUNKSIZ; + tmp = JCL_realloc (env, tmp, tmpl); + } + + /* Prepend the link's path to src. */ + tmp = maybeGrowBuf (env, + tmp, &tmpl, tmpi + strlen (&src[srci]) + 1); + if (tmp == NULL) + { + JCL_free (env, src); + JCL_free (env, dst); + return NULL; + } + + strcpy (&tmp[tmpi], &src[srci]); + JCL_free (env, src); + src = tmp; + srcl = tmpl; + srci = 0; + + /* Either replace or append dst depending on whether the + * link is relative or absolute. + */ + dsti = src[0] == '/' ? 1 : dsti_save; + } + } + else + { + /* Something doesn't exist, or we don't have permission to + * read it, or a previous path component is a directory, or + * a symlink is looped. Whatever, we can't check the + * filesystem any more. + */ + fschecks = JNI_FALSE; + } +#endif /* HAVE_LSTAT && HAVE_READLINK */ + } + dst[dsti] = '\0'; + + jpath = (*env)->NewStringUTF (env, dst); + JCL_free (env, src); + JCL_free (env, dst); + return jpath; +#else /* not WITHOUT_FILESYSTEM */ + return NULL; +#endif /* not WITHOUT_FILESYSTEM */ +} |