summaryrefslogtreecommitdiffstats
path: root/libjava/classpath/native/jni/java-io
diff options
context:
space:
mode:
Diffstat (limited to 'libjava/classpath/native/jni/java-io')
-rw-r--r--libjava/classpath/native/jni/java-io/Makefile.in10
-rw-r--r--libjava/classpath/native/jni/java-io/java_io_VMFile.c236
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 */
+}
OpenPOWER on IntegriCloud