blob: 4d987b91f05d624d4d38c0e31c8bc8c39b993740 [file] [log] [blame]
Piotr Jastrzebski51b1b692015-02-16 15:01:09 +00001/*
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}