45 |
* Some of this coded adopted from the gcj native libraries |
* Some of this coded adopted from the gcj native libraries |
46 |
*/ |
*/ |
47 |
|
|
48 |
|
/* do not move; needed here because of some macro definitions */ |
49 |
#include <config.h> |
#include <config.h> |
50 |
|
|
51 |
/* FIXME: Need to make configure set these for us */ |
/* FIXME: Need to make configure set these for us */ |
55 |
#define HAVE_FSYNC |
#define HAVE_FSYNC |
56 |
#define HAVE_SELECT |
#define HAVE_SELECT |
57 |
|
|
58 |
#include <stdio.h> |
#include <jni.h> |
59 |
#include <stdlib.h> |
#include "jcl.h" |
|
#include <string.h> |
|
|
#include <sys/types.h> |
|
|
#include <sys/time.h> |
|
|
#include <sys/stat.h> |
|
|
#include <errno.h> |
|
|
#include <fcntl.h> |
|
|
#include <unistd.h> |
|
|
|
|
|
#ifdef HAVE_SYS_IOCTL_H |
|
|
#define BSD_COMP /* Get FIONREAD on Solaris2 */ |
|
|
#include <sys/ioctl.h> |
|
|
#endif |
|
60 |
|
|
61 |
#ifdef HAVE_SYS_FILIO_H /* Get FIONREAD on Solaris 2.5 */ |
#include "target_native.h" |
62 |
#include <sys/filio.h> |
#ifndef WITHOUT_FILESYSTEM |
63 |
|
#include "target_native_file.h" |
64 |
#endif |
#endif |
65 |
|
#include "target_native_math_int.h" |
66 |
|
|
|
#include <jni.h> |
|
|
|
|
|
#include "jcl.h" |
|
67 |
#include "java_io_FileDescriptor.h" |
#include "java_io_FileDescriptor.h" |
68 |
|
|
69 |
// FIXME: This can't be right. Need converter macros |
// FIXME: This can't be right. Need converter macros |
70 |
#define CONVERT_JLONG_TO_INT(x) ((int)(x & 0xFFFFFFFF)) |
#define CONVERT_JLONG_TO_INT(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x) |
71 |
|
#define CONVERT_INT_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x) |
72 |
|
|
73 |
// FIXME: This can't be right. Need converter macros |
// FIXME: This can't be right. Need converter macros |
74 |
#define CONVERT_JLONG_TO_OFF_T(x) (x) |
#define CONVERT_JLONG_TO_OFF_T(x) TARGET_NATIVE_MATH_INT_INT64_TO_INT32(x) |
75 |
|
#define CONVERT_OFF_T_TO_JLONG(x) TARGET_NATIVE_MATH_INT_INT32_TO_INT64(x) |
76 |
|
|
77 |
// FIXME: This can't be right. Need converter macros |
// FIXME: This can't be right. Need converter macros |
78 |
#define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF)) |
#define CONVERT_JINT_TO_INT(x) ((int)(x & 0xFFFFFFFF)) |
79 |
|
#define CONVERT_INT_TO_JINT(x) ((int)(x & 0xFFFFFFFF)) |
80 |
|
|
81 |
// FIXME: This can't be right. Need converter macros |
// FIXME: This can't be right. Need converter macros |
82 |
#define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF)) |
#define CONVERT_SSIZE_T_TO_JINT(x) ((jint)(x & 0xFFFFFFFF)) |
83 |
|
#define CONVERT_JINT_TO_SSIZE_T(x) (x) |
84 |
|
|
85 |
/* These values must be kept in sync with FileDescriptor.java. */ |
/* These values must be kept in sync with FileDescriptor.java. */ |
86 |
#define SET 0 |
#define SET 0 |
87 |
#define CUR 1 |
#define CUR 1 |
88 |
#define END 2 |
#define END 2 |
89 |
#define READ 1 |
#define READ 1 |
90 |
#define WRITE 2 |
#define WRITE 2 |
91 |
#define APPEND 4 |
#define APPEND 4 |
92 |
#define EXCL 8 |
#define EXCL 8 |
93 |
#define SYNC 16 |
#define SYNC 16 |
94 |
#define DSYNC 32 |
#define DSYNC 32 |
|
|
|
95 |
|
|
96 |
/*************************************************************************/ |
/*************************************************************************/ |
97 |
|
|
124 |
INIT_FIELD ("in", 0); |
INIT_FIELD ("in", 0); |
125 |
INIT_FIELD ("out", 1); |
INIT_FIELD ("out", 1); |
126 |
INIT_FIELD ("err", 2); |
INIT_FIELD ("err", 2); |
127 |
|
|
128 |
|
#undef INIT_FIELD |
129 |
} |
} |
130 |
|
|
131 |
/*************************************************************************/ |
/*************************************************************************/ |
136 |
Java_java_io_FileDescriptor_nativeOpen(JNIEnv *env, jobject obj, jstring name, |
Java_java_io_FileDescriptor_nativeOpen(JNIEnv *env, jobject obj, jstring name, |
137 |
jint jflags) |
jint jflags) |
138 |
{ |
{ |
139 |
int rc; |
const char *filename; |
140 |
char *cname; |
int flags; |
141 |
int flags; |
int permissions; |
142 |
int mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH; |
int native_fd; |
143 |
|
int result; |
144 |
|
|
145 |
cname = JCL_jstring_to_cstring(env, name); |
filename = JCL_jstring_to_cstring(env, name); |
146 |
if (!cname) |
if (filename == NULL) |
147 |
return(-1); /* Exception will already have been thrown */ |
return(-1); /* Exception will already have been thrown */ |
148 |
|
|
149 |
flags = 0; |
/* get file/permission flags for open() */ |
|
#ifdef O_BINARY |
|
|
flags |= O_BINARY; |
|
|
#endif |
|
|
|
|
|
/* We don't have to do any checking of the flags, as it is all done |
|
|
in FileDescriptor. We can assume everything is ok. */ |
|
150 |
if ((jflags & READ) && (jflags & WRITE)) |
if ((jflags & READ) && (jflags & WRITE)) |
151 |
flags |= O_RDWR | O_CREAT; |
{ |
152 |
|
/* read/write */ |
153 |
|
flags = TARGET_NATIVE_FILE_FILEFLAG_CREATE | TARGET_NATIVE_FILE_FILEFLAG_READWRITE; |
154 |
|
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; |
155 |
|
} |
156 |
else if ((jflags & READ)) |
else if ((jflags & READ)) |
157 |
flags |= O_RDONLY; |
{ |
158 |
|
/* read */ |
159 |
|
flags = TARGET_NATIVE_FILE_FILEFLAG_READ; |
160 |
|
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; |
161 |
|
} |
162 |
else |
else |
163 |
{ |
{ |
164 |
flags |= O_WRONLY | O_CREAT; |
/* write */ |
165 |
|
flags = TARGET_NATIVE_FILE_FILEFLAG_CREATE | TARGET_NATIVE_FILE_FILEFLAG_WRITE; |
166 |
if ((jflags & APPEND)) |
if ((jflags & APPEND)) |
167 |
flags |= O_APPEND; |
{ |
168 |
|
flags |= TARGET_NATIVE_FILE_FILEFLAG_APPEND; |
169 |
|
} |
170 |
else |
else |
171 |
flags |= O_TRUNC; |
{ |
172 |
|
flags |= TARGET_NATIVE_FILE_FILEFLAG_TRUNCATE; |
173 |
if ((jflags & EXCL)) |
} |
174 |
{ |
permissions = TARGET_NATIVE_FILE_FILEPERMISSION_NORMAL; |
|
/* In this case we are making a temp file. */ |
|
|
flags |= O_EXCL; |
|
|
mode = S_IRUSR | S_IWUSR; |
|
|
} |
|
175 |
} |
} |
176 |
|
|
177 |
if ((jflags & SYNC)) |
if ((jflags & SYNC)) |
178 |
flags |= O_SYNC; |
{ |
179 |
|
flags |= TARGET_NATIVE_FILE_FILEFLAG_SYNC; |
180 |
|
} |
181 |
|
|
|
#ifdef O_DSYNC |
|
182 |
if ((jflags & DSYNC)) |
if ((jflags & DSYNC)) |
183 |
flags |= O_DSYNC; |
{ |
184 |
#else |
flags |= TARGET_NATIVE_FILE_FILEFLAG_DSYNC; |
185 |
// If O_DSYNC doesnt exist use O_SYNC instead. |
} |
186 |
if ((jflags & DSYNC)) |
#ifdef O_BINARY |
187 |
flags |= O_SYNC; |
flags |= TARGET_NATIVE_FILE_FILEFLAG_BINARY; |
188 |
#endif |
#endif |
189 |
|
|
190 |
rc = open (cname, flags, mode); |
TARGET_NATIVE_FILE_OPEN(filename,native_fd,flags,permissions,result); |
191 |
|
(*env)->ReleaseStringUTFChars(env, name, filename); |
|
(*env)->ReleaseStringUTFChars(env, name, cname); |
|
192 |
|
|
193 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
194 |
{ |
{ |
195 |
/* We can only throw FileNotFoundException. */ |
/* We can only throw FileNotFoundException. */ |
196 |
JCL_ThrowException(env,"java/io/FileNotFoundException", strerror(errno)); |
JCL_ThrowException(env, |
197 |
|
"java/io/FileNotFoundException", |
198 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
199 |
|
return JNI_JLONG_CONST_MINUS_1; |
200 |
} |
} |
201 |
|
|
202 |
return rc; |
return CONVERT_INT_TO_JLONG(native_fd); |
203 |
} |
} |
204 |
|
|
205 |
/*************************************************************************/ |
/*************************************************************************/ |
210 |
JNIEXPORT jlong JNICALL |
JNIEXPORT jlong JNICALL |
211 |
Java_java_io_FileDescriptor_nativeClose(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeClose(JNIEnv *env, jobject obj, jlong fd) |
212 |
{ |
{ |
213 |
int rc, native_fd; |
int native_fd; |
214 |
|
int result; |
215 |
|
|
216 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
217 |
|
|
218 |
rc = close(native_fd); |
TARGET_NATIVE_FILE_CLOSE(native_fd,result); |
219 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
220 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
{ |
221 |
|
JCL_ThrowException(env, |
222 |
|
"java/io/IOException", |
223 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
224 |
|
return(JNI_JLONG_CONST_MINUS_1); |
225 |
|
} |
226 |
|
|
227 |
return(rc); |
return(JNI_JLONG_CONST_0); |
228 |
} |
} |
229 |
|
|
230 |
/*************************************************************************/ |
/*************************************************************************/ |
236 |
Java_java_io_FileDescriptor_nativeWriteByte(JNIEnv *env, jobject obj, |
Java_java_io_FileDescriptor_nativeWriteByte(JNIEnv *env, jobject obj, |
237 |
jlong fd, jint b) |
jlong fd, jint b) |
238 |
{ |
{ |
239 |
int native_fd; |
int native_fd; |
240 |
int native_byte; |
char native_data; |
241 |
char buf[1]; |
ssize_t bytes_written; |
242 |
ssize_t rc; |
int result; |
243 |
|
|
244 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
245 |
native_byte = CONVERT_JINT_TO_INT(b); |
native_data = (char)(CONVERT_JINT_TO_INT(b) & 0xFF); |
246 |
buf[0] = (char)(native_byte & 0xFF); |
|
247 |
|
do |
248 |
while (rc != 1) |
{ |
249 |
{ |
TARGET_NATIVE_FILE_WRITE(native_fd, &native_data, 1, bytes_written, result); |
250 |
rc = write(fd, buf, 1); |
if ((result != TARGET_NATIVE_OK) |
251 |
if ((rc == -1) && (errno != EINTR)) |
&& (TARGET_NATIVE_LAST_ERROR() != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) |
252 |
{ |
{ |
253 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
254 |
return(-1); |
"java/io/IOException", |
255 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
256 |
|
return(JNI_JLONG_CONST_MINUS_1); |
257 |
} |
} |
258 |
} |
} |
259 |
|
while (result != TARGET_NATIVE_OK); |
260 |
|
|
261 |
return(0); |
return(JNI_JLONG_CONST_0); |
262 |
} |
} |
263 |
|
|
264 |
/*************************************************************************/ |
/*************************************************************************/ |
271 |
jlong fd, jbyteArray buf, |
jlong fd, jbyteArray buf, |
272 |
jint offset, jint len) |
jint offset, jint len) |
273 |
{ |
{ |
274 |
int native_fd; |
int native_fd; |
275 |
ssize_t rc, bytes_written = 0; |
jbyte *bufptr; |
276 |
jbyte *bufptr; |
ssize_t bytes_written; |
277 |
|
ssize_t n; |
278 |
|
int result; |
279 |
|
|
280 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
281 |
|
|
283 |
if (!bufptr) |
if (!bufptr) |
284 |
{ |
{ |
285 |
JCL_ThrowException(env, "java/io/IOException", "Unexpected JNI error"); |
JCL_ThrowException(env, "java/io/IOException", "Unexpected JNI error"); |
286 |
return(-1); |
return(JNI_JLONG_CONST_MINUS_1); |
287 |
} |
} |
288 |
|
|
289 |
while (bytes_written < len) |
bytes_written = 0; |
290 |
|
while (bytes_written < CONVERT_JINT_TO_SSIZE_T(len)) |
291 |
{ |
{ |
292 |
rc = write(fd, (bufptr + offset + bytes_written), (len - bytes_written)); |
TARGET_NATIVE_FILE_WRITE(native_fd, (bufptr + offset + bytes_written), (len - bytes_written), n, result); |
293 |
if ((rc == -1) && (errno != EINTR)) |
if ((result != TARGET_NATIVE_OK) |
294 |
|
&& (TARGET_NATIVE_LAST_ERROR() != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) |
295 |
{ |
{ |
296 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
297 |
|
"java/io/IOException", |
298 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
299 |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
300 |
return(-1); |
return(JNI_JLONG_CONST_MINUS_1); |
301 |
} |
} |
302 |
bytes_written += rc; |
bytes_written += n; |
303 |
} |
} |
304 |
|
|
305 |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
306 |
return(0); |
|
307 |
|
return(JNI_JLONG_CONST_0); |
308 |
} |
} |
309 |
|
|
310 |
/*************************************************************************/ |
/*************************************************************************/ |
315 |
JNIEXPORT jint JNICALL |
JNIEXPORT jint JNICALL |
316 |
Java_java_io_FileDescriptor_nativeReadByte(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeReadByte(JNIEnv *env, jobject obj, jlong fd) |
317 |
{ |
{ |
318 |
int native_fd; |
int native_fd; |
319 |
jbyte b; |
char data; |
320 |
ssize_t rc; |
ssize_t bytes_read; |
321 |
|
int result; |
322 |
|
|
323 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
324 |
|
|
325 |
while (rc != 1) |
bytes_read = 0; |
326 |
|
do |
327 |
{ |
{ |
328 |
rc = read(fd, &b, 1); |
TARGET_NATIVE_FILE_READ(native_fd, &data, 1, bytes_read, result); |
329 |
if (rc == 0) |
if ((result == TARGET_NATIVE_OK) && (bytes_read == 0)) |
330 |
return(-1); /* Signal end of file to Java */ |
{ |
331 |
if ((rc == -1) && (errno != EINTR)) |
return(-1); |
332 |
|
} |
333 |
|
if ((result != TARGET_NATIVE_OK) |
334 |
|
&& (TARGET_NATIVE_LAST_ERROR() != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) |
335 |
{ |
{ |
336 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
337 |
|
"java/io/IOException", |
338 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
339 |
return(-1); |
return(-1); |
340 |
} |
} |
341 |
} |
} |
342 |
return(b & 0xFF); |
while (bytes_read != 1); |
343 |
|
|
344 |
|
return((jint)(data & 0xFF)); |
345 |
} |
} |
346 |
|
|
347 |
/*************************************************************************/ |
/*************************************************************************/ |
354 |
jlong fd, jarray buf, jint offset, |
jlong fd, jarray buf, jint offset, |
355 |
jint len) |
jint len) |
356 |
{ |
{ |
357 |
int native_fd; |
int native_fd; |
358 |
ssize_t rc, bytes_read = 0; |
jbyte *bufptr; |
359 |
jbyte *bufptr; |
ssize_t bytes_read; |
360 |
|
ssize_t n; |
361 |
|
int result; |
362 |
|
|
363 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
364 |
|
|
369 |
return(-1); |
return(-1); |
370 |
} |
} |
371 |
|
|
372 |
|
bytes_read = 0; |
373 |
while (bytes_read < len) |
while (bytes_read < len) |
374 |
{ |
{ |
375 |
rc = read(fd, (bufptr + offset + bytes_read), (len - bytes_read)); |
TARGET_NATIVE_FILE_READ(native_fd, (bufptr + offset + bytes_read), (len - bytes_read), n, result); |
376 |
|
if ((result == TARGET_NATIVE_OK) && (n == 0)) |
|
if (rc == 0) |
|
377 |
{ |
{ |
378 |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
379 |
if (bytes_read == 0) |
if (bytes_read == 0) |
381 |
else |
else |
382 |
return(CONVERT_SSIZE_T_TO_JINT(bytes_read)); |
return(CONVERT_SSIZE_T_TO_JINT(bytes_read)); |
383 |
} |
} |
384 |
|
if ((result != TARGET_NATIVE_OK) |
385 |
if ((rc == -1) && (errno != EINTR)) |
&& (TARGET_NATIVE_LAST_ERROR() != TARGET_NATIVE_ERROR_INTERRUPT_FUNCTION_CALL)) |
386 |
{ |
{ |
387 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
388 |
|
"java/io/IOException", |
389 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
390 |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
391 |
return(-1); |
return(-1); |
392 |
} |
} |
393 |
bytes_read += rc; |
bytes_read += n; |
394 |
} |
} |
395 |
|
|
396 |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
(*env)->ReleaseByteArrayElements(env, buf, bufptr, 0); |
405 |
JNIEXPORT jint JNICALL |
JNIEXPORT jint JNICALL |
406 |
Java_java_io_FileDescriptor_nativeAvailable(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeAvailable(JNIEnv *env, jobject obj, jlong fd) |
407 |
{ |
{ |
408 |
#if defined(FIONREAD) || defined(HAVE_SELECT) || defined(HAVE_FSTAT) |
int native_fd; |
409 |
int native_fd, found = 0; |
jlong bytes_available; |
410 |
ssize_t num = 0, rc; |
int result; |
|
off_t cur_pos; |
|
|
struct stat sb; |
|
|
fd_set fds; |
|
|
struct timeval tv; |
|
411 |
|
|
412 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
413 |
|
|
414 |
#if defined(FIONREAD) |
TARGET_NATIVE_FILE_AVAILABLE(native_fd,bytes_available,result); |
415 |
rc = ioctl(native_fd, FIONREAD, &num); |
if (result != TARGET_NATIVE_OK) |
|
if (rc == -1) /* We don't care if this fails. Try something else */ |
|
|
{ |
|
|
rc = 0; |
|
|
num = 0; |
|
|
} |
|
|
else |
|
|
{ |
|
|
found = 1; |
|
|
} |
|
|
#endif /* defined FIONREAD */ |
|
|
#if defined (HAVE_FSTAT) |
|
|
if (!found) |
|
416 |
{ |
{ |
417 |
rc = fstat(native_fd, &sb); |
JCL_ThrowException(env, |
418 |
if (rc != -1) /* Don't bomb here either - just try the next method */ |
"java/io/IOException", |
419 |
{ |
TARGET_NATIVE_LAST_ERROR_STRING()); |
420 |
if (S_ISREG(sb.st_mode)) |
return(0); |
|
{ |
|
|
cur_pos = lseek(native_fd, 0, SEEK_CUR); |
|
|
if (cur_pos != 1) |
|
|
{ |
|
|
num = (ssize_t)(sb.st_size - cur_pos); |
|
|
found = 1; |
|
|
} |
|
|
} |
|
|
} |
|
421 |
} |
} |
|
#endif /* defined HAVE_FSTAT */ |
|
|
#if defined (HAVE_SELECT) |
|
|
if (!found) |
|
|
{ |
|
|
FD_ZERO(&fds); |
|
|
FD_SET(native_fd, &fds); |
|
|
memset(&tv, 0, sizeof(struct timeval)); |
|
|
|
|
|
rc = select(native_fd + 1, &fds, 0, 0, &tv); |
|
|
if (rc == -1) /* Finally, we give up */ |
|
|
{ |
|
|
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
|
|
return(-1); |
|
|
} |
|
|
found = 1; |
|
|
if (rc == 0) |
|
|
num = 0; /* Nothing to read here */ |
|
|
else |
|
|
num = 1; /* We know there is something, but not how much */ |
|
|
} |
|
|
#endif /* defined HAVE_SELECT */ |
|
|
|
|
|
if (!found) |
|
|
return(0); |
|
|
else |
|
|
return(CONVERT_SSIZE_T_TO_JINT(num)); |
|
422 |
|
|
423 |
#else /* defined FIONREAD, HAVE_SELECT, HAVE_FSTAT */ |
// FIXME NYI ??? why only jint and not jlong? |
424 |
/* FIXME: Probably operation isn't supported, but this exception |
return(TARGET_NATIVE_MATH_INT_INT64_TO_INT32(bytes_available)); |
|
* is too harsh as it will probably crash the program without need |
|
|
JCL_ThrowException(env, "java/lang/UnsupportedOperationException", |
|
|
"not implemented - can't shorten files on this platform"); |
|
|
|
|
|
This even seems rather harsh |
|
|
JCL_ThrowException(env, "java/io/IOException", |
|
|
"Unable to shorten file length"); |
|
|
*/ |
|
|
return(0); |
|
|
#endif |
|
425 |
} |
} |
426 |
|
|
427 |
/*************************************************************************/ |
/*************************************************************************/ |
434 |
jlong offset, jint whence, |
jlong offset, jint whence, |
435 |
jboolean stop_at_eof) |
jboolean stop_at_eof) |
436 |
{ |
{ |
437 |
int native_fd; |
int native_fd; |
438 |
off_t rc, native_offset, cur_pos, file_size; |
jlong file_size; |
439 |
struct stat sb; |
jlong current_offset, new_offset; |
440 |
|
int result; |
441 |
|
|
442 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
443 |
native_offset = CONVERT_JLONG_TO_OFF_T(offset); |
|
444 |
|
#if 0 |
445 |
|
/* Should there be such an exception? All native layer macros should |
446 |
|
be accepting 64bit-values if needed. It some target is not able |
447 |
|
to handle such values it should simply operate with 32bit-values |
448 |
|
and convert 64bit-values appriopated. In this case I assume |
449 |
|
problems should not occurre: if some specific target is not able |
450 |
|
to handle 64bit-values the system is limited to 32bit at all, thus |
451 |
|
the application can not do a seek() or something else beyond the |
452 |
|
32bit limit. It this true? |
453 |
|
*/ |
454 |
|
|
455 |
/* FIXME: What do we do if offset > the max value of off_t on this 32bit |
/* FIXME: What do we do if offset > the max value of off_t on this 32bit |
456 |
* system? How do we detect that and what do we do? */ |
* system? How do we detect that and what do we do? */ |
457 |
if ((jlong)native_offset != offset) |
if (CONVERT_OFF_T_TO_JLONG(native_offset) != offset) |
458 |
{ |
{ |
459 |
JCL_ThrowException(env, "java/io/IOException", |
JCL_ThrowException(env, "java/io/IOException", |
460 |
"Cannot represent position correctly on this system"); |
"Cannot represent position correctly on this system"); |
461 |
return(-1); |
return(JNI_JLONG_CONST_MINUS_1); |
462 |
} |
} |
463 |
|
#endif |
464 |
|
|
465 |
if (stop_at_eof) |
if (stop_at_eof) |
466 |
{ |
{ |
467 |
rc = fstat(native_fd, &sb); |
/* get file size */ |
468 |
file_size = sb.st_size; |
TARGET_NATIVE_FILE_SIZE(native_fd, file_size, result); |
469 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
470 |
{ |
{ |
471 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
472 |
return(-1); |
"java/io/IOException", |
473 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
474 |
|
return(JNI_JLONG_CONST_MINUS_1); |
475 |
} |
} |
476 |
if (whence == SET) |
|
477 |
|
/* set file read/write position (seek) */ |
478 |
|
if (whence == SET) |
479 |
{ |
{ |
480 |
if (native_offset > file_size) |
if (TARGET_NATIVE_MATH_INT_INT64_GT(offset,file_size)) |
481 |
native_offset = file_size; |
offset = file_size; |
482 |
} |
} |
483 |
else if (whence == CUR) |
else if (whence == CUR) |
484 |
{ |
{ |
485 |
cur_pos = lseek(native_fd, 0, SEEK_CUR); |
TARGET_NATIVE_FILE_TELL(native_fd, current_offset, result); |
486 |
if (cur_pos == -1) |
if (result != TARGET_NATIVE_OK) |
487 |
{ |
{ |
488 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
489 |
return(-1); |
"java/io/IOException", |
490 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
491 |
|
return(JNI_JLONG_CONST_MINUS_1); |
492 |
} |
} |
493 |
if ((cur_pos + native_offset) > file_size) |
if (TARGET_NATIVE_MATH_INT_INT64_GT(TARGET_NATIVE_MATH_INT_INT64_ADD(current_offset,offset),file_size)) |
494 |
{ |
{ |
495 |
native_offset = file_size; |
offset = file_size; |
496 |
whence = SET; |
whence = SET; |
497 |
} |
} |
498 |
} |
} |
499 |
else if (native_offset > 0) /* Default to END case */ |
else if (TARGET_NATIVE_MATH_INT_INT64_GT(offset,0)) /* Default to END case */ |
500 |
{ |
{ |
501 |
native_offset = 0; |
offset = JNI_JLONG_CONST_0; |
502 |
} |
} |
503 |
} |
} |
504 |
|
|
505 |
/* Now do it */ |
/* Now do it */ |
506 |
rc = -1; |
result = TARGET_NATIVE_ERROR; |
507 |
|
new_offset = JNI_JLONG_CONST_MINUS_1; |
508 |
if (whence == SET) |
if (whence == SET) |
509 |
rc = lseek(native_fd, native_offset, SEEK_SET); |
TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, offset, new_offset, result); |
510 |
if (whence == CUR) |
if (whence == CUR) |
511 |
rc = lseek(native_fd, native_offset, SEEK_CUR); |
TARGET_NATIVE_FILE_SEEK_CURRENT(native_fd, offset, new_offset, result); |
512 |
if (whence == END) |
if (whence == END) |
513 |
rc = lseek(native_fd, native_offset, SEEK_END); |
TARGET_NATIVE_FILE_SEEK_END(native_fd, offset, new_offset, result); |
514 |
|
|
515 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
516 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
{ |
517 |
return(rc); |
JCL_ThrowException(env, |
518 |
|
"java/io/IOException", |
519 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
520 |
|
return(JNI_JLONG_CONST_MINUS_1); |
521 |
|
} |
522 |
|
|
523 |
|
return(new_offset); |
524 |
} |
} |
525 |
|
|
526 |
/*************************************************************************/ |
/*************************************************************************/ |
532 |
Java_java_io_FileDescriptor_nativeGetFilePointer(JNIEnv *env, jobject obj, |
Java_java_io_FileDescriptor_nativeGetFilePointer(JNIEnv *env, jobject obj, |
533 |
jlong fd) |
jlong fd) |
534 |
{ |
{ |
535 |
int native_fd; |
int native_fd; |
536 |
off_t rc; |
jlong current_offset; |
537 |
|
int result; |
538 |
|
|
539 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
540 |
|
|
541 |
rc = lseek(native_fd, 0, SEEK_CUR); |
TARGET_NATIVE_FILE_TELL(native_fd, current_offset, result); |
542 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
543 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
{ |
544 |
|
JCL_ThrowException(env, |
545 |
|
"java/io/IOException", |
546 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
547 |
|
return(JNI_JLONG_CONST_MINUS_1); |
548 |
|
} |
549 |
|
|
550 |
return(rc); |
return(current_offset); |
551 |
} |
} |
552 |
|
|
553 |
/*************************************************************************/ |
/*************************************************************************/ |
558 |
JNIEXPORT jlong JNICALL |
JNIEXPORT jlong JNICALL |
559 |
Java_java_io_FileDescriptor_nativeGetLength(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeGetLength(JNIEnv *env, jobject obj, jlong fd) |
560 |
{ |
{ |
561 |
int rc, native_fd; |
int native_fd; |
562 |
struct stat sb; |
jlong file_size; |
563 |
|
int result; |
564 |
|
|
565 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
566 |
|
|
567 |
rc = fstat(native_fd, &sb); |
TARGET_NATIVE_FILE_SIZE(native_fd, file_size, result); |
568 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
569 |
{ |
{ |
570 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
571 |
return(-1); |
"java/io/IOException", |
572 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
573 |
|
return(JNI_JLONG_CONST_MINUS_1); |
574 |
} |
} |
575 |
|
|
576 |
return(sb.st_size); |
return(file_size); |
577 |
} |
} |
578 |
|
|
579 |
/*************************************************************************/ |
/*************************************************************************/ |
585 |
Java_java_io_FileDescriptor_nativeSetLength(JNIEnv *env, jobject obj, |
Java_java_io_FileDescriptor_nativeSetLength(JNIEnv *env, jobject obj, |
586 |
jlong fd, jlong len) |
jlong fd, jlong len) |
587 |
{ |
{ |
588 |
int native_fd; |
int native_fd; |
589 |
off_t rc, native_len, save_pos; |
jlong file_size; |
590 |
struct stat sb; |
int bytes_written; |
591 |
char c = '\0'; |
jlong save_offset,new_offset; |
592 |
|
char data; |
593 |
|
int result; |
594 |
|
|
595 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
596 |
native_len = CONVERT_JLONG_TO_OFF_T(len); |
|
597 |
|
#if 0 |
598 |
|
/* Should there be such an exception? All native layer macros should |
599 |
|
be accepting 64bit-values if needed. It some target is not able |
600 |
|
to handle such values it should simply operate with 32bit-values |
601 |
|
and convert 64bit-values appriopated. In this case I assume |
602 |
|
problems should not occurre: if some specific target is not able |
603 |
|
to handle 64bit-values the system is limited to 32bit at all, thus |
604 |
|
the application can not do a seek() or something else beyond the |
605 |
|
32bit limit. It this true? |
606 |
|
*/ |
607 |
|
|
608 |
/* FIXME: What do we do if len > the max value of off_t on this 32bit |
/* FIXME: What do we do if len > the max value of off_t on this 32bit |
609 |
* system? How do we detect that and what do we do? */ |
* system? How do we detect that and what do we do? */ |
610 |
if ((jlong)native_len != len) |
if (CONVERT_OFF_T_TO_JLONG(native_len) != len) |
611 |
{ |
{ |
612 |
JCL_ThrowException(env, "java/io/IOException", |
JCL_ThrowException(env, "java/io/IOException", |
613 |
"Cannot represent position correctly on this system"); |
"Cannot represent position correctly on this system"); |
614 |
return; |
return; |
615 |
} |
} |
616 |
|
#endif |
617 |
rc = fstat(native_fd, &sb); |
|
618 |
if (rc == -1) |
/* get file size */ |
619 |
{ |
TARGET_NATIVE_FILE_SIZE(native_fd, file_size, result); |
620 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
if (result != TARGET_NATIVE_OK) |
621 |
|
{ |
622 |
|
JCL_ThrowException(env, |
623 |
|
"java/io/IOException", |
624 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
625 |
return; |
return; |
626 |
} |
} |
627 |
|
|
628 |
/* Lucky us, perfect size */ |
if (TARGET_NATIVE_MATH_INT_INT64_LT(file_size,len)) |
|
if ((jlong)sb.st_size == len) |
|
|
return; |
|
|
|
|
|
/* File is too short -- seek to one byte short of where we want, |
|
|
* then write a byte */ |
|
|
if ((jlong)sb.st_size < len) |
|
629 |
{ |
{ |
630 |
|
/* File is too short -- seek to one byte short of where we want, |
631 |
|
* then write a byte */ |
632 |
|
|
633 |
/* Save off current position */ |
/* Save off current position */ |
634 |
save_pos = lseek(native_fd, 0, SEEK_CUR); |
TARGET_NATIVE_FILE_TELL(native_fd, save_offset, result); |
635 |
if (save_pos != -1) |
if (result != TARGET_NATIVE_OK) |
|
rc = lseek(native_fd, native_len - 1, SEEK_SET); |
|
|
if ((save_pos == -1) || (rc == -1)) |
|
636 |
{ |
{ |
637 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
638 |
|
"java/io/IOException", |
639 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
640 |
|
return; |
641 |
|
} |
642 |
|
|
643 |
|
/* move to position n-1 */ |
644 |
|
TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, TARGET_NATIVE_MATH_INT_INT64_SUB(len,1), new_offset, result); |
645 |
|
if (result != TARGET_NATIVE_OK) |
646 |
|
{ |
647 |
|
JCL_ThrowException(env, |
648 |
|
"java/io/IOException", |
649 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
650 |
return; |
return; |
651 |
} |
} |
652 |
|
|
653 |
/* Note: This will fail if we somehow get here in read only mode |
/* write a byte |
654 |
|
Note: This will fail if we somehow get here in read only mode |
655 |
* That shouldn't happen */ |
* That shouldn't happen */ |
656 |
rc = write(native_fd, &c, 1); |
data='\0'; |
657 |
if (rc == -1) |
TARGET_NATIVE_FILE_WRITE(native_fd, &data, 1, bytes_written, result); |
658 |
{ |
if (result != TARGET_NATIVE_OK) |
659 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
{ |
660 |
|
JCL_ThrowException(env, |
661 |
|
"java/io/IOException", |
662 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
663 |
return; |
return; |
664 |
} |
} |
665 |
|
|
666 |
/* Reposition file pointer to where we started */ |
/* Reposition file pointer to where we started */ |
667 |
rc = lseek(native_fd, save_pos, SEEK_SET); |
TARGET_NATIVE_FILE_SEEK_BEGIN(native_fd, save_offset, new_offset, result); |
668 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
669 |
{ |
{ |
670 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
JCL_ThrowException(env, |
671 |
|
"java/io/IOException", |
672 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
673 |
return; |
return; |
674 |
} |
} |
|
return; |
|
675 |
} |
} |
676 |
|
else if (TARGET_NATIVE_MATH_INT_INT64_GT(file_size,len)) |
|
/* File is too long - use ftruncate if available */ |
|
|
#ifdef HAVE_FTRUNCATE |
|
|
rc = ftruncate(native_fd, native_len); |
|
|
if (rc == -1) |
|
677 |
{ |
{ |
678 |
JCL_ThrowException(env, "java/io/IOException", strerror(errno)); |
/* File is too long - use ftruncate if available */ |
679 |
return; |
#ifdef HAVE_FTRUNCATE |
680 |
} |
TARGET_NATIVE_FILE_TRUNCATE(native_fd, len, result); |
681 |
|
if (result != TARGET_NATIVE_OK) |
682 |
|
{ |
683 |
|
JCL_ThrowException(env, |
684 |
|
"java/io/IOException", |
685 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
686 |
|
return; |
687 |
|
} |
688 |
#else /* HAVE_FTRUNCATE */ |
#else /* HAVE_FTRUNCATE */ |
689 |
/* FIXME: Probably operation isn't supported, but this exception |
/* FIXME: Probably operation isn't supported, but this exception |
690 |
* is too harsh as it will probably crash the program without need |
* is too harsh as it will probably crash the program without need |
691 |
JCL_ThrowException(env, "java/lang/UnsupportedOperationException", |
JCL_ThrowException(env, "java/lang/UnsupportedOperationException", |
692 |
"not implemented - can't shorten files on this platform"); |
"not implemented - can't shorten files on this platform"); |
693 |
*/ |
*/ |
694 |
JCL_ThrowException(env, "java/io/IOException", |
JCL_ThrowException(env, "java/io/IOException", |
695 |
"Unable to shorten file length"); |
"Unable to shorten file length"); |
696 |
#endif /* HAVE_FTRUNCATE */ |
#endif /* HAVE_FTRUNCATE */ |
697 |
|
} |
698 |
} |
} |
699 |
|
|
700 |
/*************************************************************************/ |
/*************************************************************************/ |
704 |
JNIEXPORT jboolean JNICALL |
JNIEXPORT jboolean JNICALL |
705 |
Java_java_io_FileDescriptor_nativeValid(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeValid(JNIEnv *env, jobject obj, jlong fd) |
706 |
{ |
{ |
707 |
int rc, native_fd; |
int native_fd; |
708 |
struct stat sb; |
int result; |
709 |
|
|
710 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
711 |
|
|
712 |
rc = fstat(native_fd, &sb); |
TARGET_NATIVE_FILE_VALID_FILE_DESCRIPTOR(native_fd, result); |
713 |
if (rc == -1) |
|
714 |
return JNI_FALSE; |
return((result == TARGET_NATIVE_OK)?JNI_TRUE:JNI_FALSE); |
|
else |
|
|
return JNI_TRUE; |
|
715 |
} |
} |
716 |
|
|
717 |
/*************************************************************************/ |
/*************************************************************************/ |
722 |
JNIEXPORT void JNICALL |
JNIEXPORT void JNICALL |
723 |
Java_java_io_FileDescriptor_nativeSync(JNIEnv *env, jobject obj, jlong fd) |
Java_java_io_FileDescriptor_nativeSync(JNIEnv *env, jobject obj, jlong fd) |
724 |
{ |
{ |
725 |
int rc, native_fd; |
int native_fd; |
726 |
|
int result; |
727 |
|
|
728 |
native_fd = CONVERT_JLONG_TO_INT(fd); |
native_fd = CONVERT_JLONG_TO_INT(fd); |
729 |
|
|
730 |
#ifdef HAVE_FSYNC |
#ifdef HAVE_FSYNC |
731 |
rc = fsync(native_fd); |
TARGET_NATIVE_FILE_FSYNC(native_fd, result); |
732 |
/* FIXME: gcj does not throw an exception on EROFS or EINVAL. |
/* FIXME: gcj does not throw an exception on EROFS or EINVAL. |
733 |
* Should we emulate? */ |
* Should we emulate? */ |
734 |
if (rc == -1) |
if (result != TARGET_NATIVE_OK) |
735 |
JCL_ThrowException(env, "java/io/SyncFailedException", strerror(errno)); |
{ |
736 |
|
JCL_ThrowException(env, |
737 |
|
"java/io/SyncFailedException", |
738 |
|
TARGET_NATIVE_LAST_ERROR_STRING()); |
739 |
|
} |
740 |
#else |
#else |
741 |
JCL_ThrowException(env, "java/io/SyncFailedException", |
JCL_ThrowException(env, "java/io/SyncFailedException", |
742 |
"Sync not supported"); |
"Sync not supported"); |