jdk/src/solaris/native/sun/nio/fs/LinuxWatchService.c
changeset 2057 3acf8e5e2ca0
child 5506 202f599c92aa
equal deleted inserted replaced
2056:115e09b7a004 2057:3acf8e5e2ca0
       
     1 /*
       
     2  * Copyright 2008-2009 Sun Microsystems, Inc.  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.  Sun designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    22  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    23  * have any 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 
       
    37 #include "sun_nio_fs_LinuxWatchService.h"
       
    38 
       
    39 /* inotify.h may not be available at build time */
       
    40 #ifdef  __cplusplus
       
    41 extern "C" {
       
    42 #endif
       
    43 struct inotify_event
       
    44 {
       
    45   int wd;
       
    46   uint32_t mask;
       
    47   uint32_t cookie;
       
    48   uint32_t len;
       
    49   char name __flexarr;
       
    50 };
       
    51 #ifdef  __cplusplus
       
    52 }
       
    53 #endif
       
    54 
       
    55 typedef int inotify_init_func(void);
       
    56 typedef int inotify_add_watch_func(int fd, const char* path, uint32_t mask);
       
    57 typedef int inotify_rm_watch_func(int fd, uint32_t wd);
       
    58 
       
    59 inotify_init_func* my_inotify_init_func = NULL;
       
    60 inotify_add_watch_func* my_inotify_add_watch_func = NULL;
       
    61 inotify_rm_watch_func* my_inotify_rm_watch_func = NULL;
       
    62 
       
    63 static void throwUnixException(JNIEnv* env, int errnum) {
       
    64     jobject x = JNU_NewObjectByName(env, "sun/nio/fs/UnixException",
       
    65         "(I)V", errnum);
       
    66     if (x != NULL) {
       
    67         (*env)->Throw(env, x);
       
    68     }
       
    69 }
       
    70 
       
    71 JNIEXPORT void JNICALL
       
    72 Java_sun_nio_fs_LinuxWatchService_init(JNIEnv *env, jclass clazz)
       
    73 {
       
    74     my_inotify_init_func = (inotify_init_func*)
       
    75         dlsym(RTLD_DEFAULT, "inotify_init");
       
    76     my_inotify_add_watch_func =
       
    77         (inotify_add_watch_func*) dlsym(RTLD_DEFAULT, "inotify_add_watch");
       
    78     my_inotify_rm_watch_func =
       
    79         (inotify_rm_watch_func*) dlsym(RTLD_DEFAULT, "inotify_rm_watch");
       
    80 
       
    81     if ((my_inotify_init_func == NULL) || (my_inotify_add_watch_func == NULL) ||
       
    82         (my_inotify_rm_watch_func == NULL)) {
       
    83         JNU_ThrowInternalError(env, "unable to get address of inotify functions");
       
    84     }
       
    85 }
       
    86 
       
    87 JNIEXPORT jint JNICALL
       
    88 Java_sun_nio_fs_LinuxWatchService_eventSize(JNIEnv *env, jclass clazz)
       
    89 {
       
    90     return (jint)sizeof(struct inotify_event);
       
    91 }
       
    92 
       
    93 JNIEXPORT jintArray JNICALL
       
    94 Java_sun_nio_fs_LinuxWatchService_eventOffsets(JNIEnv *env, jclass clazz)
       
    95 {
       
    96     jintArray result = (*env)->NewIntArray(env, 5);
       
    97     if (result != NULL) {
       
    98         jint arr[5];
       
    99         arr[0] = (jint)offsetof(struct inotify_event, wd);
       
   100         arr[1] = (jint)offsetof(struct inotify_event, mask);
       
   101         arr[2] = (jint)offsetof(struct inotify_event, cookie);
       
   102         arr[3] = (jint)offsetof(struct inotify_event, len);
       
   103         arr[4] = (jint)offsetof(struct inotify_event, name);
       
   104         (*env)->SetIntArrayRegion(env, result, 0, 5, arr);
       
   105     }
       
   106     return result;
       
   107 }
       
   108 
       
   109 
       
   110 JNIEXPORT jint JNICALL
       
   111 Java_sun_nio_fs_LinuxWatchService_inotifyInit
       
   112     (JNIEnv* env, jclass clazz)
       
   113 {
       
   114     int ifd = (*my_inotify_init_func)();
       
   115     if (ifd == -1) {
       
   116         throwUnixException(env, errno);
       
   117     }
       
   118     return (jint)ifd;
       
   119 }
       
   120 
       
   121 JNIEXPORT jint JNICALL
       
   122 Java_sun_nio_fs_LinuxWatchService_inotifyAddWatch
       
   123     (JNIEnv* env, jclass clazz, jint fd, jlong address, jint mask)
       
   124 {
       
   125     int wfd = -1;
       
   126     const char* path = (const char*)jlong_to_ptr(address);
       
   127 
       
   128     wfd = (*my_inotify_add_watch_func)((int)fd, path, mask);
       
   129     if (wfd == -1) {
       
   130         throwUnixException(env, errno);
       
   131     }
       
   132     return (jint)wfd;
       
   133 }
       
   134 
       
   135 JNIEXPORT void JNICALL
       
   136 Java_sun_nio_fs_LinuxWatchService_inotifyRmWatch
       
   137     (JNIEnv* env, jclass clazz, jint fd, jint wd)
       
   138 {
       
   139     int err = (*my_inotify_rm_watch_func)((int)fd, (int)wd);
       
   140     if (err == -1)
       
   141         throwUnixException(env, errno);
       
   142 }
       
   143 
       
   144 JNIEXPORT void JNICALL
       
   145 Java_sun_nio_fs_LinuxWatchService_configureBlocking
       
   146     (JNIEnv* env, jclass clazz, jint fd, jboolean blocking)
       
   147 {
       
   148     int flags = fcntl(fd, F_GETFL);
       
   149 
       
   150     if ((blocking == JNI_FALSE) && !(flags & O_NONBLOCK))
       
   151         fcntl(fd, F_SETFL, flags | O_NONBLOCK);
       
   152     else if ((blocking == JNI_TRUE) && (flags & O_NONBLOCK))
       
   153         fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
       
   154 }
       
   155 
       
   156 JNIEXPORT void JNICALL
       
   157 Java_sun_nio_fs_LinuxWatchService_socketpair
       
   158     (JNIEnv* env, jclass clazz, jintArray sv)
       
   159 {
       
   160     int sp[2];
       
   161     if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) == -1) {
       
   162         throwUnixException(env, errno);
       
   163     } else {
       
   164         jint res[2];
       
   165         res[0] = (jint)sp[0];
       
   166         res[1] = (jint)sp[1];
       
   167         (*env)->SetIntArrayRegion(env, sv, 0, 2, &res[0]);
       
   168     }
       
   169 
       
   170 }
       
   171 
       
   172 JNIEXPORT jint JNICALL
       
   173 Java_sun_nio_fs_LinuxWatchService_poll
       
   174     (JNIEnv* env, jclass clazz, jint fd1, jint fd2)
       
   175 {
       
   176     struct pollfd ufds[2];
       
   177     int n;
       
   178 
       
   179     ufds[0].fd = fd1;
       
   180     ufds[0].events = POLLIN;
       
   181     ufds[1].fd = fd2;
       
   182     ufds[1].events = POLLIN;
       
   183 
       
   184     n = poll(&ufds[0], 2, -1);
       
   185     if (n == -1) {
       
   186         if (errno == EINTR) {
       
   187             n = 0;
       
   188         } else {
       
   189             throwUnixException(env, errno);
       
   190         }
       
   191      }
       
   192     return (jint)n;
       
   193 
       
   194 
       
   195 }