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

Subversion Repositories scarts

[/] [scarts/] [trunk/] [toolchain/] [scarts-gcc/] [gcc-4.1.1/] [libjava/] [gnu/] [java/] [nio/] [channels/] [natFileChannelPosix.cc] - Blame information for rev 14

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 14 jlechner
 
2
// natFileChannelImplPosix.cc - Native part of FileChannelImpl class.
3
 
4
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2006  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
  _Jv_platform_close_on_exec (fd);
182
 
183
  return fd;
184
}
185
 
186
void
187
FileChannelImpl::write (jint b)
188
{
189
  jbyte d = (jbyte) b;
190
  int r = 0;
191
  while (r != 1)
192
    {
193
      r = ::write (fd, &d, 1);
194
      if (r == -1)
195
        {
196
          if (::java::lang::Thread::interrupted())
197
            {
198
              ::java::io::InterruptedIOException *iioe
199
                = new ::java::io::InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
200
              iioe->bytesTransferred = r == -1 ? 0 : r;
201
              throw iioe;
202
            }
203
          if (errno != EINTR)
204
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
205
        }
206
    }
207
  pos++;
208
}
209
 
210
void
211
FileChannelImpl::write (jbyteArray b, jint offset, jint len)
212
{
213
  if (! b)
214
    throw new ::java::lang::NullPointerException;
215
  if (offset < 0 || len < 0 || offset + len > JvGetArrayLength (b))
216
    throw new ArrayIndexOutOfBoundsException;
217
  jbyte *bytes = elements (b) + offset;
218
 
219
  int written = 0;
220
  while (len > 0)
221
    {
222
      int r = ::write (fd, bytes, len);
223
      if (r == -1)
224
        {
225
          if (::java::lang::Thread::interrupted())
226
            {
227
              InterruptedIOException *iioe
228
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
229
              iioe->bytesTransferred = written;
230
              throw iioe;
231
            }
232
          if (errno != EINTR)
233
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
234
          continue;
235
        }
236
 
237
      written += r;
238
      len -= r;
239
      bytes += r;
240
      pos += r;
241
    }
242
}
243
 
244
void
245
FileChannelImpl::implCloseChannel (void)
246
{
247
  jint save = fd;
248
  fd = -1;
249
  if (::close (save))
250
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
251
}
252
 
253
void
254
FileChannelImpl::implTruncate (jlong size)
255
{
256
  struct stat sb;
257
 
258
#ifdef HAVE_FTRUNCATE
259
  if (::fstat (fd, &sb))
260
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
261
 
262
  if ((jlong) sb.st_size == size)
263
    return;
264
 
265
  // If the file is too short, we extend it.  We can't rely on
266
  // ftruncate() extending the file.  So we lseek() to 1 byte less
267
  // than we want, and then we write a single byte at the end.
268
  if ((jlong) sb.st_size < size)
269
    {
270
      if (::lseek (fd, (off_t) (size - 1), SEEK_SET) == -1)
271
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
272
      char out = '\0';
273
      int r = ::write (fd, &out, 1);
274
      if (r <= 0 || ::lseek (fd, pos, SEEK_SET) == -1)
275
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
276
    }
277
  else
278
    {
279
      if (::ftruncate (fd, (off_t) size))
280
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
281
      if (pos > size
282
          && ::lseek (fd, (off_t) size, SEEK_SET) == -1)
283
        throw new IOException (JvNewStringLatin1 (strerror (errno)));
284
      pos = size;
285
    }
286
#else /* HAVE_FTRUNCATE */
287
  throw new IOException (JvNewStringLatin1 ("FileDescriptor.setLength not implemented"));
288
#endif /* HAVE_FTRUNCATE */
289
}
290
 
291
void
292
FileChannelImpl::seek (jlong newPos)
293
{
294
  off_t r = ::lseek (fd, (off_t) newPos, SEEK_SET);
295
  if (r == -1)
296
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
297
  pos = r;
298
}
299
 
300
jlong
301
FileChannelImpl::size (void)
302
{
303
  struct stat sb;
304
  if (::fstat (fd, &sb))
305
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
306
  return sb.st_size;
307
}
308
 
309
jlong
310
FileChannelImpl::implPosition (void)
311
{
312
  return pos;
313
}
314
 
315
jint
316
FileChannelImpl::read (void)
317
{
318
  jbyte b;
319
  int r;
320
  do
321
    {
322
      r = ::read (fd, &b, 1);
323
      if (r == 0)
324
        return -1;
325
      if (r == -1)
326
        {
327
          if (::java::lang::Thread::interrupted())
328
            {
329
              InterruptedIOException *iioe
330
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
331
              iioe->bytesTransferred = r == -1 ? 0 : r;
332
              throw iioe;
333
            }
334
          if (errno != EINTR)
335
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
336
        }
337
    }
338
  while (r != 1);
339
  pos++;
340
  return b & 0xFF;
341
}
342
 
343
jint
344
FileChannelImpl::read (jbyteArray buffer, jint offset, jint count)
345
{
346
  if (! buffer)
347
    throw new ::java::lang::NullPointerException;
348
  jsize bsize = JvGetArrayLength (buffer);
349
  if (offset < 0 || count < 0 || offset + count > bsize)
350
    throw new ::java::lang::ArrayIndexOutOfBoundsException;
351
 
352
  // Must return 0 if an attempt is made to read 0 bytes.
353
  if (count == 0)
354
    return 0;
355
 
356
  jbyte *bytes = elements (buffer) + offset;
357
  int r;
358
  do
359
    {
360
      r = ::read (fd, bytes, count);
361
      if (r == 0)
362
        return -1;
363
      if (r == -1)
364
        {
365
          if (::java::lang::Thread::interrupted())
366
            {
367
              InterruptedIOException *iioe
368
                = new InterruptedIOException (JvNewStringLatin1 (strerror (errno)));
369
              iioe->bytesTransferred = r == -1 ? 0 : r;
370
              throw iioe;
371
            }
372
          if (errno != EINTR)
373
            throw new IOException (JvNewStringLatin1 (strerror (errno)));
374
        }
375
    }
376
  while (r <= 0);
377
  pos += r;
378
  return r;
379
}
380
 
381
jint
382
FileChannelImpl::available (void)
383
{
384
#if defined (FIONREAD) || defined (HAVE_SELECT) || defined (HAVE_FSTAT)
385
  int num = 0;
386
  int r = 0;
387
  bool num_set = false;
388
 
389
#if defined (FIONREAD)
390
  r = ::ioctl (fd, FIONREAD, &num);
391
  if (r == -1 && errno == ENOTTY)
392
    {
393
      // If the ioctl doesn't work, we don't care.
394
      r = 0;
395
      num = 0;
396
    }
397
  else
398
    num_set = true;
399
#elif defined (HAVE_SELECT)
400
  if (fd < 0)
401
    {
402
      errno = EBADF;
403
      r = -1;
404
    }
405
#endif
406
 
407
  if (r == -1)
408
    {
409
    posix_error:
410
      throw new IOException (JvNewStringLatin1 (strerror (errno)));
411
    }
412
 
413
  // If we didn't get anything, and we have fstat, then see if see if
414
  // we're reading a regular file.  On many systems, FIONREAD does not
415
  // work on regular files; select() likewise returns a useless
416
  // result.  This is run incorrectly when FIONREAD does work on
417
  // regular files and we are at the end of the file.  However, this
418
  // case probably isn't very important.
419
#if defined (HAVE_FSTAT)
420
  if (! num_set)
421
    {
422
      struct stat sb;
423
      off_t where = 0;
424
      if (fstat (fd, &sb) != -1
425
          && S_ISREG (sb.st_mode)
426
          && (where = lseek (fd, 0, SEEK_CUR)) != (off_t) -1)
427
        {
428
          num = (int) (sb.st_size - where);
429
          num_set = true;
430
        }
431
    }
432
#endif /* HAVE_FSTAT */
433
 
434
#if defined (HAVE_SELECT)
435
  if (! num_set)
436
    {
437
      fd_set rd;
438
      FD_ZERO (&rd);
439
      FD_SET (fd, &rd);
440
      struct timeval tv;
441
      tv.tv_sec = 0;
442
      tv.tv_usec = 0;
443
      r = _Jv_select (fd + 1, &rd, NULL, NULL, &tv);
444
      if (r == -1)
445
        goto posix_error;
446
      num = r == 0 ? 0 : 1;
447
    }
448
#endif /* HAVE_SELECT */
449
 
450
  return (jint) num;
451
#else
452
  return 0;
453
#endif
454
}
455
 
456
jboolean
457
FileChannelImpl::lock
458
(jlong pos, jlong len, jboolean shared, jboolean wait)
459
{
460
  struct flock lockdata;
461
 
462
  lockdata.l_type = shared ? F_RDLCK : F_WRLCK;
463
  lockdata.l_whence = SEEK_SET;
464
  lockdata.l_start = pos;
465
  lockdata.l_len = len;
466
 
467
  if (::fcntl (fd, wait ? F_SETLKW : F_SETLK, &lockdata) == -1)
468
    {
469
      if (! wait && (errno == EACCES || errno == EAGAIN))
470
        return false;
471
      throw new IOException (JvNewStringLatin1 (strerror (errno)));
472
    }
473
  return true;
474
}
475
 
476
void
477
FileChannelImpl::unlock (jlong pos, jlong len)
478
{
479
  struct flock lockdata;
480
 
481
  lockdata.l_type = F_UNLCK;
482
  lockdata.l_whence = SEEK_SET;
483
  lockdata.l_start = pos;
484
  lockdata.l_len = len;
485
 
486
  if (::fcntl (fd, F_SETLK, &lockdata) == -1)
487
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
488
}
489
 
490
java::nio::MappedByteBuffer *
491
FileChannelImpl::mapImpl (jchar mmode, jlong position, jint size)
492
{
493
#if defined(HAVE_MMAP)
494
  int prot, flags;
495
  if (mmode == 'r')
496
    {
497
      prot = PROT_READ;
498
      flags = MAP_PRIVATE;
499
    }
500
  else
501
    {
502
      prot = PROT_READ|PROT_WRITE;
503
      flags = mmode == '+' ? MAP_SHARED : MAP_PRIVATE;
504
    }
505
  jint page_size = ::getpagesize();
506
  jint offset = position & ~(page_size-1);
507
  jint align = position - offset;
508
  void* ptr = ::mmap(NULL, size + align, prot, flags, fd, offset);
509
  MappedByteBufferImpl *buf
510
    = new MappedByteBufferImpl ((RawData *) ((char *) ptr + align),
511
                                size, mmode == 'r');
512
  if (ptr == (void *) MAP_FAILED)
513
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
514
  buf->implPtr = reinterpret_cast<RawData*> (ptr);
515
  buf->implLen = size+align;
516
  return buf;
517
#else
518
  throw new IOException (JvNewStringUTF ("mmap not implemented"));
519
#endif
520
}
521
 
522
void
523
MappedByteBufferImpl::unmapImpl ()
524
{
525
#if defined(HAVE_MMAP)
526
  munmap_adaptor(munmap, implPtr, implLen);
527
#endif
528
}
529
 
530
void
531
MappedByteBufferImpl::loadImpl ()
532
{
533
}
534
 
535
jboolean
536
MappedByteBufferImpl::isLoadedImpl ()
537
{
538
  return true;
539
}
540
 
541
void
542
MappedByteBufferImpl::forceImpl ()
543
{
544
#if defined(HAVE_MMAP)
545
  ::msync_adaptor(msync, implPtr, implLen, MS_SYNC);
546
#endif
547
}

powered by: WebSVN 2.1.0

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