1 /* 2 * Copyright (c) 2000, 2009, 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 #include "sun_nio_ch_FileDispatcherImpl.h" 31 #include "java_lang_Long.h" 32 #include <sys/types.h> 33 #include <sys/socket.h> 34 #include <fcntl.h> 35 #include <sys/uio.h> 36 #include "nio.h" 37 #include "nio_util.h" 38 39 40 static int preCloseFD = -1; /* File descriptor to which we dup other fd's 41 before closing them for real */ 42 43 44 JNIEXPORT void JNICALL 45 Java_sun_nio_ch_FileDispatcherImpl_init(JNIEnv *env, jclass cl) 46 { 47 int sp[2]; 48 if (socketpair(PF_UNIX, SOCK_STREAM, 0, sp) < 0) { 49 JNU_ThrowIOExceptionWithLastError(env, "socketpair failed"); 50 return; 51 } 52 preCloseFD = sp[0]; 53 close(sp[1]); 54 } 55 56 JNIEXPORT jint JNICALL 57 Java_sun_nio_ch_FileDispatcherImpl_read0(JNIEnv *env, jclass clazz, 58 jobject fdo, jlong address, jint len) 59 { 60 jint fd = fdval(env, fdo); 61 void *buf = (void *)jlong_to_ptr(address); 62 63 return convertReturnVal(env, read(fd, buf, len), JNI_TRUE); 64 } 65 66 JNIEXPORT jint JNICALL 67 Java_sun_nio_ch_FileDispatcherImpl_pread0(JNIEnv *env, jclass clazz, jobject fdo, 68 jlong address, jint len, jlong offset) 69 { 70 jint fd = fdval(env, fdo); 71 void *buf = (void *)jlong_to_ptr(address); 72 73 return convertReturnVal(env, pread64(fd, buf, len, offset), JNI_TRUE); 74 } 75 76 JNIEXPORT jlong JNICALL 77 Java_sun_nio_ch_FileDispatcherImpl_readv0(JNIEnv *env, jclass clazz, 78 jobject fdo, jlong address, jint len) 79 { 80 jint fd = fdval(env, fdo); 81 struct iovec *iov = (struct iovec *)jlong_to_ptr(address); 82 if (len > 16) { 83 len = 16; 84 } 85 return convertLongReturnVal(env, readv(fd, iov, len), JNI_TRUE); 86 } 87 88 JNIEXPORT jint JNICALL 89 Java_sun_nio_ch_FileDispatcherImpl_write0(JNIEnv *env, jclass clazz, 90 jobject fdo, jlong address, jint len) 91 { 92 jint fd = fdval(env, fdo); 93 void *buf = (void *)jlong_to_ptr(address); 94 95 return convertReturnVal(env, write(fd, buf, len), JNI_FALSE); 96 } 97 98 JNIEXPORT jint JNICALL 99 Java_sun_nio_ch_FileDispatcherImpl_pwrite0(JNIEnv *env, jclass clazz, jobject fdo, 100 jlong address, jint len, jlong offset) 101 { 102 jint fd = fdval(env, fdo); 103 void *buf = (void *)jlong_to_ptr(address); 104 105 return convertReturnVal(env, pwrite64(fd, buf, len, offset), JNI_FALSE); 106 } 107 108 JNIEXPORT jlong JNICALL 109 Java_sun_nio_ch_FileDispatcherImpl_writev0(JNIEnv *env, jclass clazz, 110 jobject fdo, jlong address, jint len) 111 { 112 jint fd = fdval(env, fdo); 113 struct iovec *iov = (struct iovec *)jlong_to_ptr(address); 114 if (len > 16) { 115 len = 16; 116 } 117 return convertLongReturnVal(env, writev(fd, iov, len), JNI_FALSE); 118 } 119 120 static jlong 121 handle(JNIEnv *env, jlong rv, char *msg) 122 { 123 if (rv >= 0) 124 return rv; 125 if (errno == EINTR) 126 return IOS_INTERRUPTED; 127 JNU_ThrowIOExceptionWithLastError(env, msg); 128 return IOS_THROWN; 129 } 130 131 JNIEXPORT jint JNICALL 132 Java_sun_nio_ch_FileDispatcherImpl_force0(JNIEnv *env, jobject this, 133 jobject fdo, jboolean md) 134 { 135 jint fd = fdval(env, fdo); 136 int result = 0; 137 138 if (md == JNI_FALSE) { 139 result = fdatasync(fd); 140 } else { 141 result = fsync(fd); 142 } 143 return handle(env, result, "Force failed"); 144 } 145 146 JNIEXPORT jint JNICALL 147 Java_sun_nio_ch_FileDispatcherImpl_truncate0(JNIEnv *env, jobject this, 148 jobject fdo, jlong size) 149 { 150 return handle(env, 151 ftruncate64(fdval(env, fdo), size), 152 "Truncation failed"); 153 } 154 155 JNIEXPORT jlong JNICALL 156 Java_sun_nio_ch_FileDispatcherImpl_size0(JNIEnv *env, jobject this, jobject fdo) 157 { 158 struct stat64 fbuf; 159 160 if (fstat64(fdval(env, fdo), &fbuf) < 0) 161 return handle(env, -1, "Size failed"); 162 return fbuf.st_size; 163 } 164 165 JNIEXPORT jint JNICALL 166 Java_sun_nio_ch_FileDispatcherImpl_lock0(JNIEnv *env, jobject this, jobject fdo, 167 jboolean block, jlong pos, jlong size, 168 jboolean shared) 169 { 170 jint fd = fdval(env, fdo); 171 jint lockResult = 0; 172 int cmd = 0; 173 struct flock64 fl; 174 175 fl.l_whence = SEEK_SET; 176 if (size == (jlong)java_lang_Long_MAX_VALUE) { 177 fl.l_len = (off64_t)0; 178 } else { 179 fl.l_len = (off64_t)size; 180 } 181 fl.l_start = (off64_t)pos; 182 if (shared == JNI_TRUE) { 183 fl.l_type = F_RDLCK; 184 } else { 185 fl.l_type = F_WRLCK; 186 } 187 if (block == JNI_TRUE) { 188 cmd = F_SETLKW64; 189 } else { 190 cmd = F_SETLK64; 191 } 192 lockResult = fcntl(fd, cmd, &fl); 193 if (lockResult < 0) { 194 if ((cmd == F_SETLK64) && (errno == EAGAIN || errno == EACCES)) 195 return sun_nio_ch_FileDispatcherImpl_NO_LOCK; 196 if (errno == EINTR) 197 return sun_nio_ch_FileDispatcherImpl_INTERRUPTED; 198 JNU_ThrowIOExceptionWithLastError(env, "Lock failed"); 199 } 200 return 0; 201 } 202 203 JNIEXPORT void JNICALL 204 Java_sun_nio_ch_FileDispatcherImpl_release0(JNIEnv *env, jobject this, 205 jobject fdo, jlong pos, jlong size) 206 { 207 jint fd = fdval(env, fdo); 208 jint lockResult = 0; 209 struct flock64 fl; 210 int cmd = F_SETLK64; 211 212 fl.l_whence = SEEK_SET; 213 if (size == (jlong)java_lang_Long_MAX_VALUE) { 214 fl.l_len = (off64_t)0; 215 } else { 216 fl.l_len = (off64_t)size; 217 } 218 fl.l_start = (off64_t)pos; 219 fl.l_type = F_UNLCK; 220 lockResult = fcntl(fd, cmd, &fl); 221 if (lockResult < 0) { 222 JNU_ThrowIOExceptionWithLastError(env, "Release failed"); 223 } 224 } 225 226 227 static void closeFileDescriptor(JNIEnv *env, int fd) { 228 if (fd != -1) { 229 int result = close(fd); 230 if (result < 0) 231 JNU_ThrowIOExceptionWithLastError(env, "Close failed"); 232 } 233 } 234 235 JNIEXPORT void JNICALL 236 Java_sun_nio_ch_FileDispatcherImpl_close0(JNIEnv *env, jclass clazz, jobject fdo) 237 { 238 jint fd = fdval(env, fdo); 239 closeFileDescriptor(env, fd); 240 } 241 242 JNIEXPORT void JNICALL 243 Java_sun_nio_ch_FileDispatcherImpl_preClose0(JNIEnv *env, jclass clazz, jobject fdo) 244 { 245 jint fd = fdval(env, fdo); 246 if (preCloseFD >= 0) { 247 if (dup2(preCloseFD, fd) < 0) 248 JNU_ThrowIOExceptionWithLastError(env, "dup2 failed"); 249 } 250 } 251 252 JNIEXPORT void JNICALL 253 Java_sun_nio_ch_FileDispatcherImpl_closeIntFD(JNIEnv *env, jclass clazz, jint fd) 254 { 255 closeFileDescriptor(env, fd); 256 }