summaryrefslogtreecommitdiff
path: root/libjava/java/io/natFilePosix.cc
diff options
context:
space:
mode:
authorupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
committerupstream source tree <ports@midipix.org>2015-03-15 20:14:05 -0400
commit554fd8c5195424bdbcabf5de30fdc183aba391bd (patch)
tree976dc5ab7fddf506dadce60ae936f43f58787092 /libjava/java/io/natFilePosix.cc
downloadcbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2
cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig; imported gcc-4.6.4 source tree from verified upstream tarball. downloading a git-generated archive based on the 'upstream' tag should provide you with a source tree that is binary identical to the one extracted from the above tarball. if you have obtained the source via the command 'git clone', however, do note that line-endings of files in your working directory might differ from line-endings of the respective files in the upstream repository.
Diffstat (limited to 'libjava/java/io/natFilePosix.cc')
-rw-r--r--libjava/java/io/natFilePosix.cc509
1 files changed, 509 insertions, 0 deletions
diff --git a/libjava/java/io/natFilePosix.cc b/libjava/java/io/natFilePosix.cc
new file mode 100644
index 000000000..5b6ec8458
--- /dev/null
+++ b/libjava/java/io/natFilePosix.cc
@@ -0,0 +1,509 @@
+// natFile.cc - Native part of File class for POSIX.
+
+/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2006, 2008
+ Free Software Foundation
+
+ This file is part of libgcj.
+
+This software is copyrighted work licensed under the terms of the
+Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
+details. */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <fcntl.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#include <stdlib.h>
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+#include <string.h>
+#include <utime.h>
+
+#include <gcj/cni.h>
+#include <jvm.h>
+#include <java/io/File.h>
+#include <java/io/IOException.h>
+#include <java/util/ArrayList.h>
+#include <java/lang/String.h>
+#include <java/io/FilenameFilter.h>
+#include <java/io/FileFilter.h>
+#include <java/lang/System.h>
+
+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
+ || query == EXEC);
+#ifdef HAVE_ACCESS
+ int mode;
+ if (query == READ)
+ mode = R_OK;
+ else if (query == WRITE)
+ mode = W_OK;
+ else if (query == EXISTS)
+ mode = F_OK;
+ else
+ mode = X_OK;
+ return ::access (buf, mode) == 0;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::_stat (jint query)
+{
+ if (query == ISHIDDEN)
+ 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))
+ return false;
+
+ JvAssert (query == DIRECTORY || query == ISFILE);
+ jboolean r = S_ISDIR (sb.st_mode);
+ return query == DIRECTORY ? r : ! r;
+#else
+ return false;
+#endif
+}
+
+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;
+ // FIXME: not sure about return value here.
+ if (::stat (buf, &sb))
+ return 0;
+
+ JvAssert (query == MODIFIED || query == LENGTH);
+ return query == MODIFIED ? (jlong)sb.st_mtime * 1000 : sb.st_size;
+#else
+ // There's no good choice here.
+ return 23;
+#endif
+}
+
+// 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 (char *buf, int *size, int required)
+{
+ if (required > *size)
+ {
+ *size = nextChunkSize (required);
+ buf = (char *) _Jv_Realloc (buf, *size);
+ }
+ return buf;
+}
+
+// Return a canonical representation of the pathname of this file. On
+// the GNU system 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".
+
+jstring
+java::io::File::getCanonicalPath (void)
+{
+ jstring path = getAbsolutePath ();
+
+ int len = JvGetStringUTFLength (path);
+ int srcl = nextChunkSize (len + 1);
+ char *src = (char *) _Jv_Malloc (srcl);
+ JvGetStringUTFRegion (path, 0, path->length(), src);
+ src[len] = '\0';
+ int srci = 1;
+
+ int dstl = nextChunkSize (2);
+ char *dst = (char *) _Jv_Malloc (dstl);
+ dst[0] = '/';
+ int dsti = 1;
+
+ bool fschecks = true;
+
+ while (src[srci] != '\0')
+ {
+ // Skip slashes.
+ while (src[srci] == '/')
+ srci++;
+ int 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 = true;
+ continue;
+ }
+
+ // Handle real path components.
+ dst = maybeGrowBuf (dst, &dstl, dsti + (dsti > 1 ? 1 : 0) + len + 1);
+ int dsti_save = dsti;
+ if (dsti > 1)
+ dst[dsti++] = '/';
+ strncpy (&dst[dsti], &src[tmpi], len);
+ dsti += len;
+ if (fschecks == false)
+ continue;
+
+#if defined (HAVE_LSTAT) && defined (HAVE_READLINK)
+ struct stat sb;
+ dst[dsti] = '\0';
+ if (::lstat (dst, &sb) == 0)
+ {
+ if (S_ISLNK (sb.st_mode))
+ {
+ int tmpl = CHUNKSIZ;
+ char *tmp = (char *) _Jv_Malloc (tmpl);
+
+ while (1)
+ {
+ tmpi = ::readlink (dst, tmp, tmpl);
+ if (tmpi < 1)
+ {
+ _Jv_Free (src);
+ _Jv_Free (dst);
+ _Jv_Free (tmp);
+ throw new IOException (
+ JvNewStringLatin1 ("readlink failed"));
+ }
+ if (tmpi < tmpl)
+ break;
+ tmpl += CHUNKSIZ;
+ tmp = (char *) _Jv_Realloc (tmp, tmpl);
+ }
+
+ // Prepend the link's path to src.
+ tmp = maybeGrowBuf (tmp, &tmpl, tmpi + strlen (&src[srci]) + 1);
+ strcpy(&tmp[tmpi], &src[srci]);
+ _Jv_Free (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 = false;
+ }
+#endif // HAVE_LSTAT && HAVE_READLINK
+ }
+ dst[dsti] = '\0';
+
+ // FIXME: what encoding to assume for file names? This affects many
+ // calls.
+ path = JvNewStringUTF (dst);
+ _Jv_Free (src);
+ _Jv_Free (dst);
+ return path;
+}
+
+jboolean
+java::io::File::isAbsolute (void)
+{
+ return path->length() > 0 && path->charAt(0) == '/';
+}
+
+jobjectArray
+java::io::File::performList (java::io::FilenameFilter *filter,
+ java::io::FileFilter *fileFilter,
+ java::lang::Class *result_type)
+{
+ /* 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)
+ return NULL;
+
+ java::util::ArrayList *list = new java::util::ArrayList ();
+ struct dirent *d;
+ while ((d = readdir (dir)) != NULL)
+ {
+ // Omit "." and "..".
+ if (d->d_name[0] == '.'
+ && (d->d_name[1] == '\0'
+ || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
+ continue;
+
+ jstring name = JvNewStringUTF (d->d_name);
+ if (filter && ! filter->accept(this, name))
+ continue;
+
+ if (result_type == &java::io::File::class$)
+ {
+ java::io::File *file = new java::io::File (this, name);
+ if (fileFilter && ! fileFilter->accept(file))
+ continue;
+
+ list->add(file);
+ }
+ else
+ list->add(name);
+ }
+
+ closedir (dir);
+
+ jobjectArray ret = JvNewObjectArray (list->size(), result_type, NULL);
+ list->toArray(ret);
+ return ret;
+#else /* HAVE_DIRENT_H && HAVE_OPENDIR */
+ return NULL;
+#endif /* HAVE_DIRENT_H && HAVE_OPENDIR */
+}
+
+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;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::setFilePermissions (jboolean enable,
+ jboolean ownerOnly,
+ jint permissions)
+{
+ char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
+ jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
+ buf[total] = '\0';
+ JvAssert (permissions == READ || permissions == WRITE || permissions == EXEC);
+#if defined (HAVE_STAT) && defined (HAVE_CHMOD)
+ mode_t mode = 0;
+
+ struct stat sb;
+ if (::stat (buf, &sb))
+ return false;
+
+ if (ownerOnly)
+ {
+ if (permissions == READ)
+ mode |= S_IRUSR;
+ else if (permissions == WRITE)
+ mode |= S_IWUSR;
+ else if (permissions == EXEC)
+ mode |= S_IXUSR;
+ }
+ else
+ {
+ if (permissions == READ)
+ mode |= (S_IRUSR | S_IRGRP | S_IROTH);
+ else if (permissions == WRITE)
+ mode |= (S_IWUSR | S_IWGRP | S_IWOTH);
+ else if (permissions == EXEC)
+ mode |= (S_IXUSR | S_IXGRP | S_IXOTH);
+ }
+
+ if (enable)
+ mode = sb.st_mode | mode;
+ else
+ mode = sb.st_mode & ~mode;
+
+ if (::chmod(buf, mode) < 0)
+ return false;
+ return true;
+#else
+ return false;
+#endif
+}
+
+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;
+ if (::stat (buf, &sb))
+ return false;
+
+ if (::chmod(buf, sb.st_mode & 0555))
+ return false;
+ return true;
+#else
+ return false;
+#endif
+}
+
+JArray< ::java::io::File *>*
+java::io::File::performListRoots ()
+{
+ ::java::io::File *f = new ::java::io::File (JvNewStringLatin1 ("/"));
+ JArray<java::io::File *> *unixroot
+ = reinterpret_cast <JArray<java::io::File *>*>
+ (JvNewObjectArray (1, &java::io::File::class$, f));
+ elements (unixroot) [0] = f;
+ return unixroot;
+}
+
+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
+ return ::rename (buf, buf2) == 0;
+#else
+ return false;
+#endif
+}
+
+jboolean
+java::io::File::performSetLastModified (jlong time)
+{
+#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;
+ return (::utime (buf, &tb) == 0);
+#else
+ return false;
+#endif
+}
+
+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);
+
+ if (fd < 0)
+ {
+ if (errno == EEXIST)
+ return false;
+ throw new IOException (JvNewStringLatin1 (strerror (errno)));
+ }
+ else
+ {
+ ::close (fd);
+ return true;
+ }
+}
+
+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
+ if (! ::rmdir (buf))
+ return true;
+ if (errno == ENOTDIR)
+#endif // HAVE_RMDIR
+ return ::unlink (buf) == 0;
+#endif // HAVE_UNLINK
+ return false;
+}
+
+void
+java::io::File::init_native ()
+{
+#ifdef MAXPATHLEN
+ maxPathLen = MAXPATHLEN;
+#else
+ /* Some systems do not have a limit on the length of a file name,
+ the GNU system is one such example. */
+ maxPathLen = 0;
+#endif
+ caseSensitive = true;
+}