151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*
251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 1997, 2007, Oracle and/or its affiliates. All rights reserved.
351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it
651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as
751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation.  Oracle designates this
851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided
951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code.
1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT
1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that
1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code).
1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version
1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation,
1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski *
2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any
2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions.
2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
263d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include <sys/ioctl.h>
273d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include <sys/types.h>
283d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include <sys/stat.h>
293d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include <fcntl.h>
303d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include <unistd.h>
3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jni.h"
3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jni_util.h"
3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jlong.h"
3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "io_util.h"
353d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#include "io_util_md.h"
3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "jvm.h"
3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <fcntl.h>
4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include <limits.h>
4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski#include "io_util_md.h"
44cab01ac294bb8ded259851673baa4c6ca226f828Steven Moreland#include <nativehelper/JNIHelp.h>
453d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski
463d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski#define NATIVE_METHOD(className, functionName, signature) \
473d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski{ #functionName, signature, (void*)(className ## _ ## functionName) }
4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*******************************************************************/
5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*  BEGIN JNI ********* BEGIN JNI *********** BEGIN JNI ************/
5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/*******************************************************************/
5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskijfieldID fis_fd; /* id for jobject 'fd' in java.io.FileInputStream */
5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/**************************************************************
562798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak * Input stream
5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */
5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
602798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniakstatic void FileInputStream_initIDs(JNIEnv *env) {
612798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak    jclass clazz = (*env)->FindClass(env, "java/io/FileInputStream");
622798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak    fis_fd = (*env)->GetFieldID(env, clazz, "fd", "Ljava/io/FileDescriptor;");
632798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak}
6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiJNIEXPORT void JNICALL
664c36dc077823b9fe42a30e09672613d154292628Przemyslaw SzczepaniakFileInputStream_open0(JNIEnv *env, jobject this, jstring path) {
6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    fileOpen(env, this, path, fis_fd, O_RDONLY);
6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiJNIEXPORT jlong JNICALL
71d86d266774c4d78e187426a0b26d281802712d58Przemyslaw SzczepaniakFileInputStream_skip0(JNIEnv *env, jobject this, jlong toSkip) {
7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jlong cur = jlong_zero;
7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jlong end = jlong_zero;
7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    FD fd = GET_FD(this, fis_fd);
7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (fd == -1) {
7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowIOException (env, "Stream Closed");
7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 0;
7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if ((cur = IO_Lseek(fd, (jlong)0, (jint)SEEK_CUR)) == -1) {
80d86d266774c4d78e187426a0b26d281802712d58Przemyslaw Szczepaniak      if (errno == ESPIPE) {
81d86d266774c4d78e187426a0b26d281802712d58Przemyslaw Szczepaniak        JNU_ThrowByName(env, "java/io/FileInputStream$UseManualSkipException", NULL);
82d86d266774c4d78e187426a0b26d281802712d58Przemyslaw Szczepaniak      } else {
8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowIOExceptionWithLastError(env, "Seek error");
84d86d266774c4d78e187426a0b26d281802712d58Przemyslaw Szczepaniak      }
8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    } else if ((end = IO_Lseek(fd, toSkip, (jint)SEEK_CUR)) == -1) {
8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowIOExceptionWithLastError(env, "Seek error");
8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return (end - cur);
8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski
913d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebskistatic int available(int fd, jlong *bytes) {
923ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  int n;
933ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // Unlike the original OpenJdk implementation, we use FIONREAD for all file
943ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // types. For regular files, this is specified to return the difference
953ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // between the current position and the file size. Note that this can be
963ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // negative if we're positioned past the end of the file. We must return 0
973ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // in that case.
983ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  if (ioctl(fd, FIONREAD, &n) != -1) {
993ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath    if (n < 0) {
1003ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath      n = 0;
1013d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski    }
1023ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath    *bytes = n;
1033d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski    return 1;
1043ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  }
1053ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath
1063ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // FIONREAD is specified to return ENOTTY when fd refers to a file
1073ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // type for which this ioctl isn't implemented.
1083ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  if (errno == ENOTTY) {
1093ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath    *bytes = 0;
1103ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath    return 1;
1113ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  }
1123ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath
1133ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  // Raise an exception for all other error types.
1143ef077835b6f7af06814343aab0b84f41997ad3fNarayan Kamath  return 0;
1153d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski}
1163d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski
11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr JastrzebskiJNIEXPORT jint JNICALL
11850164c3602af46021e434ff5047352299a36e0f0Yi KongFileInputStream_available0(JNIEnv *env, jobject this) {
11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    jlong ret;
12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    FD fd = GET_FD(this, fis_fd);
12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    if (fd == -1) {
12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        JNU_ThrowIOException (env, "Stream Closed");
12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return 0;
12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
1253d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski    if (available(fd, &ret)) {
12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        if (ret > INT_MAX) {
12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski            ret = (jlong) INT_MAX;
12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        }
12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski        return jlong_to_jint(ret);
13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    }
13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    JNU_ThrowIOExceptionWithLastError(env, NULL);
13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski    return 0;
13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski}
1343d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski
1353d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebskistatic JNINativeMethod gMethods[] = {
1364c36dc077823b9fe42a30e09672613d154292628Przemyslaw Szczepaniak  NATIVE_METHOD(FileInputStream, open0, "(Ljava/lang/String;)V"),
137d86d266774c4d78e187426a0b26d281802712d58Przemyslaw Szczepaniak  NATIVE_METHOD(FileInputStream, skip0, "(J)J"),
13850164c3602af46021e434ff5047352299a36e0f0Yi Kong  NATIVE_METHOD(FileInputStream, available0, "()I"),
1393d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski};
1403d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski
1413d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebskivoid register_java_io_FileInputStream(JNIEnv* env) {
1422798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak    jniRegisterNativeMethods(env, "java/io/FileInputStream", gMethods, NELEM(gMethods));
1432798490baa8ee586e38bdd09707f4fb18ef0d023Przemyslaw Szczepaniak    FileInputStream_initIDs(env);
1443d43823e17818b3c5f45831f830884917b181454Piotr Jastrzebski}
145