1 // natFileDescriptor.cc - Native part of FileDescriptor class.
3 /* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
5 This file is part of libgcj.
7 This software is copyrighted work licensed under the terms of the
8 Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
19 #include <sys/param.h>
21 #ifdef HAVE_SYS_IOCTL_H
22 #define BSD_COMP /* Get FIONREAD on Solaris2. */
23 #include <sys/ioctl.h>
26 // Pick up FIONREAD on Solaris 2.5.
27 #ifdef HAVE_SYS_FILIO_H
28 #include <sys/filio.h>
33 #include <java/io/FileDescriptor.h>
34 #include <java/io/SyncFailedException.h>
35 #include <java/io/IOException.h>
36 #include <java/io/InterruptedIOException.h>
37 #include <java/io/EOFException.h>
38 #include <java/lang/ArrayIndexOutOfBoundsException.h>
39 #include <java/lang/NullPointerException.h>
40 #include <java/lang/System.h>
41 #include <java/lang/String.h>
42 #include <java/lang/Thread.h>
43 #include <java/io/FileNotFoundException.h>
45 #define NO_FSYNC_MESSAGE "sync unsupported"
48 java::io::FileDescriptor::init (void)
50 in
= new java::io::FileDescriptor(0);
51 out
= new java::io::FileDescriptor(1);
52 err
= new java::io::FileDescriptor(2);
56 java::io::FileDescriptor::valid (void)
59 return fd
>= 0 && ::fstat (fd
, &sb
) == 0;
63 java::io::FileDescriptor::sync (void)
65 // Some files don't support fsync. We don't bother reporting these
68 if (::fsync (fd
) && errno
!= EROFS
&& errno
!= EINVAL
)
69 throw new SyncFailedException (JvNewStringLatin1 (strerror (errno
)));
71 throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE
));
76 java::io::FileDescriptor::open (jstring path
, jint jflags
)
78 char *buf
= (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path
) + 1);
79 jsize total
= JvGetStringUTFRegion (path
, 0, path
->length(), buf
);
86 JvAssert ((jflags
& READ
) || (jflags
& WRITE
));
88 if ((jflags
& READ
) && (jflags
& WRITE
))
89 flags
|= O_RDWR
| O_CREAT
;
90 else if ((jflags
& READ
))
94 flags
|= O_WRONLY
| O_CREAT
;
95 if ((jflags
& APPEND
))
103 // In this case we are making a temp file.
108 int fd
= ::open (buf
, flags
, mode
);
109 if (fd
== -1 && errno
== EMFILE
)
111 // Because finalize () calls close () we might be able to continue.
112 java::lang::System::gc ();
113 java::lang::System::runFinalization ();
114 fd
= ::open (buf
, flags
, mode
);
118 char msg
[MAXPATHLEN
+ 200];
119 // We choose the formatting here for JDK compatibility, believe
121 sprintf (msg
, "%s (%s)", buf
, strerror (errno
));
122 throw new FileNotFoundException (JvNewStringLatin1 (msg
));
125 _Jv_platform_close_on_exec (fd
);
131 java::io::FileDescriptor::write (jint b
)
137 r
= ::write (fd
, &d
, 1);
140 if (java::lang::Thread::interrupted())
142 InterruptedIOException
*iioe
143 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
144 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
147 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
154 java::io::FileDescriptor::write (jbyteArray b
, jint offset
, jint len
)
157 throw new java::lang::NullPointerException
;
158 if (offset
< 0 || len
< 0 || offset
+ len
> JvGetArrayLength (b
))
159 throw new java::lang::ArrayIndexOutOfBoundsException
;
160 jbyte
*bytes
= elements (b
) + offset
;
165 int r
= ::write (fd
, bytes
, len
);
168 if (java::lang::Thread::interrupted())
170 InterruptedIOException
*iioe
171 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
172 iioe
->bytesTransferred
= written
;
175 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
186 java::io::FileDescriptor::close (void)
191 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
195 java::io::FileDescriptor::setLength (jlong pos
)
199 #ifdef HAVE_FTRUNCATE
200 if (::fstat (fd
, &sb
))
201 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
203 if ((jlong
) sb
.st_size
== pos
)
206 // If the file is too short, we extend it. We can't rely on
207 // ftruncate() extending the file. So we lseek() to 1 byte less
208 // than we want, and then we write a single byte at the end.
209 if ((jlong
) sb
.st_size
< pos
)
211 if (::lseek (fd
, (off_t
) (pos
- 1), SEEK_SET
) == -1)
212 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
214 int r
= ::write (fd
, &out
, 1);
215 if (r
<= 0 || ::lseek (fd
, position
, SEEK_SET
) == -1)
216 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
220 if (::ftruncate (fd
, (off_t
) pos
))
221 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
224 #else /* HAVE_FTRUNCATE */
225 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
226 #endif /* HAVE_FTRUNCATE */
230 java::io::FileDescriptor::seek (jlong pos
, jint whence
, jboolean eof_trunc
)
232 JvAssert (whence
== SET
|| whence
== CUR
);
236 jlong len
= length ();
244 jlong here
= getFilePointer ();
245 if (here
+ pos
> len
)
253 off_t r
= ::lseek (fd
, (off_t
) pos
, whence
== SET
? SEEK_SET
: SEEK_CUR
);
255 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
261 java::io::FileDescriptor::length (void)
264 if (::fstat (fd
, &sb
))
265 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
270 java::io::FileDescriptor::getFilePointer (void)
276 java::io::FileDescriptor::read (void)
279 int r
= ::read (fd
, &b
, 1);
284 if (java::lang::Thread::interrupted())
286 InterruptedIOException
*iioe
287 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
288 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
291 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
298 java::io::FileDescriptor::read (jbyteArray buffer
, jint offset
, jint count
)
301 throw new java::lang::NullPointerException
;
302 jsize bsize
= JvGetArrayLength (buffer
);
303 if (offset
< 0 || count
< 0 || offset
+ count
> bsize
)
304 throw new java::lang::ArrayIndexOutOfBoundsException
;
306 // Must return 0 if an attempt is made to read 0 bytes.
310 jbyte
*bytes
= elements (buffer
) + offset
;
311 int r
= ::read (fd
, bytes
, count
);
316 if (java::lang::Thread::interrupted())
318 InterruptedIOException
*iioe
319 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno
)));
320 iioe
->bytesTransferred
= r
== -1 ? 0 : r
;
323 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
330 java::io::FileDescriptor::available (void)
332 #if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
335 bool num_set
= false;
337 #if defined (FIONREAD)
338 r
= ::ioctl (fd
, FIONREAD
, &num
);
339 if (r
== -1 && errno
== ENOTTY
)
341 // If the ioctl doesn't work, we don't care.
347 #elif defined (HAVE_SELECT)
358 throw new IOException (JvNewStringLatin1 (strerror (errno
)));
361 // If we didn't get anything, and we have fstat, then see if see if
362 // we're reading a regular file. On many systems, FIONREAD does not
363 // work on regular files; select() likewise returns a useless
364 // result. This is run incorrectly when FIONREAD does work on
365 // regular files and we are at the end of the file. However, this
366 // case probably isn't very important.
367 #if defined (HAVE_FSTAT)
372 if (fstat (fd
, &sb
) != -1
373 && S_ISREG (sb
.st_mode
)
374 && (where
= lseek (fd
, SEEK_CUR
, 0)) != (off_t
) -1)
376 num
= (long) (sb
.st_size
- where
);
380 #endif /* HAVE_FSTAT */
382 #if defined (HAVE_SELECT)
391 r
= _Jv_select (fd
+ 1, &rd
, NULL
, NULL
, &tv
);
394 num
= r
== 0 ? 0 : 1;
396 #endif /* HAVE_SELECT */
400 throw new IOException (JvNewStringLatin1 ("unimplemented"));