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

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved.
+ * 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,27 +22,51 @@
  * 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,10 +81,11 @@
  * 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,10 +99,15 @@
     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,5 +256,236 @@
     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;
+}