summaryrefslogtreecommitdiff
path: root/ojluni/src/main/native/UnixFileSystem_md.c
diff options
context:
space:
mode:
Diffstat (limited to 'ojluni/src/main/native/UnixFileSystem_md.c')
-rwxr-xr-xojluni/src/main/native/UnixFileSystem_md.c458
1 files changed, 458 insertions, 0 deletions
diff --git a/ojluni/src/main/native/UnixFileSystem_md.c b/ojluni/src/main/native/UnixFileSystem_md.c
new file mode 100755
index 0000000000..defa0ae377
--- /dev/null
+++ b/ojluni/src/main/native/UnixFileSystem_md.c
@@ -0,0 +1,458 @@
+/*
+ * Copyright (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation. Oracle designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Oracle in the LICENSE file that accompanied this code.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+#include <assert.h>
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/stat.h>
+#include <sys/statvfs.h>
+#include <string.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+#include <limits.h>
+
+#include "jni.h"
+#include "jni_util.h"
+#include "jlong.h"
+#include "jvm.h"
+#include "io_util.h"
+#include "io_util_md.h"
+#include "java_io_FileSystem.h"
+#include "java_io_UnixFileSystem.h"
+
+#if defined(_ALLBSD_SOURCE)
+#define dirent64 dirent
+#define readdir64_r readdir_r
+#define stat64 stat
+#define statvfs64 statvfs
+#endif
+
+/* -- Field IDs -- */
+
+static struct {
+ jfieldID path;
+} ids;
+
+
+JNIEXPORT void JNICALL
+Java_java_io_UnixFileSystem_initIDs(JNIEnv *env, jclass cls)
+{
+ jclass fileClass = (*env)->FindClass(env, "java/io/File");
+ if (!fileClass) return;
+ ids.path = (*env)->GetFieldID(env, fileClass,
+ "path", "Ljava/lang/String;");
+}
+
+/* -- Path operations -- */
+
+extern int canonicalize(char *path, const char *out, int len);
+
+JNIEXPORT jstring JNICALL
+Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
+ jstring pathname)
+{
+ jstring rv = NULL;
+
+ WITH_PLATFORM_STRING(env, pathname, path) {
+ char canonicalPath[JVM_MAXPATHLEN];
+ if (canonicalize(JVM_NativePath((char *)path),
+ canonicalPath, JVM_MAXPATHLEN) < 0) {
+ JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
+ } else {
+#ifdef MACOSX
+ rv = newStringPlatform(env, canonicalPath);
+#else
+ rv = JNU_NewStringPlatform(env, canonicalPath);
+#endif
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+/* -- Attribute accessors -- */
+
+
+static jboolean
+statMode(const char *path, int *mode)
+{
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ *mode = sb.st_mode;
+ return JNI_TRUE;
+ }
+ return JNI_FALSE;
+}
+
+
+JNIEXPORT jint JNICALL
+Java_java_io_UnixFileSystem_getBooleanAttributes0(JNIEnv *env, jobject this,
+ jstring abspath)
+{
+ jint rv = 0;
+
+ /* ----- BEGIN android -----
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {*/
+ WITH_PLATFORM_STRING(env, abspath, path) {
+ // ----- END android -----
+ int mode;
+ if (statMode(path, &mode)) {
+ int fmt = mode & S_IFMT;
+ rv = (jint) (java_io_FileSystem_BA_EXISTS
+ | ((fmt == S_IFREG) ? java_io_FileSystem_BA_REGULAR : 0)
+ | ((fmt == S_IFDIR) ? java_io_FileSystem_BA_DIRECTORY : 0));
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_checkAccess(JNIEnv *env, jobject this,
+ jobject file, jint a)
+{
+ jboolean rv = JNI_FALSE;
+ int mode = 0;
+ switch (a) {
+ case java_io_FileSystem_ACCESS_READ:
+ mode = R_OK;
+ break;
+ case java_io_FileSystem_ACCESS_WRITE:
+ mode = W_OK;
+ break;
+ case java_io_FileSystem_ACCESS_EXECUTE:
+ mode = X_OK;
+ break;
+ default: assert(0);
+ }
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (access(path, mode) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setPermission(JNIEnv *env, jobject this,
+ jobject file,
+ jint access,
+ jboolean enable,
+ jboolean owneronly)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ int amode = 0;
+ int mode;
+ switch (access) {
+ case java_io_FileSystem_ACCESS_READ:
+ if (owneronly)
+ amode = S_IRUSR;
+ else
+ amode = S_IRUSR | S_IRGRP | S_IROTH;
+ break;
+ case java_io_FileSystem_ACCESS_WRITE:
+ if (owneronly)
+ amode = S_IWUSR;
+ else
+ amode = S_IWUSR | S_IWGRP | S_IWOTH;
+ break;
+ case java_io_FileSystem_ACCESS_EXECUTE:
+ if (owneronly)
+ amode = S_IXUSR;
+ else
+ amode = S_IXUSR | S_IXGRP | S_IXOTH;
+ break;
+ default:
+ assert(0);
+ }
+ if (statMode(path, &mode)) {
+ if (enable)
+ mode |= amode;
+ else
+ mode &= ~amode;
+ if (chmod(path, mode) >= 0) {
+ rv = JNI_TRUE;
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getLastModifiedTime(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jlong rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ rv = 1000 * (jlong)sb.st_mtime;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getLength(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jlong rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+ if (stat64(path, &sb) == 0) {
+ rv = sb.st_size;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+/* -- File operations -- */
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_createFileExclusively(JNIEnv *env, jclass cls,
+ jstring pathname)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_PLATFORM_STRING(env, pathname, path) {
+ int fd;
+ if (!strcmp (path, "/")) {
+ fd = JVM_EEXIST; /* The root directory always exists */
+ } else {
+ fd = JVM_Open(path, JVM_O_RDWR | JVM_O_CREAT | JVM_O_EXCL, 0666);
+ }
+ if (fd < 0) {
+ if (fd != JVM_EEXIST) {
+ JNU_ThrowIOExceptionWithLastError(env, path);
+ }
+ } else {
+ JVM_Close(fd);
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_delete0(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (remove(path) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jobjectArray JNICALL
+Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
+ jobject file)
+{
+ DIR *dir = NULL;
+ struct dirent64 *ptr;
+ struct dirent64 *result;
+ int len, maxlen;
+ jobjectArray rv, old;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ dir = opendir(path);
+ } END_PLATFORM_STRING(env, path);
+ if (dir == NULL) return NULL;
+
+ ptr = malloc(sizeof(struct dirent64) + (PATH_MAX + 1));
+ if (ptr == NULL) {
+ JNU_ThrowOutOfMemoryError(env, "heap allocation failed");
+ closedir(dir);
+ return NULL;
+ }
+
+ /* Allocate an initial String array */
+ len = 0;
+ maxlen = 16;
+ rv = (*env)->NewObjectArray(env, maxlen, JNU_ClassString(env), NULL);
+ if (rv == NULL) goto error;
+
+ /* Scan the directory */
+ while ((readdir64_r(dir, ptr, &result) == 0) && (result != NULL)) {
+ jstring name;
+ if (!strcmp(ptr->d_name, ".") || !strcmp(ptr->d_name, ".."))
+ continue;
+ if (len == maxlen) {
+ old = rv;
+ rv = (*env)->NewObjectArray(env, maxlen <<= 1,
+ JNU_ClassString(env), NULL);
+ if (rv == NULL) goto error;
+ if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
+ (*env)->DeleteLocalRef(env, old);
+ }
+#ifdef MACOSX
+ name = newStringPlatform(env, ptr->d_name);
+#else
+ name = JNU_NewStringPlatform(env, ptr->d_name);
+#endif
+ if (name == NULL) goto error;
+ (*env)->SetObjectArrayElement(env, rv, len++, name);
+ (*env)->DeleteLocalRef(env, name);
+ }
+ closedir(dir);
+ free(ptr);
+
+ /* Copy the final results into an appropriately-sized array */
+ old = rv;
+ rv = (*env)->NewObjectArray(env, len, JNU_ClassString(env), NULL);
+ if (rv == NULL) {
+ return NULL;
+ }
+ if (JNU_CopyObjectArray(env, rv, old, len) < 0) {
+ return NULL;
+ }
+ return rv;
+
+ error:
+ closedir(dir);
+ free(ptr);
+ return NULL;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_createDirectory(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ if (mkdir(path, 0777) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_rename0(JNIEnv *env, jobject this,
+ jobject from, jobject to)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, from, ids.path, fromPath) {
+ WITH_FIELD_PLATFORM_STRING(env, to, ids.path, toPath) {
+ if (rename(fromPath, toPath) == 0) {
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, toPath);
+ } END_PLATFORM_STRING(env, fromPath);
+ return rv;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setLastModifiedTime(JNIEnv *env, jobject this,
+ jobject file, jlong time)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct stat64 sb;
+
+ if (stat64(path, &sb) == 0) {
+ struct timeval tv[2];
+
+ /* Preserve access time */
+ tv[0].tv_sec = sb.st_atime;
+ tv[0].tv_usec = 0;
+
+ /* Change last-modified time */
+ tv[1].tv_sec = time / 1000;
+ tv[1].tv_usec = (time % 1000) * 1000;
+
+ if (utimes(path, tv) == 0)
+ rv = JNI_TRUE;
+ }
+ } END_PLATFORM_STRING(env, path);
+
+ return rv;
+}
+
+
+JNIEXPORT jboolean JNICALL
+Java_java_io_UnixFileSystem_setReadOnly(JNIEnv *env, jobject this,
+ jobject file)
+{
+ jboolean rv = JNI_FALSE;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ int mode;
+ if (statMode(path, &mode)) {
+ if (chmod(path, mode & ~(S_IWUSR | S_IWGRP | S_IWOTH)) >= 0) {
+ rv = JNI_TRUE;
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+JNIEXPORT jlong JNICALL
+Java_java_io_UnixFileSystem_getSpace(JNIEnv *env, jobject this,
+ jobject file, jint t)
+{
+ jlong rv = 0L;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ struct statvfs64 fsstat;
+ memset(&fsstat, 0, sizeof(fsstat));
+ if (statvfs64(path, &fsstat) == 0) {
+ switch(t) {
+ case java_io_FileSystem_SPACE_TOTAL:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_blocks));
+ break;
+ case java_io_FileSystem_SPACE_FREE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_bfree));
+ break;
+ case java_io_FileSystem_SPACE_USABLE:
+ rv = jlong_mul(long_to_jlong(fsstat.f_frsize),
+ long_to_jlong(fsstat.f_bavail));
+ break;
+ default:
+ assert(0);
+ }
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}