Advertisement
Guest User

Untitled

a guest
Jun 25th, 2010
191
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 10.07 KB | None | 0 0
  1. /*
  2.  * Copyright 2000-2007 Sun Microsystems, Inc.  All Rights Reserved.
  3.  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4.  *
  5.  * This code is free software; you can redistribute it and/or modify it
  6.  * under the terms of the GNU General Public License version 2 only, as
  7.  * published by the Free Software Foundation.  Sun designates this
  8.  * particular file as subject to the "Classpath" exception as provided
  9.  * by Sun in the LICENSE file that accompanied this code.
  10.  *
  11.  * This code is distributed in the hope that it will be useful, but WITHOUT
  12.  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13.  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14.  * version 2 for more details (a copy is included in the LICENSE file that
  15.  * accompanied this code).
  16.  *
  17.  * You should have received a copy of the GNU General Public License version
  18.  * 2 along with this work; if not, write to the Free Software Foundation,
  19.  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20.  *
  21.  * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
  22.  * CA 95054 USA or visit www.sun.com if you need additional information or
  23.  * have any questions.
  24.  */
  25.  
  26. #include "jni.h"
  27. #include "jni_util.h"
  28. #include "jvm.h"
  29. #include "jlong.h"
  30. #include <sys/mman.h>
  31. #include <sys/stat.h>
  32. #include "sun_nio_ch_FileChannelImpl.h"
  33. #include "java_lang_Integer.h"
  34. #include "nio.h"
  35. #include "nio_util.h"
  36. #include <dlfcn.h>
  37.  
  38. static jfieldID chan_fd;        /* jobject 'fd' in sun.io.FileChannelImpl */
  39.  
  40. #ifdef __solaris__
  41. typedef struct sendfilevec64 {
  42.     int     sfv_fd;         /* input fd */
  43.     uint_t  sfv_flag;       /* Flags. see below */
  44.     off64_t sfv_off;        /* offset to start reading from */
  45.     size_t  sfv_len;        /* amount of data */
  46. } sendfilevec_t;
  47.  
  48. /* Function pointer for sendfilev on Solaris 8+ */
  49. typedef ssize_t sendfile_func(int fildes, const struct sendfilevec64 *vec,
  50.                               int sfvcnt, size_t *xferred);
  51.  
  52. sendfile_func* my_sendfile_func = NULL;
  53. #endif
  54.  
  55. #ifdef __linux__
  56. #include <sys/sendfile.h>
  57.  
  58. /* Function pointer for sendfile64 on Linux 2.6 (and newer 2.4 kernels) */
  59. typedef ssize_t sendfile64_func(int out_fd, int in_fd, off64_t *offset, size_t count);
  60.  
  61. sendfile64_func* my_sendfile64_func = NULL;
  62. #endif
  63.  
  64. JNIEXPORT jlong JNICALL
  65. Java_sun_nio_ch_FileChannelImpl_initIDs(JNIEnv *env, jclass clazz)
  66. {
  67.     jlong pageSize = sysconf(_SC_PAGESIZE);
  68.     chan_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
  69.  
  70. #ifdef __solaris__
  71.     if (dlopen("/usr/lib/libsendfile.so.1", RTLD_GLOBAL | RTLD_LAZY) != NULL) {
  72.         my_sendfile_func = (sendfile_func*) dlsym(RTLD_DEFAULT, "sendfilev64");
  73.     }
  74. #endif
  75.  
  76. #ifdef __linux__
  77.     my_sendfile64_func = (sendfile64_func*) dlsym(RTLD_DEFAULT, "sendfile64");
  78. #endif
  79.  
  80.     return pageSize;
  81. }
  82.  
  83. static jlong
  84. handle(JNIEnv *env, jlong rv, char *msg)
  85. {
  86.     if (rv >= 0)
  87.         return rv;
  88.     if (errno == EINTR)
  89.         return IOS_INTERRUPTED;
  90.     JNU_ThrowIOExceptionWithLastError(env, msg);
  91.     return IOS_THROWN;
  92. }
  93.  
  94.  
  95. JNIEXPORT jlong JNICALL
  96. Java_sun_nio_ch_FileChannelImpl_map0(JNIEnv *env, jobject this,
  97.                                      jint prot, jlong off, jlong len)
  98. {
  99.     void *mapAddress = 0;
  100.     jobject fdo = (*env)->GetObjectField(env, this, chan_fd);
  101.     jint fd = fdval(env, fdo);
  102.     int protections = 0;
  103.     int flags = 0;
  104.  
  105.     if (prot == sun_nio_ch_FileChannelImpl_MAP_RO) {
  106.         protections = PROT_READ;
  107.         flags = MAP_SHARED;
  108.     } else if (prot == sun_nio_ch_FileChannelImpl_MAP_RW) {
  109.         protections = PROT_WRITE | PROT_READ;
  110.         flags = MAP_SHARED;
  111.     } else if (prot == sun_nio_ch_FileChannelImpl_MAP_PV) {
  112.         protections =  PROT_WRITE | PROT_READ;
  113.         flags = MAP_PRIVATE;
  114.     }
  115.  
  116.     mapAddress = mmap64(
  117.         0,                    /* Let OS decide location */
  118.         len,                  /* Number of bytes to map */
  119.         protections,          /* File permissions */
  120.         flags,                /* Changes are shared */
  121.         fd,                   /* File descriptor of mapped file */
  122.         off);                 /* Offset into file */
  123.  
  124.     if (mapAddress == MAP_FAILED) {
  125.         if (errno == ENOMEM) {
  126.             JNU_ThrowOutOfMemoryError(env, "Map failed");
  127.             return IOS_THROWN;
  128.         }
  129.         return handle(env, -1, "Map failed");
  130.     }
  131.  
  132.     return ((jlong) (unsigned long) mapAddress);
  133. }
  134.  
  135.  
  136. JNIEXPORT jint JNICALL
  137. Java_sun_nio_ch_FileChannelImpl_unmap0(JNIEnv *env, jobject this,
  138.                                        jlong address, jlong len)
  139. {
  140.     void *a = (void *)jlong_to_ptr(address);
  141.     return handle(env,
  142.                   munmap(a, (size_t)len),
  143.                   "Unmap failed");
  144. }
  145.  
  146.  
  147. JNIEXPORT jint JNICALL
  148. Java_sun_nio_ch_FileChannelImpl_truncate0(JNIEnv *env, jobject this,
  149.                                           jobject fdo, jlong size)
  150. {
  151.     return handle(env,
  152.                   ftruncate64(fdval(env, fdo), size),
  153.                   "Truncation failed");
  154. }
  155.  
  156.  
  157. JNIEXPORT jint JNICALL
  158. Java_sun_nio_ch_FileChannelImpl_force0(JNIEnv *env, jobject this,
  159.                                        jobject fdo, jboolean md)
  160. {
  161.     jint fd = fdval(env, fdo);
  162.     int result = 0;
  163.  
  164.     if (md == JNI_FALSE) {
  165.         result = fdatasync(fd);
  166.     } else {
  167.         result = fsync(fd);
  168.     }
  169.     return handle(env, result, "Force failed");
  170. }
  171.  
  172.  
  173. JNIEXPORT jlong JNICALL
  174. Java_sun_nio_ch_FileChannelImpl_position0(JNIEnv *env, jobject this,
  175.                                           jobject fdo, jlong offset)
  176. {
  177.     jint fd = fdval(env, fdo);
  178.     jlong result = 0;
  179.  
  180.     if (offset < 0) {
  181.         result = lseek64(fd, 0, SEEK_CUR);
  182.     } else {
  183.         result = lseek64(fd, offset, SEEK_SET);
  184.     }
  185.     return handle(env, result, "Position failed");
  186. }
  187.  
  188.  
  189. JNIEXPORT jlong JNICALL
  190. Java_sun_nio_ch_FileChannelImpl_size0(JNIEnv *env, jobject this, jobject fdo)
  191. {
  192.     struct stat64 fbuf;
  193.  
  194.     if (fstat64(fdval(env, fdo), &fbuf) < 0)
  195.         return handle(env, -1, "Size failed");
  196.     return fbuf.st_size;
  197. }
  198.  
  199.  
  200. JNIEXPORT void JNICALL
  201. Java_sun_nio_ch_FileChannelImpl_close0(JNIEnv *env, jobject this, jobject fdo)
  202. {
  203.     jint fd = fdval(env, fdo);
  204.     if (fd != -1) {
  205.         jlong result = close(fd);
  206.         if (result < 0) {
  207.             JNU_ThrowIOExceptionWithLastError(env, "Close failed");
  208.         }
  209.     }
  210. }
  211.  
  212. JNIEXPORT jlong JNICALL
  213. Java_sun_nio_ch_FileChannelImpl_transferTo0(JNIEnv *env, jobject this,
  214.                                             jint srcFD,
  215.                                             jlong position, jlong count,
  216.                                             jint dstFD)
  217. {
  218. #ifdef __linux__
  219.     jlong max = (jlong)java_lang_Integer_MAX_VALUE;
  220.     jlong n;
  221.  
  222.     if (my_sendfile64_func == NULL) {
  223.         off_t offset;
  224.         if (position > max)
  225.             return IOS_UNSUPPORTED_CASE;
  226.         if (count > max)
  227.             count = max;
  228.         offset = (off_t)position;
  229.         n = sendfile(dstFD, srcFD, &offset, (size_t)count);
  230.     } else {
  231.         off64_t offset = (off64_t)position;
  232.         n = (*my_sendfile64_func)(dstFD, srcFD, &offset, (size_t)count);
  233.     }
  234.     if (n < 0) {
  235.         if (errno == EAGAIN)
  236.             return IOS_UNAVAILABLE;
  237.         if ((errno == EINVAL) && ((ssize_t)count >= 0))
  238.             return IOS_UNSUPPORTED_CASE;
  239.         if (errno == EINTR) {
  240.             return IOS_INTERRUPTED;
  241.         }
  242.         JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
  243.         return IOS_THROWN;
  244.     }
  245.     return n;
  246. #endif
  247.  
  248. #ifdef __solaris__
  249.     if (my_sendfile_func == NULL) {
  250.         return IOS_UNSUPPORTED;
  251.     } else {
  252.         sendfilevec_t sfv;
  253.         size_t numBytes = 0;
  254.         jlong result;
  255.  
  256.         sfv.sfv_fd = srcFD;
  257.         sfv.sfv_flag = 0;
  258.         sfv.sfv_off = (off64_t)position;
  259.         sfv.sfv_len = count;
  260.  
  261.         result = (*my_sendfile_func)(dstFD, &sfv, 1, &numBytes);
  262.  
  263.         /* Solaris sendfilev() will return -1 even if some bytes have been
  264.          * transferred, so we check numBytes first.
  265.          */
  266.         if (numBytes > 0)
  267.             return numBytes;
  268.         if (result < 0) {
  269.             if (errno == EAGAIN)
  270.                 return IOS_UNAVAILABLE;
  271.             if ((errno == EINVAL) && ((ssize_t)count >= 0))
  272.                 return IOS_UNSUPPORTED_CASE;
  273.             if (errno == EINTR)
  274.                 return IOS_INTERRUPTED;
  275.             JNU_ThrowIOExceptionWithLastError(env, "Transfer failed");
  276.             return IOS_THROWN;
  277.         }
  278.         return result;
  279.     }
  280. #endif
  281. }
  282.  
  283. JNIEXPORT jint JNICALL
  284. Java_sun_nio_ch_FileChannelImpl_lock0(JNIEnv *env, jobject this, jobject fdo,
  285.                                       jboolean block, jlong pos, jlong size,
  286.                                       jboolean shared)
  287. {
  288.     jint fd = fdval(env, fdo);
  289.     jint lockResult = 0;
  290.     int cmd = 0;
  291.     struct flock64 fl;
  292.  
  293.     fl.l_whence = SEEK_SET;
  294.     fl.l_len = (off64_t)size;
  295.     fl.l_start = (off64_t)pos;
  296.     if (shared == JNI_TRUE) {
  297.         fl.l_type = F_RDLCK;
  298.     } else {
  299.         fl.l_type = F_WRLCK;
  300.     }
  301.     if (block == JNI_TRUE) {
  302.         cmd = F_SETLKW64;
  303.     } else {
  304.         cmd = F_SETLK64;
  305.     }
  306.     lockResult = fcntl(fd, cmd, &fl);
  307.     if (lockResult < 0) {
  308.         if ((cmd == F_SETLK64) && (errno == EAGAIN))
  309.             return sun_nio_ch_FileChannelImpl_NO_LOCK;
  310.         if (errno == EINTR)
  311.             return sun_nio_ch_FileChannelImpl_INTERRUPTED;
  312.         JNU_ThrowIOExceptionWithLastError(env, "Lock failed");
  313.     }
  314.     return 0;
  315. }
  316.  
  317.  
  318. JNIEXPORT void JNICALL
  319. Java_sun_nio_ch_FileChannelImpl_release0(JNIEnv *env, jobject this,
  320.                                          jobject fdo, jlong pos, jlong size)
  321. {
  322.     jint fd = fdval(env, fdo);
  323.     jint lockResult = 0;
  324.     struct flock64 fl;
  325.     int cmd = F_SETLK64;
  326.  
  327.     fl.l_whence = SEEK_SET;
  328.     fl.l_len = (off64_t)size;
  329.     fl.l_start = (off64_t)pos;
  330.     fl.l_type = F_UNLCK;
  331.     lockResult = fcntl(fd, cmd, &fl);
  332.     if (lockResult < 0) {
  333.         JNU_ThrowIOExceptionWithLastError(env, "Release failed");
  334.     }
  335. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement