Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
      3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
      4  *
      5  * This code is free software; you can redistribute it and/or modify it
      6  * under the terms of the GNU General Public License version 2 only, as
      7  * published by the Free Software Foundation.  Oracle designates this
      8  * particular file as subject to the "Classpath" exception as provided
      9  * by Oracle in the LICENSE file that accompanied this code.
     10  *
     11  * This code is distributed in the hope that it will be useful, but WITHOUT
     12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
     14  * version 2 for more details (a copy is included in the LICENSE file that
     15  * accompanied this code).
     16  *
     17  * You should have received a copy of the GNU General Public License version
     18  * 2 along with this work; if not, write to the Free Software Foundation,
     19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
     20  *
     21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
     22  * or visit www.oracle.com if you need additional information or have any
     23  * questions.
     24  */
     25 
     26 #include "jni.h"
     27 #include "jni_util.h"
     28 #include "jvm.h"
     29 #include "jlong.h"
     30 
     31 #include <stdio.h>
     32 #include <string.h>
     33 #include <dlfcn.h>
     34 #include <errno.h>
     35 #include <mntent.h>
     36 
     37 #include "sun_nio_fs_LinuxNativeDispatcher.h"
     38 
     39 typedef size_t fgetxattr_func(int fd, const char* name, void* value, size_t size);
     40 typedef int fsetxattr_func(int fd, const char* name, void* value, size_t size, int flags);
     41 typedef int fremovexattr_func(int fd, const char* name);
     42 typedef int flistxattr_func(int fd, char* list, size_t size);
     43 
     44 fgetxattr_func* my_fgetxattr_func = NULL;
     45 fsetxattr_func* my_fsetxattr_func = NULL;
     46 fremovexattr_func* my_fremovexattr_func = NULL;
     47 flistxattr_func* my_flistxattr_func = NULL;
     48 
     49 static jfieldID entry_name;
     50 static jfieldID entry_dir;
     51 static jfieldID entry_fstype;
     52 static jfieldID entry_options;
     53 
     54 static void throwUnixException(JNIEnv* env, int errnum) {
     55     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
     56         "(I)V", errnum);
     57     if (x != NULL) {
     58         (*env)->Throw(env, x);
     59     }
     60 }
     61 
     62 JNIEXPORT void JNICALL
     63 Java_sun_nio_fs_LinuxNativeDispatcher_init(JNIEnv *env, jclass clazz)
     64 {
     65     my_fgetxattr_func = (fgetxattr_func*)dlsym(RTLD_DEFAULT, "fgetxattr");
     66     my_fsetxattr_func = (fsetxattr_func*)dlsym(RTLD_DEFAULT, "fsetxattr");
     67     my_fremovexattr_func = (fremovexattr_func*)dlsym(RTLD_DEFAULT, "fremovexattr");
     68     my_flistxattr_func = (flistxattr_func*)dlsym(RTLD_DEFAULT, "flistxattr");
     69 
     70     clazz = (*env)->FindClass(env, "sun/nio/fs/UnixMountEntry");
     71     CHECK_NULL(clazz);
     72     entry_name = (*env)->GetFieldID(env, clazz, "name", "[B");
     73     CHECK_NULL(entry_name);
     74     entry_dir = (*env)->GetFieldID(env, clazz, "dir", "[B");
     75     CHECK_NULL(entry_dir);
     76     entry_fstype = (*env)->GetFieldID(env, clazz, "fstype", "[B");
     77     CHECK_NULL(entry_fstype);
     78     entry_options = (*env)->GetFieldID(env, clazz, "opts", "[B");
     79     CHECK_NULL(entry_options);
     80 }
     81 
     82 JNIEXPORT jint JNICALL
     83 Java_sun_nio_fs_LinuxNativeDispatcher_fgetxattr0(JNIEnv* env, jclass clazz,
     84     jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
     85 {
     86     size_t res = -1;
     87     const char* name = jlong_to_ptr(nameAddress);
     88     void* value = jlong_to_ptr(valueAddress);
     89 
     90     if (my_fgetxattr_func == NULL) {
     91         errno = ENOTSUP;
     92     } else {
     93         /* EINTR not documented */
     94         res = (*my_fgetxattr_func)(fd, name, value, valueLen);
     95     }
     96     if (res == (size_t)-1)
     97         throwUnixException(env, errno);
     98     return (jint)res;
     99 }
    100 
    101 JNIEXPORT void JNICALL
    102 Java_sun_nio_fs_LinuxNativeDispatcher_fsetxattr0(JNIEnv* env, jclass clazz,
    103     jint fd, jlong nameAddress, jlong valueAddress, jint valueLen)
    104 {
    105     int res = -1;
    106     const char* name = jlong_to_ptr(nameAddress);
    107     void* value = jlong_to_ptr(valueAddress);
    108 
    109     if (my_fsetxattr_func == NULL) {
    110         errno = ENOTSUP;
    111     } else {
    112         /* EINTR not documented */
    113         res = (*my_fsetxattr_func)(fd, name, value, valueLen, 0);
    114     }
    115     if (res == -1)
    116         throwUnixException(env, errno);
    117 }
    118 
    119 JNIEXPORT void JNICALL
    120 Java_sun_nio_fs_LinuxNativeDispatcher_fremovexattr0(JNIEnv* env, jclass clazz,
    121     jint fd, jlong nameAddress)
    122 {
    123     int res = -1;
    124     const char* name = jlong_to_ptr(nameAddress);
    125 
    126     if (my_fremovexattr_func == NULL) {
    127         errno = ENOTSUP;
    128     } else {
    129         /* EINTR not documented */
    130         res = (*my_fremovexattr_func)(fd, name);
    131     }
    132     if (res == -1)
    133         throwUnixException(env, errno);
    134 }
    135 
    136 JNIEXPORT jint JNICALL
    137 Java_sun_nio_fs_LinuxNativeDispatcher_flistxattr(JNIEnv* env, jclass clazz,
    138     jint fd, jlong listAddress, jint size)
    139 {
    140     size_t res = -1;
    141     char* list = jlong_to_ptr(listAddress);
    142 
    143     if (my_flistxattr_func == NULL) {
    144         errno = ENOTSUP;
    145     } else {
    146         /* EINTR not documented */
    147         res = (*my_flistxattr_func)(fd, list, (size_t)size);
    148     }
    149     if (res == (size_t)-1)
    150         throwUnixException(env, errno);
    151     return (jint)res;
    152 }
    153 
    154 JNIEXPORT jlong JNICALL
    155 Java_sun_nio_fs_LinuxNativeDispatcher_setmntent0(JNIEnv* env, jclass this, jlong pathAddress,
    156                                                  jlong modeAddress)
    157 {
    158     FILE* fp = NULL;
    159     const char* path = (const char*)jlong_to_ptr(pathAddress);
    160     const char* mode = (const char*)jlong_to_ptr(modeAddress);
    161 
    162     do {
    163         fp = setmntent(path, mode);
    164     } while (fp == NULL && errno == EINTR);
    165     if (fp == NULL) {
    166         throwUnixException(env, errno);
    167     }
    168     return ptr_to_jlong(fp);
    169 }
    170 
    171 JNIEXPORT jint JNICALL
    172 Java_sun_nio_fs_LinuxNativeDispatcher_getmntent(JNIEnv* env, jclass this,
    173     jlong value, jobject entry)
    174 {
    175     struct mntent ent;
    176     char buf[1024];
    177     int buflen = sizeof(buf);
    178     struct mntent* m;
    179     FILE* fp = jlong_to_ptr(value);
    180     jsize len;
    181     jbyteArray bytes;
    182     char* name;
    183     char* dir;
    184     char* fstype;
    185     char* options;
    186 
    187     m = getmntent_r(fp, &ent, (char*)&buf, buflen);
    188     if (m == NULL)
    189         return -1;
    190     name = m->mnt_fsname;
    191     dir = m->mnt_dir;
    192     fstype = m->mnt_type;
    193     options = m->mnt_opts;
    194 
    195     len = strlen(name);
    196     bytes = (*env)->NewByteArray(env, len);
    197     if (bytes == NULL)
    198         return -1;
    199     (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)name);
    200     (*env)->SetObjectField(env, entry, entry_name, bytes);
    201 
    202     len = strlen(dir);
    203     bytes = (*env)->NewByteArray(env, len);
    204     if (bytes == NULL)
    205         return -1;
    206     (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)dir);
    207     (*env)->SetObjectField(env, entry, entry_dir, bytes);
    208 
    209     len = strlen(fstype);
    210     bytes = (*env)->NewByteArray(env, len);
    211     if (bytes == NULL)
    212         return -1;
    213     (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)fstype);
    214     (*env)->SetObjectField(env, entry, entry_fstype, bytes);
    215 
    216     len = strlen(options);
    217     bytes = (*env)->NewByteArray(env, len);
    218     if (bytes == NULL)
    219         return -1;
    220     (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte*)options);
    221     (*env)->SetObjectField(env, entry, entry_options, bytes);
    222 
    223     return 0;
    224 }
    225 
    226 JNIEXPORT void JNICALL
    227 Java_sun_nio_fs_LinuxNativeDispatcher_endmntent(JNIEnv* env, jclass this, jlong stream)
    228 {
    229     FILE* fp = jlong_to_ptr(stream);
    230     /* FIXME - man page doesn't explain how errors are returned */
    231     endmntent(fp);
    232 }
    233