--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/solaris/native/java/io/UnixFileSystem_md.c Sat Dec 01 00:00:00 2007 +0000
@@ -0,0 +1,559 @@
+/*
+ * Copyright 1998-2006 Sun Microsystems, Inc. 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. Sun designates this
+ * particular file as subject to the "Classpath" exception as provided
+ * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.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 "java_io_FileSystem.h"
+#include "java_io_UnixFileSystem.h"
+
+
+/* -- 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;");
+}
+
+
+/* -- Large-file support -- */
+
+/* LINUX_FIXME: ifdef __solaris__ here is wrong. We need to move the
+ * definition of stat64 into a solaris_largefile.h and create a
+ * linux_largefile.h with a good stat64 structure to compile on
+ * glibc2.0 based systems.
+ */
+#if defined(__solaris__) && !defined(_LFS_LARGEFILE) || !_LFS_LARGEFILE
+
+/* The stat64 structure must be provided for systems without large-file support
+ (e.g., Solaris 2.5.1). These definitions are copied from the Solaris 2.6
+ <sys/stat.h> and <sys/types.h> files.
+ */
+
+typedef longlong_t off64_t; /* offsets within files */
+typedef u_longlong_t ino64_t; /* expanded inode type */
+typedef longlong_t blkcnt64_t; /* count of file blocks */
+
+struct stat64 {
+ dev_t st_dev;
+ long st_pad1[3];
+ ino64_t st_ino;
+ mode_t st_mode;
+ nlink_t st_nlink;
+ uid_t st_uid;
+ gid_t st_gid;
+ dev_t st_rdev;
+ long st_pad2[2];
+ off64_t st_size;
+ timestruc_t st_atim;
+ timestruc_t st_mtim;
+ timestruc_t st_ctim;
+ long st_blksize;
+ blkcnt64_t st_blocks;
+ char st_fstype[_ST_FSTYPSZ];
+ long st_pad4[8];
+};
+
+#endif /* !_LFS_LARGEFILE */
+
+typedef int (*STAT64)(const char *, struct stat64 *);
+
+#if defined(__linux__) && defined(_LARGEFILE64_SOURCE)
+static STAT64 stat64_ptr = &stat64;
+#else
+static STAT64 stat64_ptr = NULL;
+#endif
+
+#ifndef __linux__
+#ifdef __GNUC__
+static void init64IO(void) __attribute__((constructor));
+#else
+#pragma init(init64IO)
+#endif
+#endif
+
+static void init64IO(void) {
+ void *handle = dlopen(0, RTLD_LAZY);
+ stat64_ptr = (STAT64) dlsym(handle, "_stat64");
+ dlclose(handle);
+}
+
+
+/* -- 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 {
+ rv = JNU_NewStringPlatform(env, canonicalPath);
+ }
+ } END_PLATFORM_STRING(env, path);
+ return rv;
+}
+
+
+/* -- Attribute accessors -- */
+
+
+static jboolean
+statMode(const char *path, int *mode)
+{
+ if (stat64_ptr) {
+ struct stat64 sb;
+ if (((*stat64_ptr)(path, &sb)) == 0) {
+ *mode = sb.st_mode;
+ return JNI_TRUE;
+ }
+ } else {
+ struct stat sb;
+ if (stat(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,
+ jobject file)
+{
+ jint rv = 0;
+
+ WITH_FIELD_PLATFORM_STRING(env, file, ids.path, path) {
+ 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;
+ 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, 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) {
+ if (stat64_ptr) {
+ struct stat64 sb;
+ if (((*stat64_ptr)(path, &sb)) == 0) {
+ rv = 1000 * (jlong)sb.st_mtime;
+ }
+ } else {
+ struct stat sb;
+ if (stat(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) {
+ if (stat64_ptr) {
+ struct stat64 sb;
+ if (((*stat64_ptr)(path, &sb)) == 0) {
+ rv = sb.st_size;
+ }
+ } else {
+ struct stat sb;
+ if (stat(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);
+ }
+ name = JNU_NewStringPlatform(env, ptr->d_name);
+ 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;
+}
+
+
+/* Bug in solaris /usr/include/sys/time.h? */
+#ifdef __solaris__
+extern int utimes(const char *, const struct timeval *);
+#elif defined(__linux___)
+extern int utimes(const char *, struct timeval *);
+#endif
+
+
+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 timeval tv[2];
+#ifdef __solaris__
+ timestruc_t ts;
+
+ if (stat64_ptr) {
+ struct stat64 sb;
+ if (((*stat64_ptr)(path, &sb)) == 0)
+ ts = sb.st_atim;
+ else
+ goto error;
+ } else {
+ struct stat sb;
+ if (stat(path, &sb) == 0)
+ ts = sb.st_atim;
+ else
+ goto error;
+ }
+#endif
+
+ /* Preserve access time */
+#ifdef __linux__
+ struct stat sb;
+
+ if (stat(path, &sb) == 0) {
+
+ tv[0].tv_sec = sb.st_atime;
+ tv[0].tv_usec = 0;
+ }
+#else
+ tv[0].tv_sec = ts.tv_sec;
+ tv[0].tv_usec = ts.tv_nsec / 1000;
+#endif
+
+ /* 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;
+
+ error: ;
+ } 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 statvfs fsstat;
+ memset(&fsstat, 0, sizeof(struct statvfs));
+ if (statvfs(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;
+}