OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [gnu/] [java/] [nio/] [channels/] [natFileChannelPosix.cc] - Blame information for rev 756

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 756 jeremybenn
 
2
// natFileChannelImplPosix.cc - Native part of FileChannelImpl class.
3
 
4
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006, 2007  Free Software Foundation
5
 
6
   This file is part of libgcj.
7
 
8
This software is copyrighted work licensed under the terms of the
9
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
10
details.  */
11
 
12
#include <config.h>
13
#include <platform.h>
14
 
15
#include <gcj/cni.h>
16
#include <gcj/javaprims.h>
17
#include <jvm.h>
18
 
19
#include "posix.h"
20
 
21
#include <errno.h>
22
#include <fcntl.h>
23
#include <stdio.h>
24
#include <string.h>
25
#include <sys/stat.h>
26
#include <sys/param.h>
27
 
28
#include <gnu/gcj/RawData.h>
29
#include <gnu/java/nio/FileLockImpl.h>
30
#include <gnu/java/nio/channels/FileChannelImpl.h>
31
#include <java/io/FileNotFoundException.h>
32
#include <java/io/IOException.h>
33
#include <java/io/SyncFailedException.h>
34
#include <java/io/InterruptedIOException.h>
35
#include <java/io/EOFException.h>
36
#include <java/lang/ArrayIndexOutOfBoundsException.h>
37
#include <java/lang/NullPointerException.h>
38
#include <java/lang/System.h>
39
#include <java/lang/String.h>
40
#include <java/lang/StringBuffer.h>
41
#include <java/lang/Thread.h>
42
#include <java/nio/ByteBuffer.h>
43
#include <java/nio/MappedByteBufferImpl.h>
44
#include <java/nio/channels/FileChannel.h>
45
#include <java/nio/channels/FileLock.h>
46
#include <gnu/java/nio/channels/FileChannelImpl.h>
47
 
48
#ifdef HAVE_SYS_IOCTL_H
49
#define BSD_COMP /* Get FIONREAD on Solaris2. */
50
#include <sys/ioctl.h>
51
#endif
52
 
53
// Pick up FIONREAD on Solaris 2.5.
54
#ifdef HAVE_SYS_FILIO_H
55
#include <sys/filio.h>
56
#endif
57
 
58
#ifdef HAVE_MMAP
59
#include <sys/mman.h>
60
 
61
// Use overload resolution to find out the argument types.
62
// E.g. Solaris 2.6 uses different argument types for munmap and msync.
63
// This is in case _POSIX_C_SOURCES is smaller than 3.
64
 
65
template <typename T_implPtr, typename T_implLen>
66
static inline int
67
munmap_adaptor(int (*munmap)(T_implPtr caddr, T_implLen sizet),
68
                 void* caddr, size_t sizet)
69
{
70
  return munmap ((T_implPtr) caddr, (T_implLen) sizet);
71
}
72
 
73
template <typename T_implPtr, typename T_implLen, typename T_msync>
74
static inline int
75
msync_adaptor(int (*msync)(T_implPtr caddr, T_implLen sizet, T_msync msynct),
76
              void* caddr, size_t sizet, int msynct)
77
{
78
  return msync ((T_implPtr) caddr, (T_implLen) sizet, (T_msync) msynct);
79
}
80
#endif
81
 
82
using gnu::gcj::RawData;
83
using java::io::IOException;
84
using java::nio::MappedByteBufferImpl;
85
using java::io::InterruptedIOException;
86
using java::io::FileNotFoundException;
87
using java::lang::ArrayIndexOutOfBoundsException;
88
using gnu::java::nio::channels::FileChannelImpl;
89
 
90
#define NO_FSYNC_MESSAGE "sync unsupported"
91
 
92
void
93
FileChannelImpl::init(void)
94
{
95
  in = new FileChannelImpl((jint) 0, FileChannelImpl::READ);
96
  out = new FileChannelImpl((jint) 1, FileChannelImpl::WRITE);
97
  err = new FileChannelImpl((jint) 2, FileChannelImpl::WRITE);
98
}
99
 
100
#if 0
101
jboolean
102
FileChannelImpl::valid (void)
103
{
104
  struct stat sb;
105
  return fd >= 0 && ::fstat (fd, &sb) == 0;
106
}
107
 
108
void
109
FileChannelImpl::sync (void)
110
{
111
  // Some files don't support fsync.  We don't bother reporting these
112
  // as errors.
113
#ifdef HAVE_FSYNC
114
  if (::fsync (fd) && errno != EROFS && errno != EINVAL)
115
    throw new SyncFailedException (JvNewStringLatin1 (strerror (errno)));
116
#else
117
  throw new SyncFailedException (JvNewStringLatin1 (NO_FSYNC_MESSAGE));
118
#endif
119
}
120
#endif
121
 
122
jint
123
FileChannelImpl::open (jstring path, jint jflags)
124
{
125
  fd = -1;
126
  char *buf = (char *) _Jv_AllocBytes (_Jv_GetStringUTFLength (path) + 1);
127
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
128
  buf[total] = '\0';
129
  int flags = 0;
130
#ifdef O_BINARY
131
  flags |= O_BINARY;
132
#endif
133
 
134
  JvAssert ((jflags & READ) || (jflags & WRITE));
135
  int mode = 0666;
136
  if ((jflags & READ) && (jflags & WRITE))
137
    flags |= O_RDWR | O_CREAT;
138
  else if ((jflags & READ))
139
    flags |= O_RDONLY;
140
  else
141
    {
142
      flags |= O_WRONLY | O_CREAT;
143
      if ((jflags & APPEND))
144
        flags |= O_APPEND;
145
      else
146
        flags |= O_TRUNC;
147
 
148
      if ((jflags & EXCL))
149
        {
150
          flags |= O_EXCL;
151
          // In this case we are making a temp file.
152
          mode = 0600;
153
        }
154
    }
155
 
156
  if ((jflags & SYNC))
157
    flags |= O_SYNC;
158
 
159
  if ((jflags & DSYNC))
160
    flags |= O_DSYNC;
161
 
162
  int fd = ::open (buf, flags, mode);
163
  if (fd == -1 && errno == EMFILE)
164
    {
165
      // Because finalize () calls close () we might be able to continue.
166
      ::java::lang::System::gc ();
167
      ::java::lang::System::runFinalization ();
168
      fd = ::open (buf, flags, mode);
169
    }
170
  if (fd == -1)
171
    {
172
      // We choose the formatting here for JDK compatibility, believe
173
      // it or not.
174
      ::java::lang::StringBuffer *msg = new ::java::lang::StringBuffer (path);
175
      msg->append (JvNewStringUTF (" ("));
176
      msg->append (JvNewStringUTF (strerror (errno)));
177
      msg->append (JvNewStringUTF (")"));
178
      throw new ::java::io::FileNotFoundException (msg->toString ());
179
    }
180
 
181
  return fd;
182
}
183
 
184
void
185
FileChannelImpl::write (jint b)
186
{
187
  jbyte d = (jbyte) b;
188
  int r = 0;
189
  while (r != 1)
190
    {
191
      r = ::write (fd, &d, 1);
192
      if (r == -1)
193
        {
194
          if (::java::lang::Thread::interrupted())
195
            {
196
              ::java::io::InterruptedIOException *iioe
197
                = new ::java::io::InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
198
              iioe->bytesTransferred = r == -1 ? 0 : r;
199
              throw iioe;
200
            }
201
          if (errno != EINTR)
202
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
203
        }
204
    }
205
  pos++;
206
}
207
 
208
void
209
FileChannelImpl::write (jbyteArray b, jint offset, jint len)
210
{
211
  if (! b)
212
    throw new ::java::lang::NullPointerException;
213
  if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
214
    throw new ArrayIndexOutOfBoundsException;
215
  jbyte *bytes = elements (b) + offset;
216
 
217
  int written = 0;
218
  while (len > 0)
219
    {
220
      int r = ::write (fd, bytes, len);
221
      if (r == -1)
222
        {
223
          if (::java::lang::Thread::interrupted())
224
            {
225
              InterruptedIOException *iioe
226
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
227
              iioe->bytesTransferred = written;
228
              throw iioe;
229
            }
230
          if (errno != EINTR)
231
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
232
          continue;
233
        }
234
 
235
      written += r;
236
      len -= r;
237
      bytes += r;
238
      pos += r;
239
    }
240
}
241
 
242
void
243
FileChannelImpl::implCloseChannel (void)
244
{
245
  jint save = fd;
246
  fd = -1;
247
  if (::close (save))
248
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
249
}
250
 
251
void
252
FileChannelImpl::implTruncate (jlong size)
253
{
254
  struct stat sb;
255
 
256
#ifdef HAVE_FTRUNCATE
257
  if (::fstat (fd, &sb))
258
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
259
 
260
  if ((jlong) sb.st_size == size)
261
    return;
262
 
263
  // If the file is too short, we extend it.  We can't rely on
264
  // ftruncate() extending the file.  So we lseek() to 1 byte less
265
  // than we want, and then we write a single byte at the end.
266
  if ((jlong) sb.st_size < size)
267
    {
268
      if (::lseek (fd, (off_t) (size - 1), SEEK_SET) == -1)
269
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
270
      char out = '\0';
271
      int r = ::write (fd, &out, 1);
272
      if (r <= 0 || ::lseek (fd, pos, SEEK_SET) == -1)
273
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
274
    }
275
  else
276
    {
277
      if (::ftruncate (fd, (off_t) size))
278
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
279
      if (pos > size
280
          && ::lseek (fd, (off_t) size, SEEK_SET) == -1)
281
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
282
      pos = size;
283
    }
284
#else /* HAVE_FTRUNCATE */
285
  throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
286
#endif /* HAVE_FTRUNCATE */
287
}
288
 
289
void
290
FileChannelImpl::seek (jlong newPos)
291
{
292
  off_t r = ::lseek (fd, (off_t) newPos, SEEK_SET);
293
  if (r == -1)
294
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
295
  pos = r;
296
}
297
 
298
jlong
299
FileChannelImpl::size (void)
300
{
301
  struct stat sb;
302
  if (::fstat (fd, &sb))
303
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
304
  return sb.st_size;
305
}
306
 
307
jlong
308
FileChannelImpl::implPosition (void)
309
{
310
  return pos;
311
}
312
 
313
jint
314
FileChannelImpl::read (void)
315
{
316
  jbyte b;
317
  int r;
318
  do
319
    {
320
      r = ::read (fd, &b, 1);
321
      if (r == 0)
322
        return -1;
323
      if (r == -1)
324
        {
325
          if (::java::lang::Thread::interrupted())
326
            {
327
              InterruptedIOException *iioe
328
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
329
              iioe->bytesTransferred = r == -1 ? 0 : r;
330
              throw iioe;
331
            }
332
          if (errno != EINTR)
333
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
334
        }
335
    }
336
  while (r != 1);
337
  pos++;
338
  return b & 0xFF;
339
}
340
 
341
jint
342
FileChannelImpl::read (jbyteArray buffer, jint offset, jint count)
343
{
344
  if (! buffer)
345
    throw new ::java::lang::NullPointerException;
346
  jsize bsize = JvGetArrayLength (buffer);
347
  if (offset < 0 || count < 0 || offset + count > bsize)
348
    throw new ::java::lang::ArrayIndexOutOfBoundsException;
349
 
350
  // Must return 0 if an attempt is made to read 0 bytes.
351
  if (count == 0)
352
    return 0;
353
 
354
  jbyte *bytes = elements (buffer) + offset;
355
  int r;
356
  do
357
    {
358
      r = ::read (fd, bytes, count);
359
      if (r == 0)
360
        return -1;
361
      if (r == -1)
362
        {
363
          if (::java::lang::Thread::interrupted())
364
            {
365
              InterruptedIOException *iioe
366
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
367
              iioe->bytesTransferred = r == -1 ? 0 : r;
368
              throw iioe;
369
            }
370
          if (errno != EINTR)
371
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
372
        }
373
    }
374
  while (r <= 0);
375
  pos += r;
376
  return r;
377
}
378
 
379
jint
380
FileChannelImpl::available (void)
381
{
382
#if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
383
  int num = 0;
384
  int r = 0;
385
  bool num_set = false;
386
 
387
#if defined (FIONREAD)
388
  r = ::ioctl (fd, FIONREAD, &num);
389
  if (r == -1 && errno == ENOTTY)
390
    {
391
      // If the ioctl doesn't work, we don't care.
392
      r = 0;
393
      num = 0;
394
    }
395
  else
396
    num_set = true;
397
#elif defined (HAVE_SELECT)
398
  if (fd < 0)
399
    {
400
      errno = EBADF;
401
      r = -1;
402
    }
403
#endif
404
 
405
  if (r == -1)
406
    {
407
    posix_error:
408
      throw new IOException (JvNewStringLatin1 (strerror (errno)));
409
    }
410
 
411
  // If we didn't get anything, and we have fstat, then see if see if
412
  // we're reading a regular file.  On many systems, FIONREAD does not
413
  // work on regular files; select() likewise returns a useless
414
  // result.  This is run incorrectly when FIONREAD does work on
415
  // regular files and we are at the end of the file.  However, this
416
  // case probably isn't very important.
417
#if defined (HAVE_FSTAT)
418
  if (! num_set)
419
    {
420
      struct stat sb;
421
      off_t where = 0;
422
      if (fstat (fd, &sb) != -1
423
          && S_ISREG (sb.st_mode)
424
          && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
425
        {
426
          num = (int) (sb.st_size - where);
427
          num_set = true;
428
        }
429
    }
430
#endif /* HAVE_FSTAT */
431
 
432
#if defined (HAVE_SELECT)
433
  if (! num_set)
434
    {
435
      fd_set rd;
436
      FD_ZERO (&rd);
437
      FD_SET (fd, &rd);
438
      struct timeval tv;
439
      tv.tv_sec = 0;
440
      tv.tv_usec = 0;
441
      r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
442
      if (r == -1)
443
        goto posix_error;
444
      num = r == 0 ? 0 : 1;
445
    }
446
#endif /* HAVE_SELECT */
447
 
448
  return (jint) num;
449
#else
450
  return 0;
451
#endif
452
}
453
 
454
jboolean
455
FileChannelImpl::lock
456
(jlong pos, jlong len, jboolean shared, jboolean wait)
457
{
458
  struct flock lockdata;
459
 
460
  lockdata.l_type = shared ? F_RDLCK : F_WRLCK;
461
  lockdata.l_whence = SEEK_SET;
462
  lockdata.l_start = pos;
463
  lockdata.l_len = len;
464
 
465
  if (::fcntl (fd, wait ? F_SETLKW : F_SETLK, &lockdata) == -1)
466
    {
467
      if (! wait && (errno == EACCES || errno == EAGAIN))
468
        return false;
469
      throw new IOException (JvNewStringLatin1 (strerror (errno)));
470
    }
471
  return true;
472
}
473
 
474
void
475
FileChannelImpl::unlock (jlong pos, jlong len)
476
{
477
  struct flock lockdata;
478
 
479
  lockdata.l_type = F_UNLCK;
480
  lockdata.l_whence = SEEK_SET;
481
  lockdata.l_start = pos;
482
  lockdata.l_len = len;
483
 
484
  if (::fcntl (fd, F_SETLK, &lockdata) == -1)
485
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
486
}
487
 
488
java::nio::MappedByteBuffer *
489
FileChannelImpl::mapImpl (jchar mmode, jlong position, jint size)
490
{
491
#if defined(HAVE_MMAP)
492
  int prot, flags;
493
  if (mmode == 'r')
494
    {
495
      prot = PROT_READ;
496
      flags = MAP_PRIVATE;
497
    }
498
  else
499
    {
500
      prot = PROT_READ|PROT_WRITE;
501
      flags = mmode == '+' ? MAP_SHARED : MAP_PRIVATE;
502
 
503
      // If the file is too short, we must extend it.  While using
504
      // ftruncate() to extend a file is not portable in general, it
505
      // should work on all systems where you can mmap() a file.
506
      struct stat st;
507
      if (fstat (fd, &st) == -1)
508
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
509
      if (position + size > st.st_size)
510
        {
511
          if (ftruncate (fd, position + size) == -1)
512
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
513
        }
514
    }
515
  jint page_size = ::getpagesize();
516
  jint offset = position & ~(page_size-1);
517
  jint align = position - offset;
518
  void* ptr = ::mmap(NULL, size + align, prot, flags, fd, offset);
519
  MappedByteBufferImpl *buf
520
    = new MappedByteBufferImpl ((RawData *) ((char *) ptr + align),
521
                                size, mmode == 'r');
522
  if (ptr == (void *) MAP_FAILED)
523
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
524
  buf->implPtr = reinterpret_cast<RawData*> (ptr);
525
  buf->implLen = size+align;
526
  return buf;
527
#else
528
  throw new IOException (JvNewStringUTF ("mmap not implemented"));
529
#endif
530
}
531
 
532
void
533
MappedByteBufferImpl::unmapImpl ()
534
{
535
#if defined(HAVE_MMAP)
536
  munmap_adaptor(munmap, implPtr, implLen);
537
#endif
538
}
539
 
540
void
541
MappedByteBufferImpl::loadImpl ()
542
{
543
}
544
 
545
jboolean
546
MappedByteBufferImpl::isLoadedImpl ()
547
{
548
  return true;
549
}
550
 
551
void
552
MappedByteBufferImpl::forceImpl ()
553
{
554
#if defined(HAVE_MMAP)
555
  ::msync_adaptor(msync, implPtr, implLen, MS_SYNC);
556
#endif
557
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.