Path: blob/master/src/java.base/unix/native/libjava/io_util_md.c
41119 views
/*1* Copyright (c) 2001, 2021, 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*/24#include "jni.h"25#include "jni_util.h"26#include "jvm.h"27#include "io_util.h"28#include "io_util_md.h"29#include <string.h>30#include <unistd.h>3132#if defined(__linux__) || defined(_ALLBSD_SOURCE) || defined(_AIX)33#include <sys/ioctl.h>34#endif3536#if defined(__linux__)37#include <linux/fs.h>38#include <sys/stat.h>39#endif4041#ifdef MACOSX4243#include <CoreFoundation/CoreFoundation.h>4445__private_extern__46jstring newStringPlatform(JNIEnv *env, const char* str)47{48jstring rv = NULL;49CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);50if (csref == NULL) {51JNU_ThrowOutOfMemoryError(env, "native heap");52} else {53CFStringAppendCString(csref, str, kCFStringEncodingUTF8);54CFStringNormalize(csref, kCFStringNormalizationFormC);55int clen = CFStringGetLength(csref);56int ulen = (clen + 1) * 2; // utf16 + zero padding57char* chars = malloc(ulen);58if (chars == NULL) {59CFRelease(csref);60JNU_ThrowOutOfMemoryError(env, "native heap");61} else {62if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {63rv = (*env)->NewString(env, (jchar*)chars, clen);64}65free(chars);66CFRelease(csref);67}68}69return rv;70}71#endif7273FD74handleOpen(const char *path, int oflag, int mode) {75FD fd;76RESTARTABLE(open64(path, oflag, mode), fd);77if (fd != -1) {78struct stat64 buf64;79int result;80RESTARTABLE(fstat64(fd, &buf64), result);81if (result != -1) {82if (S_ISDIR(buf64.st_mode)) {83close(fd);84errno = EISDIR;85fd = -1;86}87} else {88close(fd);89fd = -1;90}91}92return fd;93}9495FD getFD(JNIEnv *env, jobject obj, jfieldID fid) {96jobject fdo = (*env)->GetObjectField(env, obj, fid);97if (fdo == NULL) {98return -1;99}100return (*env)->GetIntField(env, fdo, IO_fd_fdID);101}102103void104fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags)105{106WITH_PLATFORM_STRING(env, path, ps) {107FD fd;108109#if defined(__linux__) || defined(_ALLBSD_SOURCE)110/* Remove trailing slashes, since the kernel won't */111char *p = (char *)ps + strlen(ps) - 1;112while ((p > ps) && (*p == '/'))113*p-- = '\0';114#endif115fd = handleOpen(ps, flags, 0666);116if (fd != -1) {117jobject fdobj;118jboolean append;119fdobj = (*env)->GetObjectField(env, this, fid);120if (fdobj != NULL) {121// Set FD122(*env)->SetIntField(env, fdobj, IO_fd_fdID, fd);123append = (flags & O_APPEND) == 0 ? JNI_FALSE : JNI_TRUE;124(*env)->SetBooleanField(env, fdobj, IO_append_fdID, append);125}126} else {127throwFileNotFoundException(env, path);128}129} END_PLATFORM_STRING(env, ps);130}131132// Function to close the fd held by this FileDescriptor and set fd to -1.133void134fileDescriptorClose(JNIEnv *env, jobject this)135{136FD fd = (*env)->GetIntField(env, this, IO_fd_fdID);137if ((*env)->ExceptionOccurred(env)) {138return;139}140141if (fd == -1) {142return; // already closed and set to -1143}144145/* Set the fd to -1 before closing it so that the timing window146* of other threads using the wrong fd (closed but recycled fd,147* that gets re-opened with some other filename) is reduced.148* Practically the chance of its occurance is low, however, we are149* taking extra precaution over here.150*/151(*env)->SetIntField(env, this, IO_fd_fdID, -1);152if ((*env)->ExceptionOccurred(env)) {153return;154}155/*156* Don't close file descriptors 0, 1, or 2. If we close these stream157* then a subsequent file open or socket will use them. Instead we158* just redirect these file descriptors to /dev/null.159*/160if (fd >= STDIN_FILENO && fd <= STDERR_FILENO) {161int devnull = open("/dev/null", O_WRONLY);162if (devnull < 0) {163(*env)->SetIntField(env, this, IO_fd_fdID, fd);164JNU_ThrowIOExceptionWithLastError(env, "open /dev/null failed");165} else {166dup2(devnull, fd);167close(devnull);168}169} else {170int result;171#if defined(_AIX)172/* AIX allows close to be restarted after EINTR */173RESTARTABLE(close(fd), result);174#else175result = close(fd);176#endif177if (result == -1 && errno != EINTR) {178JNU_ThrowIOExceptionWithLastError(env, "close failed");179}180}181}182183ssize_t184handleRead(FD fd, void *buf, jint len)185{186ssize_t result;187RESTARTABLE(read(fd, buf, len), result);188return result;189}190191ssize_t192handleWrite(FD fd, const void *buf, jint len)193{194ssize_t result;195RESTARTABLE(write(fd, buf, len), result);196return result;197}198199jint200handleAvailable(FD fd, jlong *pbytes)201{202int mode;203struct stat64 buf64;204jlong size = -1, current = -1;205206int result;207RESTARTABLE(fstat64(fd, &buf64), result);208if (result != -1) {209mode = buf64.st_mode;210if (S_ISCHR(mode) || S_ISFIFO(mode) || S_ISSOCK(mode)) {211int n;212int result;213RESTARTABLE(ioctl(fd, FIONREAD, &n), result);214if (result >= 0) {215*pbytes = n;216return 1;217}218} else if (S_ISREG(mode)) {219size = buf64.st_size;220}221}222223if ((current = lseek64(fd, 0, SEEK_CUR)) == -1) {224return 0;225}226227if (size < current) {228if ((size = lseek64(fd, 0, SEEK_END)) == -1)229return 0;230else if (lseek64(fd, current, SEEK_SET) == -1)231return 0;232}233234*pbytes = size - current;235return 1;236}237238jint239handleSetLength(FD fd, jlong length)240{241int result;242RESTARTABLE(ftruncate64(fd, length), result);243return result;244}245246jlong247handleGetLength(FD fd)248{249struct stat64 sb;250int result;251RESTARTABLE(fstat64(fd, &sb), result);252if (result < 0) {253return -1;254}255#if defined(__linux__) && defined(BLKGETSIZE64)256if (S_ISBLK(sb.st_mode)) {257uint64_t size;258if(ioctl(fd, BLKGETSIZE64, &size) < 0) {259return -1;260}261return (jlong)size;262}263#endif264return sb.st_size;265}266267268