Home | History | Annotate | Download | only in native
      1 /*
      2  * Copyright (c) 2008, 2011, 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 <stdlib.h>
     32 #include <dlfcn.h>
     33 #include <sys/types.h>
     34 #include <sys/socket.h>
     35 #include <sys/poll.h>
     36 #include <sys/inotify.h>
     37 
     38 #include "sun_nio_fs_LinuxWatchService.h"
     39 
     40 static void throwUnixException(JNIEnv* env, int errnum) {
     41     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
     42         "(I)V", errnum);
     43     if (x != NULL) {
     44         (*env)->Throw(env, x);
     45     }
     46 }
     47 
     48 JNIEXPORT jint JNICALL
     49 Java_sun_nio_fs_LinuxWatchService_eventSize(JNIEnv *env, jclass clazz)
     50 {
     51     return (jint)sizeof(struct inotify_event);
     52 }
     53 
     54 JNIEXPORT jintArray JNICALL
     55 Java_sun_nio_fs_LinuxWatchService_eventOffsets(JNIEnv *env, jclass clazz)
     56 {
     57     jintArray result = (*env)->NewIntArray(env, 5);
     58     if (result != NULL) {
     59         jint arr[5];
     60         arr[0] = (jint)offsetof(struct inotify_event, wd);
     61         arr[1] = (jint)offsetof(struct inotify_event, mask);
     62         arr[2] = (jint)offsetof(struct inotify_event, cookie);
     63         arr[3] = (jint)offsetof(struct inotify_event, len);
     64         arr[4] = (jint)offsetof(struct inotify_event, name);
     65         (*env)->SetIntArrayRegion(env, result, 0, 5, arr);
     66     }
     67     return result;
     68 }
     69 
     70 
     71 JNIEXPORT jint JNICALL
     72 Java_sun_nio_fs_LinuxWatchService_inotifyInit
     73     (JNIEnv* env, jclass clazz)
     74 {
     75     int ifd = inotify_init();
     76     if (ifd == -1) {
     77         throwUnixException(env, errno);
     78     }
     79     return (jint)ifd;
     80 }
     81 
     82 JNIEXPORT jint JNICALL
     83 Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch
     84     (JNIEnv* env, jclass clazz, jint fd, jlong address, jint mask)
     85 {
     86     int wfd = -1;
     87     const char* path = (const char*)jlong_to_ptr(address);
     88 
     89     wfd = inotify_add_watch((int)fd, path, mask);
     90     if (wfd == -1) {
     91         throwUnixException(env, errno);
     92     }
     93     return (jint)wfd;
     94 }
     95 
     96 JNIEXPORT void JNICALL
     97 Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch
     98     (JNIEnv* env, jclass clazz, jint fd, jint wd)
     99 {
    100     int err = inotify_rm_watch((int)fd, (int)wd);
    101     if (err == -1)
    102         throwUnixException(env, errno);
    103 }
    104 
    105 JNIEXPORT void JNICALL
    106 Java_sun_nio_fs_LinuxWatchService_configureBlocking
    107     (JNIEnv* env, jclass clazz, jint fd, jboolean blocking)
    108 {
    109     int flags = fcntl(fd, F_GETFL);
    110 
    111     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK))
    112         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
    113     else if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK))
    114         fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
    115 }
    116 
    117 JNIEXPORT void JNICALL
    118 Java_sun_nio_fs_LinuxWatchService_socketpair
    119     (JNIEnv* env, jclass clazz, jintArray sv)
    120 {
    121     int sp[2];
    122     if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
    123         throwUnixException(env, errno);
    124     } else {
    125         jint res[2];
    126         res[0] = (jint)sp[0];
    127         res[1] = (jint)sp[1];
    128         (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
    129     }
    130 }
    131 
    132 JNIEXPORT jint JNICALL
    133 Java_sun_nio_fs_LinuxWatchService_poll
    134     (JNIEnv* env, jclass clazz, jint fd1, jint fd2)
    135 {
    136     struct pollfd ufds[2];
    137     int n;
    138 
    139     ufds[0].fd = fd1;
    140     ufds[0].events = POLLIN;
    141     ufds[1].fd = fd2;
    142     ufds[1].events = POLLIN;
    143 
    144     n = poll(&ufds[0], 2, -1);
    145     if (n == -1) {
    146         if (errno == EINTR) {
    147             n = 0;
    148         } else {
    149             throwUnixException(env, errno);
    150         }
    151      }
    152     return (jint)n;
    153 }
    154