src/java.base/aix/native/libnio/fs/AixNativeDispatcher.c

Print this page

        

*** 1,7 **** /* ! * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. * Copyright 2013 SAP AG. 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 --- 1,7 ---- /* ! * Copyright (c) 2008, 2014, Oracle and/or its affiliates. All rights reserved. * Copyright 2013 SAP AG. 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
*** 22,48 **** --- 22,72 ---- * 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. */ + /* + * Portions Copyright (c) 2014 IBM Corporation + */ + #include <stdlib.h> #include <errno.h> #include <sys/types.h> #include <sys/mntctl.h> #include "jni.h" #include "jni_util.h" + #include "jvm.h" + #include "jlong.h" + + #include <stdio.h> + #include <dlfcn.h> + #include <mntent.h> + #include <sys/vmount.h> + #include "net_util.h" #include "sun_nio_fs_AixNativeDispatcher.h" static jfieldID entry_name; static jfieldID entry_dir; static jfieldID entry_fstype; static jfieldID entry_options; static jclass entry_cls; + typedef size_t fgetxattr_func_t(int fd, const char* name, void* value, size_t size); + typedef int fsetxattr_func_t(int fd, const char* name, void* value, size_t size, int flags); + typedef int fremovexattr_func_t(int fd, const char* name); + typedef int flistxattr_func_t(int fd, char* list, size_t size); + + fgetxattr_func_t* fgetxattr_func = NULL; + fsetxattr_func_t* fsetxattr_func = NULL; + fremovexattr_func_t* fremovexattr_func = NULL; + flistxattr_func_t* flistxattr_func = NULL; + + + /** * Call this to throw an internal UnixException when a system/library * call fails */ static void throwUnixException(JNIEnv* env, int errnum) {
*** 57,66 **** --- 81,91 ---- * Initialization */ JNIEXPORT void JNICALL Java_sun_nio_fs_AixNativeDispatcher_init(JNIEnv* env, jclass this) { + jint flags = 0; jclass clazz; clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); CHECK_NULL(clazz); entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
*** 74,83 **** --- 99,113 ---- entry_cls = (*env)->NewGlobalRef(env, clazz); if (entry_cls == NULL) { JNU_ThrowOutOfMemoryError(env, NULL); return; } + + fgetxattr_func = (fgetxattr_func_t*)dlsym(RTLD_DEFAULT, "fgetxattr"); + fsetxattr_func = (fsetxattr_func_t*)dlsym(RTLD_DEFAULT, "fsetxattr"); + fremovexattr_func = (fremovexattr_func_t*)dlsym(RTLD_DEFAULT, "fremovexattr"); + flistxattr_func = (flistxattr_func_t*)dlsym(RTLD_DEFAULT, "flistxattr"); } /** * Special implementation of getextmntent (see SolarisNativeDispatcher.c) * that returns all entries at once.
*** 226,230 **** --- 256,491 ---- if (must_free_buf) { free(buffer); } return ret; } + + JNIEXPORT jint JNICALL + Java_sun_nio_fs_AixNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress, jlong valueAddress, jint valueLen) + { + size_t res = -1; + const char* name = jlong_to_ptr(nameAddress); + void* value = jlong_to_ptr(valueAddress); + + if (fgetxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*fgetxattr_func)(fd, name, value, valueLen); + } + if (res == (size_t)-1) { + throwUnixException(env, errno); + } + return (jint)res; + } + + JNIEXPORT void JNICALL + Java_sun_nio_fs_AixNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress, jlong valueAddress, jint valueLen) + { + int res = -1; + const char* name = jlong_to_ptr(nameAddress); + void* value = jlong_to_ptr(valueAddress); + + if (fsetxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*fsetxattr_func)(fd, name, value, valueLen, 0); + } + if (res == -1) { + throwUnixException(env, errno); + } + } + + JNIEXPORT void JNICALL + Java_sun_nio_fs_AixNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz, + jint fd, jlong nameAddress) + { + int res = -1; + const char* name = jlong_to_ptr(nameAddress); + + if (fremovexattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*fremovexattr_func)(fd, name); + } + if (res == -1) { + throwUnixException(env, errno); + } + } + + JNIEXPORT jint JNICALL + Java_sun_nio_fs_AixNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz, + jint fd, jlong listAddress, jint size) + { + size_t res = -1; + char* list = jlong_to_ptr(listAddress); + + if (flistxattr_func == NULL) { + errno = ENOTSUP; + } else { + /* EINTR not documented */ + res = (*flistxattr_func)(fd, list, (size_t)size); + } + if (res == (size_t)-1) { + throwUnixException(env, errno); + } + return (jint)res; + } + + JNIEXPORT jint JNICALL + Java_sun_nio_fs_AixNativeDispatcher_queryMountEntrySize(JNIEnv* env, jclass this) + { + int size; + + if (mntctl(MCTL_QUERY, sizeof(size), (char *)&size) != 0) { + return 0; + } + return size; + } + + JNIEXPORT void JNICALL + Java_sun_nio_fs_AixNativeDispatcher_getAixMountEntries(JNIEnv* env, jclass this, jobject entries, jlong bufferAddress, jint size) + { + jmethodID addMethod, constructor; + jclass arrayListClass, unixMountEntryClass; + int entryNum; + char *buffer = NULL; + char *ptr = NULL; + char *name = NULL; + char *type = NULL; + char *path = NULL; + char *opts = NULL; + int len, count; + jboolean readOnly = JNI_FALSE; + jobject mountEntry; + jbyteArray bytes; + struct vmount * vmountPtr = NULL; + jfieldID entry_name; + jfieldID entry_dir; + jfieldID entry_fstype; + jfieldID entry_options; + + arrayListClass = (*env)->FindClass(env, "java/util/ArrayList"); + if ((*env)->ExceptionOccurred(env)) { + return; + } + + addMethod = (*env)->GetMethodID(env, arrayListClass, "add", "(Ljava/lang/Object;)Z"); + if ((*env)->ExceptionOccurred(env)) { + return; + } + + unixMountEntryClass = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry"); + if ((*env)->ExceptionOccurred(env)) { + return; + } + + constructor = (*env)->GetMethodID(env, unixMountEntryClass, "<init>", "()V"); + if ((*env)->ExceptionOccurred(env)) { + return; + } + + buffer = (char *)jlong_to_ptr(bufferAddress); + + entryNum = mntctl(MCTL_QUERY, size, buffer); + + if (entryNum <= 0) { + return; + } + + entry_name = (*env)->GetFieldID(env, unixMountEntryClass, "name", "[B"); + entry_dir = (*env)->GetFieldID(env, unixMountEntryClass, "dir", "[B"); + entry_fstype = (*env)->GetFieldID(env, unixMountEntryClass, "fstype", "[B"); + entry_options = (*env)->GetFieldID(env, unixMountEntryClass, "opts", "[B"); + + ptr = buffer; + for (count = 0; count < entryNum; count++, ptr += vmountPtr->vmt_length) { + vmountPtr = (struct vmount *)ptr; + switch (vmountPtr->vmt_gfstype) { + case MNT_JFS: + type = "jfs"; + break; + case MNT_J2: + type = "jfs2"; + break; + case MNT_NFS: + type = "nfs"; + break; + case MNT_CDROM: + type = "cdrom"; + break; + case MNT_PROCFS: + type = "procfs"; + break; + default: + type = "unknown"; + } + if (vmountPtr->vmt_flags & MNT_READONLY) { + readOnly = JNI_TRUE; + } else { + readOnly = JNI_FALSE; + } + + name = (char *)(ptr + vmountPtr->vmt_data[VMT_OBJECT].vmt_off); + path = (char *)(ptr + vmountPtr->vmt_data[VMT_STUB].vmt_off); + + mountEntry = (*env)->NewObject(env, unixMountEntryClass, constructor); + + // name + len = strlen(name); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) { + break; + } + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name); + (*env)->SetObjectField(env, mountEntry, entry_name, bytes); + + // dir + len = strlen(path); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) { + break; + } + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)path); + (*env)->SetObjectField(env, mountEntry, entry_dir, bytes); + + // filetype + len = strlen(type); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) { + break; + } + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)type); + (*env)->SetObjectField(env, mountEntry, entry_fstype, bytes); + + // opts + if (readOnly) { + opts = "ro"; + } else { + opts = ""; + } + len = strlen(opts); + bytes = (*env)->NewByteArray(env, len); + if (bytes == NULL) { + break; + } + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)opts); + (*env)->SetObjectField(env, mountEntry, entry_options, bytes); + + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + goto error; + } + (*env)->CallBooleanMethod(env, entries, addMethod, mountEntry); + if ((*env)->ExceptionOccurred(env)) { + (*env)->ExceptionDescribe(env); + goto error; + } + } + + error: + return; + }