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