1 /* 2 * Copyright (c) 2000, 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 <windows.h> 27 #include <winsock2.h> 28 #include <io.h> 29 #include "jni.h" 30 #include "jni_util.h" 31 #include "jvm.h" 32 #include "jlong.h" 33 34 #include "nio.h" 35 #include "nio_util.h" 36 #include "sun_nio_ch_IOUtil.h" 37 38 /* field id for jlong 'handle' in java.io.FileDescriptor used for file fds */ 39 static jfieldID handle_fdID; 40 41 /* field id for jint 'fd' in java.io.FileDescriptor used for socket fds */ 42 static jfieldID fd_fdID; 43 44 JNIEXPORT jboolean JNICALL 45 Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed 46 (JNIEnv *env, jclass clazz, jbyteArray randArray); 47 48 /************************************************************** 49 * static method to store field IDs in initializers 50 */ 51 52 JNIEXPORT void JNICALL 53 Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) 54 { 55 CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); 56 CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); 57 CHECK_NULL(handle_fdID = (*env)->GetFieldID(env, clazz, "handle", "J")); 58 } 59 60 /************************************************************** 61 * IOUtil.c 62 */ 63 JNIEXPORT jboolean JNICALL 64 Java_sun_nio_ch_IOUtil_randomBytes(JNIEnv *env, jclass clazz, 65 jbyteArray randArray) 66 { 67 return 68 Java_sun_security_provider_NativeSeedGenerator_nativeGenerateSeed(env, 69 clazz, 70 randArray); 71 } 72 73 JNIEXPORT jint JNICALL 74 Java_sun_nio_ch_IOUtil_iovMax(JNIEnv *env, jclass this) 75 { 76 return 16; 77 } 78 79 80 jint 81 convertReturnVal(JNIEnv *env, jint n, jboolean reading) 82 { 83 if (n > 0) /* Number of bytes written */ 84 return n; 85 if (n == 0) { 86 if (reading) { 87 return IOS_EOF; /* EOF is -1 in javaland */ 88 } else { 89 return 0; 90 } 91 } 92 JNU_ThrowIOExceptionWithLastError(env, "Read/write failed"); 93 return IOS_THROWN; 94 } 95 96 jlong 97 convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading) 98 { 99 if (n > 0) /* Number of bytes written */ 100 return n; 101 if (n == 0) { 102 if (reading) { 103 return IOS_EOF; /* EOF is -1 in javaland */ 104 } else { 105 return 0; 106 } 107 } 108 JNU_ThrowIOExceptionWithLastError(env, "Read/write failed"); 109 return IOS_THROWN; 110 } 111 112 JNIEXPORT jint JNICALL 113 Java_sun_nio_ch_IOUtil_fdVal(JNIEnv *env, jclass clazz, jobject fdo) 114 { 115 return fdval(env, fdo); 116 } 117 118 JNIEXPORT void JNICALL 119 Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val) 120 { 121 (*env)->SetIntField(env, fdo, fd_fdID, val); 122 } 123 124 125 #define SET_BLOCKING 0 126 #define SET_NONBLOCKING 1 127 128 JNIEXPORT void JNICALL 129 Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz, 130 jobject fdo, jboolean blocking) 131 { 132 u_long argp; 133 int result = 0; 134 jint fd = fdval(env, fdo); 135 136 if (blocking == JNI_FALSE) { 137 argp = SET_NONBLOCKING; 138 } else { 139 argp = SET_BLOCKING; 140 /* Blocking fd cannot be registered with EventSelect */ 141 WSAEventSelect(fd, NULL, 0); 142 } 143 result = ioctlsocket(fd, FIONBIO, &argp); 144 if (result == SOCKET_ERROR) { 145 int error = WSAGetLastError(); 146 handleSocketError(env, (jint)error); 147 } 148 } 149 150 /* Note: Drain uses the int fd value. It is currently not called 151 on windows. 152 */ 153 JNIEXPORT jboolean JNICALL 154 Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd) 155 { 156 DWORD read = 0; 157 int totalRead = 0; 158 BOOL result = 0; 159 HANDLE h = (HANDLE)_get_osfhandle(fd); 160 char buf[128]; 161 162 if (h == INVALID_HANDLE_VALUE) { 163 JNU_ThrowIOExceptionWithLastError(env, "Read failed"); 164 return JNI_FALSE; 165 } 166 167 for (;;) { 168 result = ReadFile(h, /* File handle to read */ 169 (LPVOID)&buf, /* address to put data */ 170 128, /* number of bytes to read */ 171 &read, /* number of bytes read */ 172 NULL); /* no overlapped struct */ 173 174 if (result == 0) { 175 int error = GetLastError(); 176 if (error == ERROR_NO_DATA) { 177 return (totalRead > 0) ? JNI_TRUE : JNI_FALSE; 178 } 179 JNU_ThrowIOExceptionWithLastError(env, "Drain"); 180 return JNI_FALSE; 181 } 182 if (read > 0) { 183 totalRead += read; 184 } else { 185 break; 186 } 187 } 188 return (totalRead > 0) ? JNI_TRUE : JNI_FALSE; 189 } 190 191 /* Note: This function returns the int fd value from file descriptor. 192 It is mostly used for sockets which should use the int fd value. 193 */ 194 jint 195 fdval(JNIEnv *env, jobject fdo) 196 { 197 return (*env)->GetIntField(env, fdo, fd_fdID); 198 } 199 200 jlong 201 handleval(JNIEnv *env, jobject fdo) 202 { 203 return (*env)->GetLongField(env, fdo, handle_fdID); 204 }