source: trunk/gcc/libjava/java/io/natFileDescriptorPosix.cc

Last change on this file was 1392, checked in by bird, 21 years ago

This commit was generated by cvs2svn to compensate for changes in r1391,
which included commits to RCS files with non-trunk default branches.

  • Property cvs2svn:cvs-rev set to 1.1.1.2
  • Property svn:eol-style set to native
  • Property svn:executable set to *
File size: 9.3 KB
Line 
1// natFileDescriptor.cc - Native part of FileDescriptor class.
2
3/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003 Free Software Foundation
4
5 This file is part of libgcj.
6
7This software is copyrighted work licensed under the terms of the
8Libgcj License. Please consult the file "LIBGCJ_LICENSE" for
9details. */
10
11#include <config.h>
12
13#include "posix.h"
14
15#include <errno.h>
16#include <stdio.h>
17#include <string.h>
18#include <sys/stat.h>
19#include <sys/param.h>
20
21#ifndef MAXPATHLEN
22# define MAXPATHLEN 1024
23#endif
24
25#ifdef HAVE_SYS_IOCTL_H
26#define BSD_COMP /* Get FIONREAD on Solaris2. */
27#include <sys/ioctl.h>
28#endif
29
30// Pick up FIONREAD on Solaris 2.5.
31#ifdef HAVE_SYS_FILIO_H
32#include <sys/filio.h>
33#endif
34
35#include <gcj/cni.h>
36#include <jvm.h>
37#include <java/io/FileDescriptor.h>
38#include <java/io/SyncFailedException.h>
39#include <java/io/IOException.h>
40#include <java/io/InterruptedIOException.h>
41#include <java/io/EOFException.h>
42#include <java/lang/ArrayIndexOutOfBoundsException.h>
43#include <java/lang/NullPointerException.h>
44#include <java/lang/System.h>
45#include <java/lang/String.h>
46#include <java/lang/Thread.h>
47#include <java/io/FileNotFoundException.h>
48
49#define NO_FSYNC_MESSAGE "sync unsupported"
50
51void
52java::io::FileDescriptor::init (void)
53{
54 in = new java::io::FileDescriptor(0);
55 out = new java::io::FileDescriptor(1);
56 err = new java::io::FileDescriptor(2);
57}
58
59jboolean
60java::io::FileDescriptor::valid (void)
61{
62 struct stat sb;
63 return fd >= 0 && ::fstat (fd, &sb) == 0;
64}
65
66void
67java::io::FileDescriptor::sync (void)
68{
69 // Some files don't support fsync. We don't bother reporting these
70 // as errors.
71#ifdef HAVE_FSYNC
72 if (::fsync (fd) && errno != EROFS && errno != EINVAL)
73 throw new SyncFailedException (JvNewStringLatin1 (strerror (errno)));
74#else
75 throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
76#endif
77}
78
79jint
80java::io::FileDescriptor::open (jstring path, jint jflags)
81{
82 char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1);
83 jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
84 buf[total] = '\0';
85 int flags = 0;
86#ifdef O_BINARY
87 flags |= O_BINARY;
88#endif
89
90 JvAssert ((jflags & READ) || (jflags & WRITE));
91 int mode = 0666;
92 if ((jflags & READ) && (jflags & WRITE))
93 flags |= O_RDWR | O_CREAT;
94 else if ((jflags & READ))
95 flags |= O_RDONLY;
96 else
97 {
98 flags |= O_WRONLY | O_CREAT;
99 if ((jflags & APPEND))
100 flags |= O_APPEND;
101 else
102 flags |= O_TRUNC;
103
104 if ((jflags & EXCL))
105 {
106 flags |= O_EXCL;
107 // In this case we are making a temp file.
108 mode = 0600;
109 }
110 }
111
112 int fd = ::open (buf, flags, mode);
113 if (fd == -1 && errno == EMFILE)
114 {
115 // Because finalize () calls close () we might be able to continue.
116 java::lang::System::gc ();
117 java::lang::System::runFinalization ();
118 fd = ::open (buf, flags, mode);
119 }
120 if (fd == -1)
121 {
122 char msg[MAXPATHLEN + 200];
123 // We choose the formatting here for JDK compatibility, believe
124 // it or not.
125 sprintf (msg, "%s (%s)", buf, strerror (errno));
126 throw new FileNotFoundException (JvNewStringLatin1 (msg));
127 }
128
129 _Jv_platform_close_on_exec (fd);
130
131 return fd;
132}
133
134void
135java::io::FileDescriptor::write (jint b)
136{
137 jbyte d = (jbyte) b;
138 int r = 0;
139 while (r != 1)
140 {
141 r = ::write (fd, &d, 1);
142 if (r == -1)
143 {
144 if (java::lang::Thread::interrupted())
145 {
146 InterruptedIOException *iioe
147 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
148 iioe->bytesTransferred = r == -1 ? 0 : r;
149 throw iioe;
150 }
151 throw new IOException (JvNewStringLatin1 (strerror (errno)));
152 }
153 }
154 position++;
155}
156
157void
158java::io::FileDescriptor::write (jbyteArray b, jint offset, jint len)
159{
160 if (! b)
161 throw new java::lang::NullPointerException;
162 if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
163 throw new java::lang::ArrayIndexOutOfBoundsException;
164 jbyte *bytes = elements (b) + offset;
165
166 int written = 0;
167 while (len > 0)
168 {
169 int r = ::write (fd, bytes, len);
170 if (r == -1)
171 {
172 if (java::lang::Thread::interrupted())
173 {
174 InterruptedIOException *iioe
175 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
176 iioe->bytesTransferred = written;
177 throw iioe;
178 }
179 throw new IOException (JvNewStringLatin1 (strerror (errno)));
180 }
181
182 written += r;
183 len -= r;
184 bytes += r;
185 position += r;
186 }
187}
188
189void
190java::io::FileDescriptor::close (void)
191{
192 jint save = fd;
193 fd = -1;
194 if (::close (save))
195 throw new IOException (JvNewStringLatin1 (strerror (errno)));
196}
197
198void
199java::io::FileDescriptor::setLength (jlong pos)
200{
201 struct stat sb;
202
203#ifdef HAVE_FTRUNCATE
204 if (::fstat (fd, &sb))
205 throw new IOException (JvNewStringLatin1 (strerror (errno)));
206
207 if ((jlong) sb.st_size == pos)
208 return;
209
210 // If the file is too short, we extend it. We can't rely on
211 // ftruncate() extending the file. So we lseek() to 1 byte less
212 // than we want, and then we write a single byte at the end.
213 if ((jlong) sb.st_size < pos)
214 {
215 if (::lseek (fd, (off_t) (pos - 1), SEEK_SET) == -1)
216 throw new IOException (JvNewStringLatin1 (strerror (errno)));
217 char out = '\0';
218 int r = ::write (fd, &out, 1);
219 if (r <= 0 || ::lseek (fd, position, SEEK_SET) == -1)
220 throw new IOException (JvNewStringLatin1 (strerror (errno)));
221 }
222 else
223 {
224 if (::ftruncate (fd, (off_t) pos))
225 throw new IOException (JvNewStringLatin1 (strerror (errno)));
226 position = pos;
227 }
228#else /* HAVE_FTRUNCATE */
229 throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
230#endif /* HAVE_FTRUNCATE */
231}
232
233jint
234java::io::FileDescriptor::seek (jlong pos, jint whence, jboolean eof_trunc)
235{
236 JvAssert (whence == SET || whence == CUR);
237
238 if (eof_trunc)
239 {
240 jlong len = length ();
241 if (whence == SET)
242 {
243 if (pos > len)
244 pos = len;
245 }
246 else
247 {
248 jlong here = getFilePointer ();
249 if (here + pos > len)
250 {
251 pos = len;
252 whence = SET;
253 }
254 }
255 }
256
257 off_t r = ::lseek (fd, (off_t) pos, whence == SET ? SEEK_SET : SEEK_CUR);
258 if (r == -1)
259 throw new IOException (JvNewStringLatin1 (strerror (errno)));
260 position = r;
261 return r;
262}
263
264jlong
265java::io::FileDescriptor::length (void)
266{
267 struct stat sb;
268 if (::fstat (fd, &sb))
269 throw new IOException (JvNewStringLatin1 (strerror (errno)));
270 return sb.st_size;
271}
272
273jlong
274java::io::FileDescriptor::getFilePointer (void)
275{
276 return position;
277}
278
279jint
280java::io::FileDescriptor::read (void)
281{
282 jbyte b;
283 int r = ::read (fd, &b, 1);
284 if (r == 0)
285 return -1;
286 if (r == -1)
287 {
288 if (java::lang::Thread::interrupted())
289 {
290 InterruptedIOException *iioe
291 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
292 iioe->bytesTransferred = r == -1 ? 0 : r;
293 throw iioe;
294 }
295 throw new IOException (JvNewStringLatin1 (strerror (errno)));
296 }
297 position++;
298 return b & 0xFF;
299}
300
301jint
302java::io::FileDescriptor::read (jbyteArray buffer, jint offset, jint count)
303{
304 if (! buffer)
305 throw new java::lang::NullPointerException;
306 jsize bsize = JvGetArrayLength (buffer);
307 if (offset < 0 || count < 0 || offset + count > bsize)
308 throw new java::lang::ArrayIndexOutOfBoundsException;
309
310 // Must return 0 if an attempt is made to read 0 bytes.
311 if (count == 0)
312 return 0;
313
314 jbyte *bytes = elements (buffer) + offset;
315 int r = ::read (fd, bytes, count);
316 if (r == 0)
317 return -1;
318 if (r == -1)
319 {
320 if (java::lang::Thread::interrupted())
321 {
322 InterruptedIOException *iioe
323 = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
324 iioe->bytesTransferred = r == -1 ? 0 : r;
325 throw iioe;
326 }
327 throw new IOException (JvNewStringLatin1 (strerror (errno)));
328 }
329 position += r;
330 return r;
331}
332
333jint
334java::io::FileDescriptor::available (void)
335{
336#if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
337 long num = 0;
338 int r = 0;
339 bool num_set = false;
340
341#if defined (FIONREAD)
342 r = ::ioctl (fd, FIONREAD, &num);
343 if (r == -1 && errno == ENOTTY)
344 {
345 // If the ioctl doesn't work, we don't care.
346 r = 0;
347 num = 0;
348 }
349 else
350 num_set = true;
351#elif defined (HAVE_SELECT)
352 if (fd < 0)
353 {
354 errno = EBADF;
355 r = -1;
356 }
357#endif
358
359 if (r == -1)
360 {
361 posix_error:
362 throw new IOException (JvNewStringLatin1 (strerror (errno)));
363 }
364
365 // If we didn't get anything, and we have fstat, then see if see if
366 // we're reading a regular file. On many systems, FIONREAD does not
367 // work on regular files; select() likewise returns a useless
368 // result. This is run incorrectly when FIONREAD does work on
369 // regular files and we are at the end of the file. However, this
370 // case probably isn't very important.
371#if defined (HAVE_FSTAT)
372 if (! num_set)
373 {
374 struct stat sb;
375 off_t where = 0;
376 if (fstat (fd, &sb) != -1
377 && S_ISREG (sb.st_mode)
378 && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
379 {
380 num = (long) (sb.st_size - where);
381 num_set = true;
382 }
383 }
384#endif /* HAVE_FSTAT */
385
386#if defined (HAVE_SELECT)
387 if (! num_set)
388 {
389 fd_set rd;
390 FD_ZERO (&rd);
391 FD_SET (fd, &rd);
392 struct timeval tv;
393 tv.tv_sec = 0;
394 tv.tv_usec = 0;
395 r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
396 if (r == -1)
397 goto posix_error;
398 num = r == 0 ? 0 : 1;
399 }
400#endif /* HAVE_SELECT */
401
402 return (jint) num;
403#else
404 return 0;
405#endif
406}
Note: See TracBrowser for help on using the repository browser.