Path: blob/master/src/java.base/share/native/libjava/io_util.c
41149 views
/*1* Copyright (c) 1994, 2020, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation. Oracle designates this7* particular file as subject to the "Classpath" exception as provided8* by Oracle in the LICENSE file that accompanied this code.9*10* This code is distributed in the hope that it will be useful, but WITHOUT11* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or12* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License13* version 2 for more details (a copy is included in the LICENSE file that14* accompanied this code).15*16* You should have received a copy of the GNU General Public License version17* 2 along with this work; if not, write to the Free Software Foundation,18* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.19*20* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA21* or visit www.oracle.com if you need additional information or have any22* questions.23*/2425#include <stdlib.h>26#include <string.h>27#include <stddef.h>2829#include "jni.h"30#include "jni_util.h"31#include "jvm.h"32#include "io_util.h"33#include "io_util_md.h"3435/* IO helper functions */3637jint38readSingle(JNIEnv *env, jobject this, jfieldID fid) {39jint nread;40char ret;41FD fd = getFD(env, this, fid);42if (fd == -1) {43JNU_ThrowIOException(env, "Stream Closed");44return -1;45}46nread = IO_Read(fd, &ret, 1);47if (nread == 0) { /* EOF */48return -1;49} else if (nread == -1) { /* error */50JNU_ThrowIOExceptionWithLastError(env, "Read error");51}52return ret & 0xFF;53}5455/* The maximum size of a stack-allocated buffer.56*/57#define BUF_SIZE 81925859/*60* Returns true if the array slice defined by the given offset and length61* is out of bounds.62*/63static int64outOfBounds(JNIEnv *env, jint off, jint len, jbyteArray array) {65return ((off < 0) ||66(len < 0) ||67// We are very careful to avoid signed integer overflow,68// the result of which is undefined in C.69((*env)->GetArrayLength(env, array) - off < len));70}7172jint73readBytes(JNIEnv *env, jobject this, jbyteArray bytes,74jint off, jint len, jfieldID fid)75{76jint nread;77char stackBuf[BUF_SIZE];78char *buf = NULL;79FD fd;8081if (IS_NULL(bytes)) {82JNU_ThrowNullPointerException(env, NULL);83return -1;84}8586if (outOfBounds(env, off, len, bytes)) {87JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", NULL);88return -1;89}9091if (len == 0) {92return 0;93} else if (len > BUF_SIZE) {94buf = malloc(len);95if (buf == NULL) {96JNU_ThrowOutOfMemoryError(env, NULL);97return 0;98}99} else {100buf = stackBuf;101}102103fd = getFD(env, this, fid);104if (fd == -1) {105JNU_ThrowIOException(env, "Stream Closed");106nread = -1;107} else {108nread = IO_Read(fd, buf, len);109if (nread > 0) {110(*env)->SetByteArrayRegion(env, bytes, off, nread, (jbyte *)buf);111} else if (nread == -1) {112JNU_ThrowIOExceptionWithLastError(env, "Read error");113} else { /* EOF */114nread = -1;115}116}117118if (buf != stackBuf) {119free(buf);120}121return nread;122}123124void125writeSingle(JNIEnv *env, jobject this, jint byte, jboolean append, jfieldID fid) {126// Discard the 24 high-order bits of byte. See OutputStream#write(int)127char c = (char) byte;128jint n;129FD fd = getFD(env, this, fid);130if (fd == -1) {131JNU_ThrowIOException(env, "Stream Closed");132return;133}134if (append == JNI_TRUE) {135n = IO_Append(fd, &c, 1);136} else {137n = IO_Write(fd, &c, 1);138}139if (n == -1) {140JNU_ThrowIOExceptionWithLastError(env, "Write error");141}142}143144void145writeBytes(JNIEnv *env, jobject this, jbyteArray bytes,146jint off, jint len, jboolean append, jfieldID fid)147{148jint n;149char stackBuf[BUF_SIZE];150char *buf = NULL;151FD fd;152153if (IS_NULL(bytes)) {154JNU_ThrowNullPointerException(env, NULL);155return;156}157158if (outOfBounds(env, off, len, bytes)) {159JNU_ThrowByName(env, "java/lang/IndexOutOfBoundsException", NULL);160return;161}162163if (len == 0) {164return;165} else if (len > BUF_SIZE) {166buf = malloc(len);167if (buf == NULL) {168JNU_ThrowOutOfMemoryError(env, NULL);169return;170}171} else {172buf = stackBuf;173}174175(*env)->GetByteArrayRegion(env, bytes, off, len, (jbyte *)buf);176177if (!(*env)->ExceptionOccurred(env)) {178off = 0;179while (len > 0) {180fd = getFD(env, this, fid);181if (fd == -1) {182JNU_ThrowIOException(env, "Stream Closed");183break;184}185if (append == JNI_TRUE) {186n = IO_Append(fd, buf+off, len);187} else {188n = IO_Write(fd, buf+off, len);189}190if (n == -1) {191JNU_ThrowIOExceptionWithLastError(env, "Write error");192break;193}194off += n;195len -= n;196}197}198if (buf != stackBuf) {199free(buf);200}201}202203void204throwFileNotFoundException(JNIEnv *env, jstring path)205{206char buf[256];207size_t n;208jobject x;209jstring why = NULL;210211n = getLastErrorString(buf, sizeof(buf));212if (n > 0) {213why = JNU_NewStringPlatform(env, buf);214CHECK_NULL(why);215}216x = JNU_NewObjectByName(env,217"java/io/FileNotFoundException",218"(Ljava/lang/String;Ljava/lang/String;)V",219path, why);220if (x != NULL) {221(*env)->Throw(env, x);222}223}224225226