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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [native/] [jni/] [java-nio/] [gnu_java_nio_VMChannel.c] - Blame information for rev 774

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 774 jeremybenn
/* gnu_java_nio_VMChannel.c -
2
   Copyright (C) 2003, 2004, 2005, 2006, 2007  Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
#ifdef HAVE_CONFIG_H
40
#include <config.h>
41
#endif
42
 
43
#include <config-int.h>
44
 
45
#include <sys/types.h>
46
#ifdef HAVE_SYS_MMAN_H
47
#include <sys/mman.h>
48
#endif
49
#include <sys/socket.h>
50
#include <sys/stat.h>
51
#include <sys/uio.h>
52
 
53
#include <netinet/in.h>
54
 
55
#include <stdlib.h>
56
#include <errno.h>
57
#include <unistd.h>
58
#include <string.h>
59
 
60
#include <jni.h>
61
#include <jcl.h>
62
 
63
#include "cpio.h"
64
#include "gnu_java_nio_VMChannel.h"
65
#include "javanio.h"
66
 
67
#ifdef HAVE_FCNTL_H
68
#include <fcntl.h>
69
#endif /* HAVE_FCNTL_H */
70
 
71
#if defined(HAVE_SYS_IOCTL_H)
72
#define BSD_COMP /* Get FIONREAD on Solaris2 */
73
#include <sys/ioctl.h>
74
#endif
75
#if defined(HAVE_SYS_FILIO_H) /* Get FIONREAD on Solaris 2.5 */
76
#include <sys/filio.h>
77
#endif
78
 
79
#define CONNECT_EXCEPTION "java/net/ConnectException"
80
#define IO_EXCEPTION "java/io/IOException"
81
#define SOCKET_EXCEPTION "java/net/SocketException"
82
#define INTERRUPTED_IO_EXCEPTION "java/io/InterruptedIOException"
83
#define NON_READABLE_CHANNEL_EXCEPTION "java/nio/channels/NonReadableChannelException"
84
#define NON_WRITABLE_CHANNEL_EXCEPTION "java/nio/channels/NonWritableChannelException"
85
#define SOCKET_TIMEOUT_EXCEPTION "java/net/SocketTimeoutException"
86
 
87
/* Align a value up or down to a multiple of the pagesize. */
88
#define ALIGN_DOWN(p,s) ((p) - ((p) % (s)))
89
#define ALIGN_UP(p,s) ((p) + ((s) - ((p) % (s))))
90
 
91
/*
92
 * Limit to maximum of 16 buffers
93
 */
94
#define JCL_IOV_MAX 16
95
 
96
#ifdef __cplusplus
97
extern "C"
98
{
99
#endif
100
 
101
enum JCL_buffer_type { DIRECT, HEAP, ARRAY, UNKNOWN };
102
 
103
struct JCL_buffer
104
{
105
  enum JCL_buffer_type type;
106
  jbyte *ptr;
107
  jint offset;
108
  jint position;
109
  jint limit;
110
  jint count;
111
};
112
 
113
jmethodID get_method_id(JNIEnv *, jclass, const char *, const char *);
114
void JCL_print_buffer(JNIEnv *, struct JCL_buffer *);
115
int JCL_init_buffer(JNIEnv *, struct JCL_buffer *, jobject);
116
void JCL_release_buffer(JNIEnv *, struct JCL_buffer *, jobject, jint);
117
void JCL_cleanup_buffers(JNIEnv *, struct JCL_buffer *, jint, jobjectArray, jint, jlong);
118
int JCL_thread_interrupted(JNIEnv *);
119
 
120
static jfieldID address_fid;
121
static jmethodID get_position_mid;
122
static jmethodID set_position_mid;
123
static jmethodID get_limit_mid;
124
static jmethodID set_limit_mid;
125
static jmethodID has_array_mid;
126
static jmethodID array_mid;
127
static jmethodID array_offset_mid;
128
static jmethodID thread_interrupted_mid;
129
static jclass vm_channel_class;
130
 
131
jmethodID
132
get_method_id(JNIEnv *env,  jclass clazz, const char *name,
133
                  const char *sig)
134
{
135
  jmethodID mid = (*env)->GetMethodID(env, clazz, name, sig);
136
/*   NIODBG("name: %s; sig: %s", name, sig); */
137
  if (mid == NULL)
138
    {
139
      JCL_ThrowException(env, "java/lang/InternalError", name);
140
      return NULL;
141
    }
142
 
143
  return mid;
144
}
145
 
146
inline void
147
JCL_print_buffer(JNIEnv *env __attribute__((__unused__)), struct JCL_buffer *buf)
148
{
149
  fprintf (stderr, "Buffer - type: %d, ptr: %p\n", buf->type, buf->ptr);
150
}
151
 
152
 
153
int
154
JCL_init_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf)
155
{
156
  void *addr = (*env)->GetDirectBufferAddress (env, bbuf);
157
 
158
/*   NIODBG("buf: %p; bbuf: %p; addr: %p", (void *) buf, bbuf, addr); */
159
 
160
  buf->position = (*env)->CallIntMethod(env, bbuf, get_position_mid);
161
  buf->limit = (*env)->CallIntMethod(env, bbuf, get_limit_mid);
162
  buf->offset = 0;
163
  buf->count = 0;
164
  buf->type = UNKNOWN;
165
 
166
  if (addr != NULL)
167
    {
168
      buf->ptr = (jbyte *) addr;
169
      buf->type = DIRECT;
170
    }
171
  else
172
    {
173
      jboolean has_array;
174
      has_array = (*env)->CallBooleanMethod(env, bbuf, has_array_mid);
175
 
176
      if (has_array == JNI_TRUE)
177
        {
178
          jbyteArray arr;
179
          buf->offset = (*env)->CallIntMethod(env, bbuf, array_offset_mid);
180
          arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
181
          buf->ptr = (*env)->GetByteArrayElements(env, arr, 0);
182
          buf->type = ARRAY;
183
          (*env)->DeleteLocalRef(env, arr);
184
        }
185
      else
186
        {
187
          jobject address = (*env)->GetObjectField (env, bbuf, address_fid);
188
          if (address == NULL)
189
            return -1; /* XXX handle non-array, non-native buffers? */
190
          buf->ptr = (jbyte *) JCL_GetRawData(env, address);
191
          buf->type = HEAP;
192
          (*env)->DeleteLocalRef(env, address);
193
        }
194
    }
195
 
196
  return 0;
197
}
198
 
199
void
200
JCL_release_buffer(JNIEnv *env, struct JCL_buffer *buf, jobject bbuf,
201
    jint action)
202
{
203
  jbyteArray arr;
204
 
205
/*   NIODBG("buf: %p; bbuf: %p; action: %x", (void *) buf, bbuf, action); */
206
 
207
  /* Set the position to the appropriate value */
208
  if (buf->count > 0)
209
    {
210
      jobject bbufTemp;
211
      bbufTemp = (*env)->CallObjectMethod(env, bbuf, set_position_mid,
212
                                          buf->position + buf->count);
213
      (*env)->DeleteLocalRef(env, bbufTemp);
214
    }
215
 
216
  switch (buf->type)
217
    {
218
    case DIRECT:
219
    case HEAP:
220
      break;
221
    case ARRAY:
222
      arr = (*env)->CallObjectMethod(env, bbuf, array_mid);
223
      (*env)->ReleaseByteArrayElements(env, arr, buf->ptr, action);
224
      (*env)->DeleteLocalRef(env, arr);
225
      break;
226
    case UNKNOWN:
227
      /* TODO: Handle buffers that are not direct or array backed */
228
      break;
229
    }
230
}
231
 
232
void
233
JCL_cleanup_buffers(JNIEnv *env,
234
                    struct JCL_buffer *bi_list,
235
                    jint vec_len,
236
                    jobjectArray bbufs,
237
                    jint offset,
238
                    jlong num_bytes)
239
{
240
  jint i;
241
 
242
/*   NIODBG("bi_list: %p; vec_len: %d; bbufs: %p; offset: %d; num_bytes: %lld", */
243
/*       (void *) bi_list, vec_len, bbufs, offset, num_bytes); */
244
 
245
  /* Update all of the bbufs with the approriate information */
246
  for (i = 0; i < vec_len; i++)
247
    {
248
      struct JCL_buffer* buf;
249
      jobject bbuf;
250
 
251
      buf = &bi_list[i];
252
      bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
253
 
254
      if (num_bytes > (buf->limit - buf->position))
255
        buf->count = (buf->limit - buf->position);
256
      else
257
        buf->count = num_bytes;
258
 
259
      num_bytes -= buf->count;
260
 
261
      JCL_release_buffer(env, buf, bbuf, JNI_ABORT);
262
      (*env)->DeleteLocalRef(env, bbuf);
263
    }
264
}
265
 
266
 
267
int
268
JCL_thread_interrupted(JNIEnv *env)
269
{
270
  return (int) (*env)->CallStaticBooleanMethod(env, vm_channel_class,
271
                                               thread_interrupted_mid);
272
}
273
 
274
 
275
/*
276
 * Class:     gnu_java_nio_VMChannel
277
 * Method:    stdin_fd
278
 * Signature: ()I
279
 */
280
JNIEXPORT jint JNICALL
281
Java_gnu_java_nio_VMChannel_stdin_1fd (JNIEnv *env __attribute__((unused)),
282
                                       jclass c __attribute__((unused)))
283
{
284
/*   NIODBG("%d", fileno (stdin)); */
285
  return fileno (stdin);
286
}
287
 
288
 
289
/*
290
 * Class:     gnu_java_nio_VMChannel
291
 * Method:    stdout_fd
292
 * Signature: ()I
293
 */
294
JNIEXPORT jint JNICALL
295
Java_gnu_java_nio_VMChannel_stdout_1fd (JNIEnv *env __attribute__((unused)),
296
                                       jclass c __attribute__((unused)))
297
{
298
/*   NIODBG("%d", fileno (stdout)); */
299
  return fileno (stdout);
300
}
301
 
302
 
303
/*
304
 * Class:     gnu_java_nio_VMChannel
305
 * Method:    stderr_fd
306
 * Signature: ()I
307
 */
308
JNIEXPORT jint JNICALL
309
Java_gnu_java_nio_VMChannel_stderr_1fd (JNIEnv *env __attribute__((unused)),
310
                                       jclass c __attribute__((unused)))
311
{
312
/*   NIODBG("%d", fileno (stderr)); */
313
  return fileno (stderr);
314
}
315
 
316
 
317
JNIEXPORT void JNICALL
318
Java_gnu_java_nio_VMChannel_initIDs  (JNIEnv *env,
319
        jclass clazz)
320
{
321
  jclass bufferClass = JCL_FindClass(env, "java/nio/Buffer");
322
  jclass byteBufferClass = JCL_FindClass(env, "java/nio/ByteBuffer");
323
 
324
/*   NIODBG("%s", "..."); */
325
 
326
  address_fid = (*env)->GetFieldID(env, bufferClass, "address",
327
                                   "Lgnu/classpath/Pointer;");
328
  if (address_fid == NULL)
329
    {
330
          JCL_ThrowException(env, "java/lang/InternalError",
331
                "Unable to find internal field");
332
      return;
333
    }
334
 
335
  get_position_mid = get_method_id(env, bufferClass, "position", "()I");
336
  set_position_mid = get_method_id(env, bufferClass, "position",
337
                                   "(I)Ljava/nio/Buffer;");
338
  get_limit_mid = get_method_id(env, bufferClass, "limit", "()I");
339
  set_limit_mid = get_method_id(env, bufferClass, "limit",
340
                                "(I)Ljava/nio/Buffer;");
341
  has_array_mid = get_method_id(env, byteBufferClass, "hasArray", "()Z");
342
  array_mid = get_method_id(env, byteBufferClass, "array", "()[B");
343
  array_offset_mid = get_method_id(env, byteBufferClass, "arrayOffset", "()I");
344
 
345
  vm_channel_class = clazz;
346
  thread_interrupted_mid = (*env)->GetStaticMethodID(env, clazz,
347
                                                  "isThreadInterrupted",
348
                                                  "()Z");
349
}
350
 
351
JNIEXPORT void JNICALL
352
Java_gnu_java_nio_VMChannel_setBlocking (JNIEnv *env,
353
        jobject o __attribute__ ((__unused__)),
354
        jint fd,
355
        jboolean blocking)
356
{
357
  int opts;
358
 
359
/*   NIODBG("fd: %d; blocking: %d", fd, blocking); */
360
 
361
  opts = fcntl(fd, F_GETFL);
362
  if (opts < 0)
363
    {
364
      JCL_ThrowException(env, IO_EXCEPTION,
365
        "Failed to get flags for file desriptor");
366
      return;
367
    }
368
 
369
  if (blocking == JNI_TRUE)
370
    opts &= ~(O_NONBLOCK);
371
  else
372
    opts |= O_NONBLOCK;
373
 
374
  opts = fcntl(fd, F_SETFL, opts);
375
 
376
  if (opts < 0)
377
    {
378
      JCL_ThrowException(env, IO_EXCEPTION,
379
        "Failed to set flags for file desriptor");
380
      return;
381
    }
382
}
383
 
384
/* Return true if fd is in non-blocking mode. */
385
static jboolean
386
is_non_blocking_fd(jint fd)
387
{
388
  int opts;
389
  opts = fcntl(fd, F_GETFL);
390
  if (opts == -1)
391
    {
392
      /* Assume blocking on error. */
393
      return 0;
394
    }
395
  return (opts & O_NONBLOCK) != 0;
396
}
397
 
398
JNIEXPORT jint JNICALL
399
Java_gnu_java_nio_VMChannel_read__ILjava_nio_ByteBuffer_2 (JNIEnv *env,
400
                                                           jobject o __attribute__ ((__unused__)),
401
                                                           jint fd,
402
                                                           jobject bbuf)
403
{
404
#ifdef HAVE_READ
405
  jint len;
406
  ssize_t result;
407
  struct JCL_buffer buf;
408
  int tmp_errno;
409
 
410
/*   NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
411
 
412
  if (JCL_init_buffer(env, &buf, bbuf) < 0)
413
    {
414
      /* TODO: Rethrown exception */
415
      JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
416
      return -1;
417
    }
418
 
419
  len = buf.limit - buf.position;
420
 
421
  if (len == 0)
422
    {
423
      JCL_release_buffer (env, &buf, bbuf, JNI_ABORT);
424
      return 0;
425
    }
426
 
427
  do
428
    {
429
      result = cpnio_read (fd, &(buf.ptr[buf.position + buf.offset]), len);
430
      tmp_errno = errno;
431
    }
432
  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
433
  errno = tmp_errno;
434
 
435
  if (result == 0)
436
    {
437
      result = -1;
438
      buf.count = 0;
439
    }
440
  else if (result == -1)
441
    {
442
      buf.count = 0;
443
      if (errno == EAGAIN)
444
        {
445
          if (is_non_blocking_fd(fd))
446
            {
447
              /* Non-blocking */
448
              result = 0;
449
            }
450
          else
451
            {
452
              /* Read timeout on a socket with SO_RCVTIMEO != 0. */
453
              JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
454
              JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
455
              return -1;
456
            }
457
        }
458
      else if (errno == EBADF) /* Bad fd */
459
        {
460
          JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
461
          JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
462
                              strerror(errno));
463
          return -1;
464
        }
465
      else if (EINTR == errno) /* read interrupted */
466
        {
467
          JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
468
          JCL_ThrowException(env, INTERRUPTED_IO_EXCEPTION, strerror (errno));
469
          return -1;
470
        }
471
      else
472
        {
473
          JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
474
          JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
475
          return -1;
476
        }
477
    }
478
  else
479
    buf.count = result;
480
 
481
  JCL_release_buffer(env, &buf, bbuf, 0);
482
 
483
  return result;
484
#else
485
  (void) fd;
486
  (void) bbuf;
487
  JCL_ThrowException (env, IO_EXCEPTION, "read not supported");
488
  return -1;
489
#endif /* HAVE_READ */
490
}
491
 
492
JNIEXPORT jint JNICALL
493
Java_gnu_java_nio_VMChannel_write__ILjava_nio_ByteBuffer_2 (JNIEnv *env,
494
                                                            jobject o __attribute__ ((__unused__)),
495
                                                            jint fd,
496
                                                            jobject bbuf)
497
{
498
#ifdef HAVE_WRITE
499
  jint len;
500
  ssize_t result;
501
  struct JCL_buffer buf;
502
  int tmp_errno;
503
 
504
/*   NIODBG("fd: %d; bbuf: %p", fd, bbuf); */
505
 
506
  if (JCL_init_buffer(env, &buf, bbuf) < 0)
507
    {
508
      /* TODO: Rethrown exception */
509
      JCL_ThrowException (env, IO_EXCEPTION, "Buffer initialisation failed");
510
      return -1;
511
    }
512
 
513
  len = buf.limit - buf.position;
514
 
515
  if (len == 0)
516
    {
517
      JCL_release_buffer (env, &buf, bbuf, JNI_ABORT);
518
      return 0;
519
    }
520
 
521
  do
522
    {
523
      result = cpnio_write (fd, &(buf.ptr[buf.position + buf.offset]), len);
524
      tmp_errno = errno;
525
    }
526
  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
527
  errno = tmp_errno;
528
 
529
  buf.count = result;
530
 
531
  if (result == -1)
532
    {
533
      if (errno == EAGAIN) /* Non-blocking */
534
        {
535
          result = 0;
536
        }
537
      else
538
        {
539
          JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
540
          JCL_ThrowException(env, IO_EXCEPTION, strerror(errno));
541
          return -1;
542
        }
543
    }
544
 
545
  JCL_release_buffer(env, &buf, bbuf, JNI_ABORT);
546
 
547
  return result;
548
#else
549
  (void) fd;
550
  (void) bbuf;
551
  JCL_ThrowException (env, IO_EXCEPTION, "write not supported");
552
  return -1;
553
#endif /* HAVE_WRITE */
554
}
555
 
556
 
557
/*
558
 * Implementation of a scattering read.  Will use the appropriate
559
 * vector based read call (currently readv on Linux).
560
 *
561
 * This has a limit to the number of buffers that will be read.  It
562
 * will not make muliple readv calls.  This is to ensure that operations
563
 * are atomic.  Currently it is limited to 16 buffers.  This is for
564
 * compatibiliy with Sun.
565
 */
566
JNIEXPORT jlong JNICALL
567
Java_gnu_java_nio_VMChannel_readScattering (JNIEnv *env,
568
        jobject o __attribute__ ((__unused__)),
569
        jint fd,
570
        jobjectArray bbufs,
571
        jint offset,
572
        jint length)
573
{
574
  jint i;
575
/*   jboolean is_error = JNI_FALSE; */
576
/*   char *error_msg; */
577
  struct iovec buffers[JCL_IOV_MAX];
578
  struct JCL_buffer bi_list[JCL_IOV_MAX];
579
  ssize_t result;
580
  jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
581
  jlong bytes_read = 0;
582
  int tmp_errno;
583
 
584
/*   NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
585
/*          fd, bbufs, offset, length); */
586
 
587
  /* Build the vector of buffers to read into */
588
  for (i = 0; i < vec_len; i++)
589
    {
590
      struct JCL_buffer* buf;
591
      jobject bbuf;
592
 
593
      buf = &bi_list[i];
594
      bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
595
 
596
      JCL_init_buffer(env, buf, bbuf);
597
 
598
/*       JCL_print_buffer (env, buf); */
599
 
600
      buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
601
      buffers[i].iov_len = buf->limit - buf->position;
602
      (*env)->DeleteLocalRef(env, bbuf);
603
    }
604
 
605
  /* Work the scattering magic */
606
  do
607
    {
608
      result = cpnio_readv (fd, buffers, vec_len);
609
      tmp_errno = errno;
610
    }
611
  while (result == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
612
  errno = tmp_errno;
613
  bytes_read = (jlong) result;
614
 
615
  /* Handle the response */
616
  if (result < 0)
617
    {
618
      if (errno == EAGAIN)
619
        {
620
          if (is_non_blocking_fd(fd))
621
            {
622
              /* Non-blocking */
623
              result = 0;
624
            }
625
          else
626
            {
627
              /* Read timeout on a socket with SO_RCVTIMEO != 0. */
628
              JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
629
              JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
630
              return -1;
631
            }
632
        }
633
      else if (errno == EBADF) /* Bad fd */
634
        {
635
          JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
636
          JCL_ThrowException (env, NON_READABLE_CHANNEL_EXCEPTION,
637
                              strerror(errno));
638
          return -1;
639
        }
640
      else
641
        {
642
          JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
643
          JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
644
          return -1;
645
        }
646
      bytes_read = 0;
647
    }
648
  else if (result == 0) /* EOF */
649
    {
650
      result = -1;
651
    }
652
 
653
  JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_read);
654
 
655
  return (jlong) result;
656
}
657
 
658
 
659
/*
660
 * Implementation of a gathering write.  Will use the appropriate
661
 * vector based read call (currently readv on Linux).
662
 *
663
 * This has a limit to the number of buffers that will be read.  It
664
 * will not make muliple readv calls.  This is to ensure that operations
665
 * are atomic.  Currently it is limited to 16 buffers.  This is for
666
 * compatibiliy with Sun.
667
 */
668
JNIEXPORT jlong JNICALL
669
Java_gnu_java_nio_VMChannel_writeGathering (JNIEnv *env,
670
        jobject o __attribute__ ((__unused__)),
671
        jint fd,
672
        jobjectArray bbufs,
673
        jint offset,
674
        jint length)
675
{
676
  int i;
677
/*   jboolean is_error = JNI_FALSE; */
678
/*   char *error_msg; */
679
  struct iovec buffers[JCL_IOV_MAX];
680
  struct JCL_buffer bi_list[JCL_IOV_MAX];
681
  ssize_t result;
682
  jint vec_len = length < JCL_IOV_MAX ? length : JCL_IOV_MAX;
683
  jlong bytes_written;
684
  int tmp_errno;
685
 
686
/*   NIODBG("fd: %d; bbufs: %p; offset: %d; length: %d", */
687
/*          fd, bbufs, offset, length); */
688
 
689
  /* Build the vector of buffers to read into */
690
  for (i = 0; i < vec_len; i++)
691
    {
692
      struct JCL_buffer* buf;
693
      jobject bbuf;
694
 
695
      buf = &bi_list[i];
696
      bbuf = (*env)->GetObjectArrayElement(env, bbufs, offset + i);
697
 
698
      JCL_init_buffer(env, buf, bbuf);
699
 
700
/*       JCL_print_buffer(env, buf); */
701
 
702
      buffers[i].iov_base = &(buf->ptr[buf->position + buf->offset]);
703
      buffers[i].iov_len = buf->limit - buf->position;
704
      (*env)->DeleteLocalRef(env, bbuf);
705
    }
706
 
707
  /* Work the gathering magic */
708
  do
709
    {
710
      result = cpnio_writev (fd, buffers, vec_len);
711
      tmp_errno = errno;
712
    }
713
  while (result == -1 && tmp_errno == EINTR && ! JCL_thread_interrupted(env));
714
  errno = tmp_errno;
715
 
716
  bytes_written = (jlong) result;
717
 
718
  if (result < 0)
719
    {
720
      bytes_written = 0;
721
      if (errno == EAGAIN) /* Non blocking */
722
        result = 0;
723
      else if (errno == EBADF) /* Bad fd */
724
        {
725
          JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
726
                              bytes_written);
727
          JCL_ThrowException (env, NON_WRITABLE_CHANNEL_EXCEPTION,
728
                              strerror(errno));
729
          return -1;
730
        }
731
      else
732
        {
733
          JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset,
734
                              bytes_written);
735
          JCL_ThrowException (env, IO_EXCEPTION, strerror(errno));
736
          return -1;
737
        }
738
    }
739
  else if (result == 0) /* EOF??  Does this happen on a write */
740
    result = -1;
741
 
742
  JCL_cleanup_buffers(env, bi_list, vec_len, bbufs, offset, bytes_written);
743
  return (jlong) result;
744
}
745
 
746
 
747
/*
748
 * Class:     gnu_java_nio_VMChannel
749
 * Method:    receive
750
 * Signature: (Ljava/nio/ByteBuffer;Ljava/nio/ByteBuffer;)I
751
 */
752
JNIEXPORT jint JNICALL
753
Java_gnu_java_nio_VMChannel_receive (JNIEnv *env,
754
                                     jclass c __attribute__((unused)),
755
                                     jint fd, jobject dst, jobject addrPort)
756
{
757
#ifdef HAVE_RECVFROM
758
  char *addrPortPtr = (*env)->GetDirectBufferAddress (env, addrPort);
759
  struct JCL_buffer buf;
760
#ifdef HAVE_INET6
761
  struct sockaddr_in6 sock_storage;
762
  struct sockaddr_in6 *sock6;
763
  socklen_t slen = sizeof (struct sockaddr_in6);
764
#else
765
  struct sockaddr_in sock_storage;
766
  socklen_t slen = sizeof (struct sockaddr_in);
767
#endif /* HAVE_INET6 */
768
  struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
769
  struct sockaddr_in *sock4;
770
  int ret;
771
  jint result = -1;
772
 
773
  if (JCL_init_buffer (env, &buf, dst) == -1)
774
    JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
775
 
776
#ifndef HAVE_MSG_WAITALL
777
#define MSG_WAITALL       0
778
#endif
779
 
780
  ret = cpnio_recvfrom (fd, &(buf.ptr[buf.position + buf.offset]),
781
                        buf.limit - buf.position, MSG_WAITALL,
782
                        sockaddr, &slen);
783
 
784
  if (-1 == ret)
785
    {
786
      JCL_release_buffer (env, &buf, dst, JNI_ABORT);
787
      if (EINTR == errno)
788
        JCL_ThrowException (env, "java/io/InterruptedIOException", strerror (errno));
789
      else if (EAGAIN == errno)
790
        {
791
          /* If the socket is in blocking mode, our timeout expired. */
792
          int val = fcntl (fd, F_GETFL, 0);
793
          if (val == -1)
794
            JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
795
          else if ((val & O_NONBLOCK) == 0)
796
            JCL_ThrowException (env, "java/net/SocketTimeoutException",
797
                                "read timed out");
798
        }
799
      else
800
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
801
      return 0;
802
    }
803
 
804
  if (sockaddr->sa_family == AF_INET)
805
    {
806
      sock4 = (struct sockaddr_in *) sockaddr;
807
      memcpy (addrPortPtr, &(sock4->sin_addr.s_addr), 4);
808
      ;memcpy (addrPortPtr + 4, &(sock4->sin_port), 2);
809
      result = 4;
810
    }
811
#ifdef HAVE_INET6
812
  else if (sockaddr->sa_family == AF_INET6)
813
    {
814
      sock6 = (struct sockaddr_in6 *) sockaddr;
815
      memcpy (addrPortPtr, &(sock6->sin6_addr.s6_addr), 16);
816
      memcpy (addrPortPtr + 16, &(sock6->sin6_port), 2);
817
      result = 16;
818
    }
819
#endif /* HAVE_INET6 */
820
  else if (ret == 0)
821
    {
822
      result = 0;
823
    }
824
  else
825
    {
826
      JCL_ThrowException (env, "java/net/SocketException",
827
                          "unsupported address type returned");
828
    }
829
 
830
  buf.count += ret;
831
  JCL_release_buffer (env, &buf, dst, 0);
832
  return result;
833
#else
834
  (void) fd;
835
  (void) dst;
836
  (void) addrPort;
837
  JCL_ThrowException (env, IO_EXCEPTION, "recvfrom not supported");
838
#endif /* HAVE_RECVFROM */
839
}
840
 
841
 
842
/*
843
 * Class:     gnu_java_nio_VMChannel
844
 * Method:    send
845
 * Signature: (Ljava/nio/ByteBuffer;[BI)I
846
 */
847
JNIEXPORT jint JNICALL
848
Java_gnu_java_nio_VMChannel_send (JNIEnv *env,
849
                                  jclass c __attribute__((unused)),
850
                                  int fd, jobject src, jbyteArray addr, jint port)
851
{
852
#ifdef HAVE_SENDTO
853
  struct sockaddr_in sockaddr;
854
  jbyte *elems;
855
  struct JCL_buffer buf;
856
  int ret;
857
 
858
/*   NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
859
/*          fd, src, addr, port); */
860
 
861
  if (JCL_init_buffer (env, &buf, src) == -1)
862
    {
863
      JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
864
      return -1;
865
    }
866
 
867
/*   JCL_print_buffer (env, &buf); */
868
 
869
  elems = (*env)->GetByteArrayElements (env, addr, NULL);
870
 
871
  sockaddr.sin_family = AF_INET;
872
  sockaddr.sin_addr.s_addr = *((uint32_t *) elems);
873
  sockaddr.sin_port = htons (port);
874
 
875
  do
876
    {
877
      ret = cpnio_sendto (fd, &(buf.ptr[buf.position + buf.offset]),
878
                          buf.limit - buf.position,
879
                          0, (const struct sockaddr *) &sockaddr,
880
                          sizeof (struct sockaddr_in));
881
    }
882
  while (-1 == ret && EINTR == errno);
883
 
884
  (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
885
 
886
  if (-1 == ret)
887
    {
888
      if (errno != EAGAIN)
889
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
890
      JCL_release_buffer (env, &buf, src, JNI_ABORT);
891
      return 0;
892
    }
893
 
894
  buf.count += ret;
895
  JCL_release_buffer (env, &buf, src, JNI_ABORT);
896
  return ret;
897
#else
898
  (void) fd;
899
  (void) src;
900
  (void) addr;
901
  (void) port;
902
#endif /* HAVE_SENDTO */
903
}
904
 
905
 
906
/*
907
 * Class:     gnu_java_nio_VMChannel
908
 * Method:    send6
909
 * Signature: (Ljava/nio/ByteBuffer;[BI)I
910
 */
911
JNIEXPORT jint JNICALL
912
Java_gnu_java_nio_VMChannel_send6 (JNIEnv *env,
913
                                   jclass c __attribute__((unused)),
914
                                   int fd, jobject src, jbyteArray addr, jint port)
915
{
916
#if defined(HAVE_SENDTO) && defined(HAVE_INET6)
917
  struct sockaddr_in6 sockaddr;
918
  jbyte *elems;
919
  struct JCL_buffer buf;
920
  int ret;
921
 
922
/*   NIODBG("fd: %d; src: %p; addr: %p; port: %d", */
923
/*          fd, src, addr, port); */
924
 
925
  if (JCL_init_buffer (env, &buf, src) == -1)
926
    {
927
      JCL_ThrowException (env, IO_EXCEPTION, "loading buffer failed");
928
      return -1;
929
    }
930
 
931
/*   JCL_print_buffer (env, &buf); */
932
 
933
  elems = (*env)->GetByteArrayElements (env, addr, NULL);
934
 
935
  sockaddr.sin6_family = AF_INET6;
936
  memcpy (&sockaddr.sin6_addr.s6_addr, elems, 16);
937
  sockaddr.sin6_port = htons (port);
938
 
939
  do
940
    {
941
      ret = cpnio_sendto (fd, (const void *) (buf.ptr + buf.offset),
942
                          buf.limit - buf.position,
943
                          0, (const struct sockaddr *) &sockaddr,
944
                          sizeof (struct sockaddr_in6));
945
    }
946
  while (-1 == ret && EINTR == errno);
947
 
948
  (*env)->ReleaseByteArrayElements (env, addr, elems, JNI_ABORT);
949
 
950
  if (-1 == ret)
951
    {
952
      if (errno != EAGAIN)
953
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
954
      JCL_release_buffer (env, &buf, src, JNI_ABORT);
955
      return 0;
956
    }
957
 
958
  buf.count += ret;
959
  JCL_release_buffer (env, &buf, src, JNI_ABORT);
960
  return ret;
961
#else
962
  (void) fd;
963
  (void) src;
964
  (void) addr;
965
  (void) port;
966
  JCL_ThrowException (env, IO_EXCEPTION, "IPv6 sendto not supported");
967
  return -1;
968
#endif /* HAVE_SENDTO && HAVE_INET6 */
969
}
970
 
971
 
972
/*
973
 * Class:     gnu_java_nio_VMChannel
974
 * Method:    read
975
 * Signature: (I)I
976
 */
977
JNIEXPORT jint JNICALL
978
Java_gnu_java_nio_VMChannel_read__I (JNIEnv *env,
979
                                     jclass c __attribute__((unused)),
980
                                     jint fd)
981
{
982
#ifdef HAVE_READ
983
  char in;
984
  int ret;
985
  int tmp_errno;
986
 
987
/*   NIODBG("fd: %d", fd); */
988
 
989
  do
990
    {
991
      ret = cpnio_read (fd, &in, 1);
992
      tmp_errno = errno;
993
    }
994
  while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
995
  errno = tmp_errno;
996
 
997
  if (-1 == ret)
998
    {
999
      if (errno == EAGAIN && !is_non_blocking_fd(fd))
1000
        {
1001
          /* Read timeout on a socket with SO_RCVTIMEO != 0. */
1002
          JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "read timed out");
1003
        }
1004
      else
1005
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1006
      return -1;
1007
    }
1008
 
1009
  if (0 == ret)
1010
    return -1;
1011
 
1012
  return (in & 0xFF);
1013
#else
1014
  (void) fd;
1015
  JCL_ThrowException (env, IO_EXCEPTION, "read not supported");
1016
#endif /* HAVE_READ */
1017
}
1018
 
1019
 
1020
/*
1021
 * Class:     gnu_java_nio_VMChannel
1022
 * Method:    write
1023
 * Signature: (I)V
1024
 */
1025
JNIEXPORT void JNICALL
1026
Java_gnu_java_nio_VMChannel_write__II (JNIEnv *env,
1027
                                       jclass c __attribute__((unused)),
1028
                                       jint fd, jint data)
1029
{
1030
#ifdef HAVE_WRITE
1031
  char out = (char) data;
1032
  int ret;
1033
  int tmp_errno;
1034
 
1035
/*   NIODBG("fd: %d; data: %d", fd, data); */
1036
 
1037
  do
1038
    {
1039
      ret = cpnio_write (fd, &out, 1);
1040
      tmp_errno = errno;
1041
    }
1042
  while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
1043
  errno = tmp_errno;
1044
 
1045
  if (-1 == ret)
1046
    JCL_ThrowException(env, IO_EXCEPTION, strerror (errno));
1047
#else
1048
  (void) fd;
1049
  (void) data;
1050
  JCL_ThrowException (env, IO_EXCEPTION, "write not supported");
1051
#endif /* HAVE_WRITE */
1052
}
1053
 
1054
 
1055
/*
1056
 * Class:     gnu_java_nio_VMChannel
1057
 * Method:    socket
1058
 * Signature: (Z)I
1059
 */
1060
JNIEXPORT jint JNICALL
1061
Java_gnu_java_nio_VMChannel_socket (JNIEnv *env, jclass clazz __attribute__((unused)),
1062
                                    jboolean stream)
1063
{
1064
#ifdef HAVE_SOCKET
1065
  int ret;
1066
 
1067
  do
1068
    {
1069
      ret = cpnio_socket (AF_INET, stream ? SOCK_STREAM : SOCK_DGRAM, 0);
1070
    }
1071
  while (-1 == ret && EINTR == errno);
1072
 
1073
  if (ret == -1)
1074
    JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1075
/*   NIODBG("created socket %d", ret); */
1076
 
1077
  return ret;
1078
#else
1079
  (void) stream;
1080
  JCL_ThrowException (env, IO_EXCEPTION, "socket not supported");
1081
  return -1;
1082
#endif /* HAVE_SOCKET */
1083
}
1084
 
1085
 
1086
/*
1087
 * Class:     gnu_java_nio_VMChannel
1088
 * Method:    connect
1089
 * Signature: (I[BI)Z
1090
 */
1091
JNIEXPORT jboolean JNICALL
1092
Java_gnu_java_nio_VMChannel_connect (JNIEnv *env, jclass clazz __attribute__((unused)),
1093
                                     jint fd, jbyteArray addr, jint port, jint timeout)
1094
{
1095
#ifdef HAVE_CONNECT
1096
  struct sockaddr_in sockaddr;
1097
  struct timeval timeo;
1098
  int origflags = 0, flags;
1099
  jbyte *addr_elems;
1100
  int ret;
1101
  int tmpErrno;
1102
 
1103
  if ((*env)->GetArrayLength (env, addr) != 4)
1104
    {
1105
      JCL_ThrowException (env, SOCKET_EXCEPTION,
1106
                          "expecting 4-byte address");
1107
      return JNI_FALSE;
1108
    }
1109
 
1110
  if (timeout > 0)
1111
    {
1112
      timeo.tv_sec = timeout / 1000;
1113
      timeo.tv_usec = (timeout % 1000) * 1000;
1114
      origflags = fcntl (fd, F_GETFL, 0);
1115
      if (origflags == -1)
1116
        {
1117
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1118
          return JNI_FALSE;
1119
        }
1120
      /* Set nonblocking mode, if not already set. */
1121
      if (!(origflags & O_NONBLOCK))
1122
        {
1123
          flags = origflags | O_NONBLOCK;
1124
          if (fcntl (fd, F_SETFL, flags) == -1)
1125
            {
1126
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1127
              return JNI_FALSE;
1128
            }
1129
        }
1130
    }
1131
 
1132
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
1133
 
1134
  memset (&sockaddr, 0, sizeof (struct sockaddr_in));
1135
  sockaddr.sin_family = AF_INET;
1136
  sockaddr.sin_port = htons (port);
1137
  sockaddr.sin_addr.s_addr = *((uint32_t *) addr_elems);
1138
 
1139
 
1140
  do
1141
    {
1142
      ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr,
1143
                           sizeof (struct sockaddr_in));
1144
      tmpErrno = errno;
1145
    }
1146
  while (ret == -1 && errno == EINTR && ! JCL_thread_interrupted(env));
1147
  errno = tmpErrno;
1148
 
1149
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
1150
 
1151
  /* If a timeout was specified, select on the file descriptor with
1152
     the timeout. */
1153
  if (timeout > 0 && ret == -1)
1154
    {
1155
      /* Reset the non-blocking flag, if needed. */
1156
      if (!(origflags & O_NONBLOCK))
1157
        {
1158
          if (fcntl (fd, F_SETFL, origflags) == -1)
1159
            {
1160
              /* oops */
1161
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1162
              return JNI_FALSE;
1163
            }
1164
        }
1165
      if (EINPROGRESS == errno)
1166
        {
1167
          fd_set wrfds;
1168
          FD_ZERO(&wrfds);
1169
          FD_SET(fd, &wrfds);
1170
          ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
1171
          if (ret == -1)
1172
            {
1173
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1174
              return JNI_FALSE;
1175
            }
1176
          if (ret == 0) /* connect timed out */
1177
            {
1178
              JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION,
1179
                                  "connect timed out");
1180
              return JNI_FALSE;
1181
            }
1182
          return JNI_TRUE; /* Connected! */
1183
        }
1184
      else if (ECONNREFUSED == errno)
1185
        {
1186
          JCL_ThrowException (env, CONNECT_EXCEPTION,
1187
                              strerror (errno));
1188
          return JNI_FALSE;
1189
        }
1190
      else
1191
        {
1192
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1193
          return JNI_FALSE;
1194
        }
1195
    }
1196
 
1197
  if (ret == -1)
1198
    {
1199
      if (EINPROGRESS == errno)
1200
        return JNI_FALSE;
1201
      else if (ECONNREFUSED == errno)
1202
        {
1203
          JCL_ThrowException (env, CONNECT_EXCEPTION,
1204
                              strerror (errno));
1205
          return JNI_FALSE;
1206
        }
1207
      else
1208
        {
1209
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1210
          return JNI_FALSE;
1211
        }
1212
    }
1213
 
1214
  return JNI_TRUE;
1215
#else
1216
  (void) fd;
1217
  (void) addr;
1218
  (void) port;
1219
  (void) timeout;
1220
  JCL_ThrowException (env, SOCKET_EXCEPTION, "connect not supported");
1221
  return JNI_FALSE;
1222
#endif /* HAVE_CONNECT */
1223
}
1224
 
1225
 
1226
/*
1227
 * Class:     gnu_java_nio_VMChannel
1228
 * Method:    connect6
1229
 * Signature: (I[BI)Z
1230
 */
1231
JNIEXPORT jboolean JNICALL
1232
Java_gnu_java_nio_VMChannel_connect6 (JNIEnv *env, jclass clazz __attribute__((unused)),
1233
                                      jint fd, jbyteArray addr, jint port, int timeout)
1234
{
1235
#if defined(HAVE_CONNECT) && defined(HAVE_INET6)
1236
  struct sockaddr_in6 sockaddr;
1237
  struct timeval timeo;
1238
  int flags, origflags = 0;
1239
  jbyte *addr_elems;
1240
  int ret;
1241
 
1242
  if (timeout > 0)
1243
    {
1244
      timeo.tv_sec = timeout / 1000;
1245
      timeo.tv_usec = (timeout % 1000) * 1000;
1246
      origflags = fcntl (fd, F_GETFL, 0);
1247
      if (origflags == -1)
1248
        {
1249
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1250
          return JNI_FALSE;
1251
        }
1252
      /* Set nonblocking mode, if not already set. */
1253
      if (!(origflags & O_NONBLOCK))
1254
        {
1255
          flags = origflags | O_NONBLOCK;
1256
          if (fcntl (fd, F_SETFL, flags) == -1)
1257
            {
1258
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1259
              return JNI_FALSE;
1260
            }
1261
        }
1262
    }
1263
 
1264
  addr_elems = (*env)->GetByteArrayElements (env, addr, NULL);
1265
 
1266
  memset (&sockaddr, 0, sizeof (struct sockaddr_in6));
1267
  sockaddr.sin6_family = AF_INET6;
1268
  sockaddr.sin6_port = htons (port);
1269
  memcpy (&sockaddr.sin6_addr.s6_addr, addr_elems, 16);
1270
 
1271
  ret = cpnio_connect (fd, (struct sockaddr *) &sockaddr,
1272
                       sizeof (struct sockaddr_in6));
1273
 
1274
  (*env)->ReleaseByteArrayElements (env, addr, addr_elems, JNI_ABORT);
1275
 
1276
  /* If a timeout was specified, select on the file descriptor with
1277
     the timeout. */
1278
  if (timeout > 0 && ret == -1)
1279
    {
1280
      /* Reset the non-blocking flag, if needed. */
1281
      if (!(origflags & O_NONBLOCK))
1282
        {
1283
          if (fcntl (fd, F_SETFL, origflags) == -1)
1284
            {
1285
              /* oops */
1286
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1287
              return JNI_FALSE;
1288
            }
1289
        }
1290
      if (EINPROGRESS == errno)
1291
        {
1292
          fd_set wrfds;
1293
          FD_ZERO(&wrfds);
1294
          FD_SET(fd, &wrfds);
1295
          ret = cpnio_select (fd + 1, NULL, &wrfds, NULL, &timeo);
1296
          if (ret == -1)
1297
            {
1298
              JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1299
              return JNI_FALSE;
1300
            }
1301
          if (ret == 0) /* connect timed out */
1302
            {
1303
              JCL_ThrowException (env, SOCKET_TIMEOUT_EXCEPTION,
1304
                                  "connect timed out");
1305
              return JNI_FALSE;
1306
            }
1307
          return JNI_TRUE; /* Connected! */
1308
        }
1309
      else if (ECONNREFUSED == errno)
1310
        {
1311
          JCL_ThrowException (env, CONNECT_EXCEPTION,
1312
                              strerror (errno));
1313
          return JNI_FALSE;
1314
        }
1315
      else
1316
        {
1317
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1318
          return JNI_FALSE;
1319
        }
1320
    }
1321
 
1322
  if (ret == -1)
1323
    {
1324
      if (EAGAIN == errno)
1325
        return JNI_FALSE;
1326
      else if (ECONNREFUSED == errno)
1327
        {
1328
          JCL_ThrowException (env, CONNECT_EXCEPTION,
1329
                              strerror (errno));
1330
          return JNI_FALSE;
1331
        }
1332
      else
1333
        {
1334
          JCL_ThrowException (env, SOCKET_EXCEPTION, strerror (errno));
1335
          return JNI_FALSE;
1336
        }
1337
    }
1338
 
1339
  return JNI_TRUE;
1340
#else
1341
  (void) fd;
1342
  (void) addr;
1343
  (void) port;
1344
  (void) timeout;
1345
  JCL_ThrowException (env, SOCKET_EXCEPTION, "IPv6 connect not supported");
1346
  return JNI_FALSE;
1347
#endif /* HAVE_CONNECT && HAVE_INET6 */
1348
}
1349
 
1350
 
1351
/*
1352
 * Class:     gnu_java_nio_VMChannel
1353
 * Method:    getsockname
1354
 * Signature: (ILjava/nio/ByteBuffer;)I
1355
 */
1356
JNIEXPORT jint JNICALL
1357
Java_gnu_java_nio_VMChannel_getsockname (JNIEnv *env, jclass clazz __attribute__((unused)),
1358
                                         jint fd, jobject name)
1359
{
1360
#ifdef HAVE_GETSOCKNAME
1361
#ifdef HAVE_INET6
1362
  struct sockaddr_in6 *addr6;
1363
  struct sockaddr_in6 sock_storage;
1364
  socklen_t socklen = sizeof (struct sockaddr_in6);
1365
#else
1366
  struct sockaddr_in sock_storage;
1367
  socklen_t socklen = sizeof (struct sockaddr_in);
1368
#endif /* HAVE_INET6 */
1369
 
1370
  struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
1371
  struct sockaddr_in *addr4;
1372
  int ret;
1373
  char *nameptr = (*env)->GetDirectBufferAddress (env, name);
1374
 
1375
  ret = getsockname (fd, sockaddr, &socklen);
1376
  if (ret == -1)
1377
    {
1378
      JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1379
      return 0;
1380
    }
1381
 
1382
  if (sockaddr->sa_family == AF_INET)
1383
    {
1384
      addr4 = (struct sockaddr_in *) sockaddr;
1385
      memcpy (nameptr, &(addr4->sin_addr.s_addr), 4);
1386
      memcpy (nameptr + 4, &(addr4->sin_port), 2);
1387
      return 4;
1388
    }
1389
 
1390
#ifdef HAVE_INET6
1391
  /* IPv6 */
1392
  if (sockaddr->sa_family == AF_INET6)
1393
    {
1394
      addr6 = (struct sockaddr_in6 *) sockaddr;
1395
      memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
1396
      memcpy (nameptr + 16, &(addr6->sin6_port), 2);
1397
      return 16;
1398
    }
1399
#endif /* HAVE_INET6 */
1400
  JCL_ThrowException (env, IO_EXCEPTION, "unsupported address format");
1401
  return -1;
1402
#else
1403
  (void) fd;
1404
  (void) name;
1405
  JCL_ThrowException (env, IO_EXCEPTION, "getsockname not supported");
1406
  return -1;
1407
#endif /* HAVE_GETSOCKNAME */
1408
}
1409
 
1410
 
1411
/*
1412
 * Class:     gnu_java_nio_VMChannel
1413
 * Method:    getpeername
1414
 * Signature: (ILjava/nio/ByteBuffer;)I
1415
 */
1416
JNIEXPORT jint JNICALL
1417
Java_gnu_java_nio_VMChannel_getpeername (JNIEnv *env, jclass clazz __attribute__((unused)),
1418
                                         jint fd, jobject name)
1419
{
1420
#ifdef HAVE_GETPEERNAME
1421
#ifdef HAVE_INET6
1422
  struct sockaddr_in6 *addr6;
1423
  struct sockaddr_in6 sock_storage;
1424
  socklen_t socklen = sizeof (struct sockaddr_in6);
1425
#else
1426
  struct sockaddr_in sock_storage;
1427
  socklen_t socklen = sizeof (struct sockaddr_in);
1428
#endif /* HAVE_INET6 */
1429
 
1430
  struct sockaddr *sockaddr = (struct sockaddr *) &sock_storage;
1431
  struct sockaddr_in *addr4;
1432
  int ret;
1433
  char *nameptr = (*env)->GetDirectBufferAddress (env, name);
1434
 
1435
  ret = getpeername (fd, sockaddr, &socklen);
1436
  if (ret == -1)
1437
    {
1438
      if (ENOTCONN != errno)
1439
        JCL_ThrowException (env, "java/net/SocketException", strerror (errno));
1440
      return 0;
1441
    }
1442
 
1443
  if (sockaddr->sa_family == AF_INET)
1444
    {
1445
      addr4 = (struct sockaddr_in *) sockaddr;
1446
      memcpy (nameptr, &(addr4->sin_addr.s_addr), 4);
1447
      memcpy (nameptr + 4, &(addr4->sin_port), 2);
1448
      return 4;
1449
    }
1450
#ifdef HAVE_INET6
1451
  else if (sockaddr->sa_family == AF_INET6)
1452
    {
1453
      addr6 = (struct sockaddr_in6 *) sockaddr;
1454
      memcpy (nameptr, &(addr6->sin6_addr.s6_addr), 16);
1455
      memcpy (nameptr + 16, &(addr6->sin6_port), 2);
1456
      return 16;
1457
    }
1458
#endif /* HAVE_INET6 */
1459
 
1460
  JCL_ThrowException (env, "java/net/SocketException",
1461
                      "unsupported address type");
1462
  return -1;
1463
#else
1464
  (void) fd;
1465
  (void) name;
1466
  JCL_ThrowException (env, IO_EXCEPTION, "getpeername not supported");
1467
  return -1;
1468
#endif /* HAVE_GETPEERNAME */
1469
}
1470
 
1471
 
1472
/*
1473
 * Class:     gnu_java_nio_VMChannel
1474
 * Method:    accept
1475
 * Signature: (I)I
1476
 */
1477
JNIEXPORT jint JNICALL
1478
Java_gnu_java_nio_VMChannel_accept (JNIEnv *env,
1479
                                    jclass c __attribute__((unused)),
1480
                                    jint fd)
1481
{
1482
#ifdef HAVE_ACCEPT
1483
  int ret;
1484
  int tmp_errno = 0;
1485
 
1486
#ifdef HAVE_INET6
1487
  struct sockaddr_in6 addr;
1488
  socklen_t alen = sizeof (struct sockaddr_in6);
1489
#else
1490
  struct sockaddr_in addr;
1491
  socklen_t alen = sizeof (struct sockaddr_in);
1492
#endif /* HAVE_INET6 */
1493
 
1494
  do
1495
    {
1496
      ret = cpnio_accept (fd, (struct sockaddr *) &addr, &alen);
1497
      tmp_errno = errno;
1498
 
1499
      if (ret == -1)
1500
        switch (tmp_errno)
1501
        {
1502
          case EINTR:
1503
            /* Check if interrupted by Thread.interrupt(). If not then some
1504
             * other unrelated signal interrupted the system function and
1505
             * we should start over again.
1506
             */
1507
            if (JCL_thread_interrupted(env))
1508
              {
1509
                JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
1510
                return -1;
1511
              }
1512
            break;
1513
#if defined(EWOULDBLOCK) && defined(EAGAIN) && EWOULDBLOCK != EAGAIN
1514
          case EWOULDBLOCK:
1515
#endif
1516
          case EAGAIN:
1517
            if (!is_non_blocking_fd(fd))
1518
              {
1519
                JCL_ThrowException(env, SOCKET_TIMEOUT_EXCEPTION, "Accept timed out");
1520
              }
1521
            /* Socket in non-blocking mode and no pending connection. */
1522
            return -1;
1523
          default:
1524
            JCL_ThrowException (env, "java/net/SocketException", strerror (tmp_errno));
1525
            return -1;
1526
        }
1527
      else
1528
        break;
1529
    }
1530
  while (1);
1531
 
1532
  cpio_closeOnExec(ret);
1533
 
1534
  return ret;
1535
#else
1536
  (void) fd;
1537
  JCL_ThrowException (env, IO_EXCEPTION, "accept not supported");
1538
  return -1;
1539
#endif /* HAVE_ACCEPT */
1540
}
1541
 
1542
 
1543
 
1544
/*
1545
 * Class:     gnu_java_nio_VMChannel
1546
 * Method:    disconnect
1547
 * Signature: (I)V
1548
 */
1549
JNIEXPORT void JNICALL
1550
Java_gnu_java_nio_VMChannel_disconnect (JNIEnv *env,
1551
                                        jclass c __attribute__((unused)),
1552
                                        jint fd)
1553
{
1554
  struct sockaddr sockaddr;
1555
 
1556
  sockaddr.sa_family = AF_UNSPEC;
1557
  if (connect (fd, &sockaddr, sizeof (struct sockaddr)) == -1)
1558
    {
1559
      /* The expected error for a successful disconnect is EAFNOSUPPORT. */
1560
      if (errno != EAFNOSUPPORT)
1561
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1562
    }
1563
}
1564
 
1565
 
1566
/*
1567
 * Class:     gnu_java_nio_VMChannel
1568
 * Method:    close
1569
 * Signature: (I)V
1570
 */
1571
JNIEXPORT void JNICALL
1572
Java_gnu_java_nio_VMChannel_close (JNIEnv *env,
1573
                                   jclass c __attribute__((unused)),
1574
                                   jint fd)
1575
{
1576
  if (close (fd) == -1)
1577
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1578
}
1579
 
1580
 
1581
/*
1582
 * Class:     gnu_java_nio_VMChannel
1583
 * Method:    available
1584
 * Signature: (I)I
1585
 */
1586
JNIEXPORT jint JNICALL
1587
Java_gnu_java_nio_VMChannel_available (JNIEnv *env,
1588
                                       jclass c __attribute__((unused)),
1589
                                       jint fd)
1590
{
1591
#if defined (FIONREAD)
1592
 
1593
  jint avail = 0;
1594
 
1595
#if defined(ENOTTY) && defined(HAVE_FSTAT)
1596
  struct stat statBuffer;
1597
  off_t n;
1598
#endif
1599
 
1600
/*   NIODBG("fd: %d", fd); */
1601
  if (ioctl (fd, FIONREAD, &avail) == -1)
1602
    {
1603
#if defined(ENOTTY) && defined(HAVE_FSTAT)
1604
      if (errno == ENOTTY)
1605
        {
1606
          if ((fstat (fd, &statBuffer) == 0) && S_ISREG (statBuffer.st_mode))
1607
            {
1608
              n = lseek (fd, 0, SEEK_CUR);
1609
              if (n != -1)
1610
                {
1611
                  avail = statBuffer.st_size - n;
1612
                  return avail;
1613
                }
1614
            }
1615
        }
1616
#endif
1617
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1618
    }
1619
/*   NIODBG("avail: %d", avail); */
1620
 
1621
  return avail;
1622
 
1623
#elif defined(HAVE_FSTAT)
1624
 
1625
  jint avail = 0;
1626
 
1627
  struct stat statBuffer;
1628
  off_t n;
1629
 
1630
  if ((fstat (fd, &statBuffer) == 0) && S_ISREG (statBuffer.st_mode))
1631
    {
1632
      n = lseek (fd, 0, SEEK_CUR);
1633
      if (n != -1)
1634
        {
1635
          avail = statBuffer.st_size - n;
1636
          return avail;
1637
        }
1638
    }
1639
  JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1640
 
1641
#elif defined(HAVE_SELECT)
1642
 
1643
  jint avail = 0;
1644
  fd_set filedescriptset;
1645
  struct timeval tv;
1646
 
1647
  FD_ZERO (&filedescriptset);
1648
  FD_SET (fd,&filedescriptset);
1649
  memset (&tv, 0, sizeof(tv));
1650
 
1651
  switch (select (fd+1, &filedescriptset, NULL, NULL, &tv))
1652
    {
1653
      case -1:
1654
        break;
1655
      case  0:
1656
        avail = 0;
1657
        return avail;
1658
      default:
1659
        avail = 1;
1660
        return avail;
1661
    }
1662
  JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1663
 
1664
#else
1665
 
1666
  JCL_ThrowException (env, IO_EXCEPTION, "No native method for available");
1667
 
1668
#endif
1669
}
1670
 
1671
 
1672
enum FileChannel_mode {
1673
  CPNIO_READ   = 1,
1674
  CPNIO_WRITE  = 2,
1675
  CPNIO_APPEND = 4,
1676
  CPNIO_EXCL   = 8,
1677
  CPNIO_SYNC   = 16,
1678
  CPNIO_DSYNC  = 32
1679
};
1680
 
1681
 
1682
/*
1683
 * Class:     gnu_java_nio_VMChannel
1684
 * Method:    open
1685
 * Signature: (Ljava/lang/String;I)I
1686
 */
1687
JNIEXPORT jint JNICALL
1688
Java_gnu_java_nio_VMChannel_open (JNIEnv *env,
1689
                                  jclass c __attribute__((unused)),
1690
                                  jstring path, jint mode)
1691
{
1692
  int nmode = 0;
1693
  int ret;
1694
  const char *npath;
1695
 
1696
  if ((mode & CPNIO_READ) && (mode & CPNIO_WRITE))
1697
    nmode = O_RDWR;
1698
  else if (mode & CPNIO_WRITE)
1699
    nmode = O_WRONLY;
1700
  else
1701
    nmode = O_RDONLY;
1702
 
1703
  nmode = (nmode
1704
           | ((nmode == O_RDWR || nmode == O_WRONLY) ? O_CREAT : 0)
1705
           | ((mode & CPNIO_APPEND) ? O_APPEND :
1706
              ((nmode == O_WRONLY) ? O_TRUNC : 0))
1707
           | ((mode & CPNIO_EXCL) ? O_EXCL : 0)
1708
           | ((mode & CPNIO_SYNC) ? O_SYNC : 0));
1709
 
1710
  npath = JCL_jstring_to_cstring (env, path);
1711
 
1712
/*   NIODBG("path: %s; mode: %x", npath, nmode); */
1713
 
1714
  ret = open (npath, nmode, 0666);
1715
 
1716
/*   NIODBG("ret: %d\n", ret); */
1717
 
1718
  JCL_free_cstring (env, path, npath);
1719
 
1720
  if (-1 == ret)
1721
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1722
 
1723
  return ret;
1724
}
1725
 
1726
 
1727
/*
1728
 * Class:     gnu_java_nio_VMChannel
1729
 * Method:    position
1730
 * Signature: (I)J
1731
 */
1732
JNIEXPORT jlong JNICALL
1733
Java_gnu_java_nio_VMChannel_position (JNIEnv *env,
1734
                                      jclass c __attribute__((unused)),
1735
                                      jint fd)
1736
{
1737
#ifdef HAVE_LSEEK
1738
  off_t ret;
1739
 
1740
  ret = lseek (fd, 0, SEEK_CUR);
1741
 
1742
  if (-1 == ret)
1743
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1744
 
1745
  return (jlong) ret;
1746
#else
1747
  JCL_ThrowException (env, IO_EXCEPTION, "position not supported");
1748
  return -1;
1749
#endif /* HAVE_LSEEK */
1750
}
1751
 
1752
 
1753
/*
1754
 * Class:     gnu_java_nio_VMChannel
1755
 * Method:    seek
1756
 * Signature: (IJ)V
1757
 */
1758
JNIEXPORT void JNICALL
1759
Java_gnu_java_nio_VMChannel_seek (JNIEnv *env,
1760
                                  jclass c __attribute__((unused)),
1761
                                  jint fd, jlong pos)
1762
{
1763
#ifdef HAVE_LSEEK
1764
  if (lseek (fd, (off_t) pos, SEEK_SET) == -1)
1765
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1766
#else
1767
  JCL_ThrowException (env, IO_EXCEPTION, "seek not supported");
1768
#endif /* HAVE_LSEEK */
1769
}
1770
 
1771
 
1772
/*
1773
 * Class:     gnu_java_nio_VMChannel
1774
 * Method:    truncate
1775
 * Signature: (IJ)V
1776
 */
1777
JNIEXPORT void JNICALL
1778
Java_gnu_java_nio_VMChannel_truncate (JNIEnv *env,
1779
                                      jclass c __attribute__((unused)),
1780
                                      jint fd, jlong len)
1781
{
1782
#if defined(HAVE_FTRUNCATE) && defined(HAVE_LSEEK)
1783
  off_t pos = lseek (fd, 0, SEEK_CUR);
1784
  if (pos == -1)
1785
    {
1786
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1787
      return;
1788
    }
1789
  if (ftruncate (fd, (off_t) len) == -1)
1790
    {
1791
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1792
      return;
1793
    }
1794
  if (pos > len)
1795
    {
1796
      if (lseek (fd, len, SEEK_SET) == -1)
1797
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1798
    }
1799
#else
1800
  JCL_ThrowException (env, IO_EXCEPTION, "truncate not supported");
1801
#endif /* HAVE_FTRUNCATE && HAVE_LSEEK */
1802
}
1803
 
1804
 
1805
/*
1806
 * Class:     gnu_java_nio_VMChannel
1807
 * Method:    lock
1808
 * Signature: (IJJZZ)Z
1809
 */
1810
JNIEXPORT jboolean JNICALL
1811
Java_gnu_java_nio_VMChannel_lock (JNIEnv *env,
1812
                                  jclass c __attribute__((unused)),
1813
                                  jint fd, jlong pos, jlong len,
1814
                                  jboolean shared, jboolean wait)
1815
{
1816
#if HAVE_FCNTL
1817
  struct flock fl;
1818
 
1819
  fl.l_start  = (off_t) pos;
1820
  /* Long.MAX_VALUE means lock everything possible starting at pos. */
1821
  if (len == 9223372036854775807LL)
1822
    fl.l_len = 0;
1823
  else
1824
    fl.l_len = (off_t) len;
1825
  fl.l_pid    = getpid ();
1826
  fl.l_type   = (shared ? F_RDLCK : F_WRLCK);
1827
  fl.l_whence = SEEK_SET;
1828
 
1829
  if (cpnio_fcntl (fd, (wait ? F_SETLKW : F_SETLK), (long) &fl) == -1)
1830
    {
1831
      if (errno != EAGAIN)
1832
        JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1833
      return JNI_FALSE;
1834
    }
1835
 
1836
  return JNI_TRUE;
1837
#else
1838
  JCL_ThrowException (env, IO_EXCEPTION, "lock not supported");
1839
  return JNI_FALSE;
1840
#endif /* HAVE_FCNTL */
1841
}
1842
 
1843
/*
1844
 * Class:     gnu_java_nio_VMChannel
1845
 * Method:    unlock
1846
 * Signature: (IJJ)V
1847
 */
1848
JNIEXPORT void JNICALL
1849
Java_gnu_java_nio_VMChannel_unlock (JNIEnv *env,
1850
                                    jclass c __attribute__((unused)),
1851
                                    jint fd, jlong pos, jlong len)
1852
{
1853
#if HAVE_FCNTL
1854
  struct flock fl;
1855
 
1856
  fl.l_start  = (off_t) pos;
1857
  fl.l_len    = (off_t) len;
1858
  fl.l_pid    = getpid ();
1859
  fl.l_type   = F_UNLCK;
1860
  fl.l_whence = SEEK_SET;
1861
 
1862
  if (cpnio_fcntl (fd, F_SETLK, (long) &fl) == -1)
1863
    {
1864
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1865
    }
1866
#else
1867
  JCL_ThrowException (env, IO_EXCEPTION, "unlock not supported");
1868
#endif /* HAVE_FCNTL */
1869
}
1870
 
1871
/*
1872
 * Class:     gnu_java_nio_VMChannel
1873
 * Method:    size
1874
 * Signature: (I)J
1875
 */
1876
JNIEXPORT jlong JNICALL
1877
Java_gnu_java_nio_VMChannel_size (JNIEnv *env,
1878
                                  jclass c __attribute__((unused)),
1879
                                  jint fd)
1880
{
1881
#ifdef HAVE_FSTAT
1882
  struct stat st;
1883
 
1884
  if (fstat (fd, &st) == -1)
1885
    JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1886
 
1887
  return (jlong) st.st_size;
1888
#else
1889
  JCL_ThrowException (env, IO_EXCEPTION, "size not supported");
1890
  return 0;
1891
#endif
1892
}
1893
 
1894
/*
1895
 * Class:     gnu_java_nio_VMChannel
1896
 * Method:    map
1897
 * Signature: (ICJI)Lgnu/classpath/Pointer;
1898
 */
1899
JNIEXPORT jobject JNICALL
1900
Java_gnu_java_nio_VMChannel_map (JNIEnv *env,
1901
                                 jclass clazz __attribute__((unused)),
1902
                                 jint fd, jchar mode, jlong position, jint size)
1903
{
1904
#ifdef HAVE_MMAP
1905
  jclass MappedByteBufferImpl_class;
1906
  jmethodID MappedByteBufferImpl_init = NULL;
1907
  jobject Pointer_instance;
1908
  volatile jobject buffer;
1909
  long pagesize;
1910
  int prot, flags;
1911
  void *p;
1912
  void *address;
1913
 
1914
/*   NIODBG("fd: %d; mode: %x; position: %lld; size: %d", */
1915
/*          fd, mode, position, size); */
1916
 
1917
  /* FIXME: should we just assume we're on an OS modern enough to
1918
     have 'sysconf'? And not check for 'getpagesize'? */
1919
#if defined(HAVE_GETPAGESIZE)
1920
  pagesize = getpagesize ();
1921
#elif defined(HAVE_SYSCONF)
1922
  pagesize = sysconf (_SC_PAGESIZE);
1923
#else
1924
  JCL_ThrowException (env, IO_EXCEPTION,
1925
                      "can't determine memory page size");
1926
  return NULL;
1927
#endif /* HAVE_GETPAGESIZE/HAVE_SYSCONF */
1928
 
1929
  if ((*env)->ExceptionOccurred (env))
1930
    {
1931
      return NULL;
1932
    }
1933
 
1934
  prot = PROT_READ;
1935
  if (mode == '+' || mode == 'c')
1936
    {
1937
      /* When writing we need to make sure the file is big enough,
1938
         otherwise the result of mmap is undefined. */
1939
      struct stat st;
1940
      if (fstat (fd, &st) == -1)
1941
        {
1942
          JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1943
          return NULL;
1944
        }
1945
      if (position + size > st.st_size)
1946
        {
1947
          if (ftruncate(fd, position + size) == -1)
1948
            {
1949
              JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1950
              return NULL;
1951
            }
1952
        }
1953
      prot |= PROT_WRITE;
1954
    }
1955
 
1956
  flags = (mode == 'c' ? MAP_PRIVATE : MAP_SHARED);
1957
  p = mmap (NULL, (size_t) ALIGN_UP (size, pagesize), prot, flags,
1958
            fd, ALIGN_DOWN (position, pagesize));
1959
  if (p == MAP_FAILED)
1960
    {
1961
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
1962
      return NULL;
1963
    }
1964
 
1965
  /* Unalign the mapped value back up, since we aligned offset
1966
     down to a multiple of the page size. */
1967
  address = (void *) ((char *) p + (position % pagesize));
1968
 
1969
  Pointer_instance = JCL_NewRawDataObject(env, address);
1970
 
1971
  MappedByteBufferImpl_class = (*env)->FindClass (env,
1972
                                                  "java/nio/MappedByteBufferImpl");
1973
  if (MappedByteBufferImpl_class != NULL)
1974
    {
1975
      MappedByteBufferImpl_init =
1976
        (*env)->GetMethodID (env, MappedByteBufferImpl_class,
1977
                             "<init>", "(Lgnu/classpath/Pointer;IZ)V");
1978
    }
1979
 
1980
  if ((*env)->ExceptionOccurred (env))
1981
    {
1982
      munmap (p, ALIGN_UP (size, pagesize));
1983
      return NULL;
1984
    }
1985
  if (MappedByteBufferImpl_init == NULL)
1986
    {
1987
      JCL_ThrowException (env, "java/lang/InternalError",
1988
                          "could not get MappedByteBufferImpl constructor");
1989
      munmap (p, ALIGN_UP (size, pagesize));
1990
      return NULL;
1991
    }
1992
 
1993
  buffer = (*env)->NewObject (env, MappedByteBufferImpl_class,
1994
                              MappedByteBufferImpl_init, Pointer_instance,
1995
                              (jint) size, mode == 'r');
1996
  return buffer;
1997
#else
1998
  (void) fd;
1999
  (void) mode;
2000
  (void) position;
2001
  (void) size;
2002
  JCL_ThrowException (env, IO_EXCEPTION,
2003
                      "memory-mapped files not implemented");
2004
  return 0;
2005
#endif /* HAVE_MMAP */
2006
}
2007
 
2008
/*
2009
 * Class:     gnu_java_nio_VMChannel
2010
 * Method:    flush
2011
 * Signature: (IZ)Z
2012
 */
2013
JNIEXPORT jboolean JNICALL
2014
Java_gnu_java_nio_VMChannel_flush (JNIEnv *env,
2015
                                   jclass c __attribute__((unused)),
2016
                                   jint fd, jboolean metadata __attribute__((unused)))
2017
{
2018
#ifdef HAVE_FSYNC
2019
  /* XXX blocking? */
2020
  if (fsync (fd) == -1)
2021
    {
2022
      JCL_ThrowException (env, IO_EXCEPTION, strerror (errno));
2023
      return JNI_FALSE;
2024
    }
2025
  return JNI_TRUE;
2026
#else
2027
  JCL_ThrowException (env, IO_EXCEPTION, "flush not implemented");
2028
  return JNI_TRUE;
2029
#endif /* HAVE_FSYNC */
2030
}
2031
 
2032
 
2033
#ifdef __cplusplus
2034
}
2035
#endif

powered by: WebSVN 2.1.0

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