1 /* 2 * Copyright (c) 2000, 2018, 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 <sys/types.h> 27 #include <string.h> 28 #include <sys/resource.h> 29 30 #include "jni.h" 31 #include "jni_util.h" 32 #include "jvm.h" 33 #include "jlong.h" 34 #include "sun_nio_ch_IOUtil.h" 35 #include "java_lang_Integer.h" 36 #include "nio.h" 37 #include "nio_util.h" 38 39 static jfieldID fd_fdID; /* for jint 'fd' in java.io.FileDescriptor */ 40 41 42 JNIEXPORT void JNICALL 43 Java_sun_nio_ch_IOUtil_initIDs(JNIEnv *env, jclass clazz) 44 { 45 CHECK_NULL(clazz = (*env)->FindClass(env, "java/io/FileDescriptor")); 46 CHECK_NULL(fd_fdID = (*env)->GetFieldID(env, clazz, "fd", "I")); 47 } 48 49 JNIEXPORT jboolean JNICALL 50 Java_sun_nio_ch_IOUtil_randomBytes(JNIEnv *env, jclass clazz, 51 jbyteArray randArray) 52 { 53 JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", NULL); 54 return JNI_FALSE; 55 } 56 57 JNIEXPORT jint JNICALL 58 Java_sun_nio_ch_IOUtil_fdVal(JNIEnv *env, jclass clazz, jobject fdo) 59 { 60 return (*env)->GetIntField(env, fdo, fd_fdID); 61 } 62 63 JNIEXPORT void JNICALL 64 Java_sun_nio_ch_IOUtil_setfdVal(JNIEnv *env, jclass clazz, jobject fdo, jint val) 65 { 66 (*env)->SetIntField(env, fdo, fd_fdID, val); 67 } 68 69 static int 70 configureBlocking(int fd, jboolean blocking) 71 { 72 int flags = fcntl(fd, F_GETFL); 73 int newflags = blocking ? (flags & ~O_NONBLOCK) : (flags | O_NONBLOCK); 74 75 return (flags == newflags) ? 0 : fcntl(fd, F_SETFL, newflags); 76 } 77 78 JNIEXPORT void JNICALL 79 Java_sun_nio_ch_IOUtil_configureBlocking(JNIEnv *env, jclass clazz, 80 jobject fdo, jboolean blocking) 81 { 82 if (configureBlocking(fdval(env, fdo), blocking) < 0) 83 JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed"); 84 } 85 86 JNIEXPORT jlong JNICALL 87 Java_sun_nio_ch_IOUtil_makePipe(JNIEnv *env, jobject this, jboolean blocking) 88 { 89 int fd[2]; 90 91 if (pipe(fd) < 0) { 92 JNU_ThrowIOExceptionWithLastError(env, "Pipe failed"); 93 return 0; 94 } 95 if (blocking == JNI_FALSE) { 96 if ((configureBlocking(fd[0], JNI_FALSE) < 0) 97 || (configureBlocking(fd[1], JNI_FALSE) < 0)) { 98 JNU_ThrowIOExceptionWithLastError(env, "Configure blocking failed"); 99 close(fd[0]); 100 close(fd[1]); 101 return 0; 102 } 103 } 104 return ((jlong) fd[0] << 32) | (jlong) fd[1]; 105 } 106 107 JNIEXPORT jint JNICALL 108 Java_sun_nio_ch_IOUtil_write1(JNIEnv *env, jclass cl, jint fd, jbyte b) 109 { 110 char c = (char)b; 111 return convertReturnVal(env, write(fd, &c, 1), JNI_FALSE); 112 } 113 114 JNIEXPORT jboolean JNICALL 115 Java_sun_nio_ch_IOUtil_drain(JNIEnv *env, jclass cl, jint fd) 116 { 117 char buf[16]; 118 int tn = 0; 119 120 for (;;) { 121 int n = read(fd, buf, sizeof(buf)); 122 tn += n; 123 if ((n < 0) && (errno != EAGAIN && errno != EWOULDBLOCK)) 124 JNU_ThrowIOExceptionWithLastError(env, "Drain"); 125 if (n == (int)sizeof(buf)) 126 continue; 127 return (tn > 0) ? JNI_TRUE : JNI_FALSE; 128 } 129 } 130 131 JNIEXPORT jint JNICALL 132 Java_sun_nio_ch_IOUtil_drain1(JNIEnv *env, jclass cl, jint fd) 133 { 134 int res; 135 char buf[1]; 136 137 res = read(fd, buf, 1); 138 if (res < 0) { 139 if (errno == EAGAIN || errno == EWOULDBLOCK) { 140 res = 0; 141 } else if (errno == EINTR) { 142 return IOS_INTERRUPTED; 143 } else { 144 JNU_ThrowIOExceptionWithLastError(env, "read"); 145 return IOS_THROWN; 146 } 147 } 148 return res; 149 } 150 151 JNIEXPORT jint JNICALL 152 Java_sun_nio_ch_IOUtil_fdLimit(JNIEnv *env, jclass this) 153 { 154 struct rlimit rlp; 155 if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) { 156 JNU_ThrowIOExceptionWithLastError(env, "getrlimit failed"); 157 return -1; 158 } 159 if (rlp.rlim_max == RLIM_INFINITY || 160 rlp.rlim_max > (rlim_t)java_lang_Integer_MAX_VALUE) { 161 return java_lang_Integer_MAX_VALUE; 162 } else { 163 return (jint)rlp.rlim_max; 164 } 165 } 166 167 JNIEXPORT jint JNICALL 168 Java_sun_nio_ch_IOUtil_iovMax(JNIEnv *env, jclass this) 169 { 170 jlong iov_max = sysconf(_SC_IOV_MAX); 171 if (iov_max == -1) 172 iov_max = 16; 173 return (jint)iov_max; 174 } 175 176 /* Declared in nio_util.h for use elsewhere in NIO */ 177 178 jint 179 convertReturnVal(JNIEnv *env, jint n, jboolean reading) 180 { 181 if (n > 0) /* Number of bytes written */ 182 return n; 183 else if (n == 0) { 184 if (reading) { 185 return IOS_EOF; /* EOF is -1 in javaland */ 186 } else { 187 return 0; 188 } 189 } 190 else if (errno == EAGAIN || errno == EWOULDBLOCK) 191 return IOS_UNAVAILABLE; 192 else if (errno == EINTR) 193 return IOS_INTERRUPTED; 194 else { 195 const char *msg = reading ? "Read failed" : "Write failed"; 196 JNU_ThrowIOExceptionWithLastError(env, msg); 197 return IOS_THROWN; 198 } 199 } 200 201 /* Declared in nio_util.h for use elsewhere in NIO */ 202 203 jlong 204 convertLongReturnVal(JNIEnv *env, jlong n, jboolean reading) 205 { 206 if (n > 0) /* Number of bytes written */ 207 return n; 208 else if (n == 0) { 209 if (reading) { 210 return IOS_EOF; /* EOF is -1 in javaland */ 211 } else { 212 return 0; 213 } 214 } 215 else if (errno == EAGAIN || errno == EWOULDBLOCK) 216 return IOS_UNAVAILABLE; 217 else if (errno == EINTR) 218 return IOS_INTERRUPTED; 219 else { 220 const char *msg = reading ? "Read failed" : "Write failed"; 221 JNU_ThrowIOExceptionWithLastError(env, msg); 222 return IOS_THROWN; 223 } 224 } 225 226 jint 227 fdval(JNIEnv *env, jobject fdo) 228 { 229 return (*env)->GetIntField(env, fdo, fd_fdID); 230 }