libcore_io_Linux.cpp revision c7fa20701d5e9398c38f4615ed293acfce1c0cf6
1ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes/* 2ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Copyright (C) 2011 The Android Open Source Project 3ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * 4ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 5ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * you may not use this file except in compliance with the License. 6ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * You may obtain a copy of the License at 7ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * 8ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 9ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * 10ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * Unless required by applicable law or agreed to in writing, software 11ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 12ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * See the License for the specific language governing permissions and 14ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes * limitations under the License. 15ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes */ 16ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes 17ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#define LOG_TAG "Posix" 18ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes 19ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "JNIHelp.h" 20ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "JniConstants.h" 21ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include "JniException.h" 220f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes#include "ScopedPrimitiveArray.h" 23ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include "ScopedUtfChars.h" 2459fa7163774d6930a174bc038414a4b780581957Elliott Hughes#include "StaticAssert.h" 25ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include "toStringArray.h" 26ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes 27ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes#include <errno.h> 280ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <fcntl.h> 29ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes#include <stdlib.h> 307e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes#include <sys/mman.h> 3147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes#include <sys/stat.h> 320ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <sys/types.h> 3359fa7163774d6930a174bc038414a4b780581957Elliott Hughes#include <sys/vfs.h> // Bionic doesn't have <sys/statvfs.h> 340ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes#include <unistd.h> 35ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes 367e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic void throwErrnoException(JNIEnv* env, const char* name) { 377e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes int errnum = errno; 387e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes 39ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes jthrowable cause = NULL; 40ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes if (env->ExceptionCheck()) { 41ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes cause = env->ExceptionOccurred(); 42ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes env->ExceptionClear(); 43ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } 44ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 45f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes ScopedLocalRef<jstring> javaName(env, env->NewStringUTF(name)); 46f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes if (javaName.get() == NULL) { 47f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes // Not really much we can do here. We're probably dead in the water, 48f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes // but let's try to stumble on... 49f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes env->ExceptionClear(); 50f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes } 51f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes 52ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes jobject exception; 53ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes if (cause != NULL) { 54f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes static jmethodID ctor = env->GetMethodID(JniConstants::errnoExceptionClass, "<init>", 55f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes "(Ljava/lang/String;ILjava/lang/Throwable;)V"); 56f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes exception = env->NewObject(JniConstants::errnoExceptionClass, ctor, 57f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes javaName.get(), errnum, cause); 58ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } else { 59f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes static jmethodID ctor = env->GetMethodID(JniConstants::errnoExceptionClass, "<init>", 60f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes "(Ljava/lang/String;I)V"); 61f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes exception = env->NewObject(JniConstants::errnoExceptionClass, ctor, javaName.get(), errnum); 62ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } 63ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes env->Throw(reinterpret_cast<jthrowable>(exception)); 64dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes} 65dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes 66dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughestemplate <typename rc_t> 677e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) { 68dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes if (rc == rc_t(-1)) { 697e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, name); 70dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes } 71dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes return rc; 7247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes} 7347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes 7447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject makeStructStat(JNIEnv* env, const struct stat& sb) { 7547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes static jmethodID ctor = env->GetMethodID(JniConstants::structStatClass, "<init>", 7647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes "(JJIJIIJJJJJJJ)V"); 7747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return env->NewObject(JniConstants::structStatClass, ctor, 7859fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.st_dev), static_cast<jlong>(sb.st_ino), 7959fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jint>(sb.st_mode), static_cast<jlong>(sb.st_nlink), 8059fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jint>(sb.st_uid), static_cast<jint>(sb.st_gid), 8159fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.st_rdev), static_cast<jlong>(sb.st_size), 8259fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.st_atime), static_cast<jlong>(sb.st_mtime), 8359fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.st_ctime), static_cast<jlong>(sb.st_blksize), 8459fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.st_blocks)); 8559fa7163774d6930a174bc038414a4b780581957Elliott Hughes} 8659fa7163774d6930a174bc038414a4b780581957Elliott Hughes 8759fa7163774d6930a174bc038414a4b780581957Elliott Hughesstatic jobject makeStructStatFs(JNIEnv* env, const struct statfs& sb) { 8859fa7163774d6930a174bc038414a4b780581957Elliott Hughes STATIC_ASSERT(sizeof(sb.f_bavail) == sizeof(jlong), statfs_not_64_bit); 8959fa7163774d6930a174bc038414a4b780581957Elliott Hughes STATIC_ASSERT(sizeof(sb.f_bfree) == sizeof(jlong), statfs_not_64_bit); 9059fa7163774d6930a174bc038414a4b780581957Elliott Hughes STATIC_ASSERT(sizeof(sb.f_blocks) == sizeof(jlong), statfs_not_64_bit); 9159fa7163774d6930a174bc038414a4b780581957Elliott Hughes 9259fa7163774d6930a174bc038414a4b780581957Elliott Hughes static jmethodID ctor = env->GetMethodID(JniConstants::structStatFsClass, "<init>", 9359fa7163774d6930a174bc038414a4b780581957Elliott Hughes "(JJJJJJJJ)V"); 9459fa7163774d6930a174bc038414a4b780581957Elliott Hughes return env->NewObject(JniConstants::structStatFsClass, ctor, static_cast<jlong>(sb.f_bsize), 9559fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.f_blocks), static_cast<jlong>(sb.f_bfree), 9659fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.f_bavail), static_cast<jlong>(sb.f_files), 9759fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.f_ffree), static_cast<jlong>(sb.f_namelen), 9859fa7163774d6930a174bc038414a4b780581957Elliott Hughes static_cast<jlong>(sb.f_frsize)); 9947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes} 10047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes 10147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject doStat(JNIEnv* env, jstring javaPath, bool isLstat) { 10247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes ScopedUtfChars path(env, javaPath); 10347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes if (path.c_str() == NULL) { 10447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return NULL; 10547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 10647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes struct stat sb; 10747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes int rc = isLstat ? TEMP_FAILURE_RETRY(lstat(path.c_str(), &sb)) 10847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes : TEMP_FAILURE_RETRY(stat(path.c_str(), &sb)); 109dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes if (rc == -1) { 1107e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, isLstat ? "lstat" : "stat"); 11147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return NULL; 11247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 11347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return makeStructStat(env, sb); 114ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes} 115ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 116ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jboolean Posix_access(JNIEnv* env, jobject, jstring javaPath, jint mode) { 117ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes ScopedUtfChars path(env, javaPath); 118ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes if (path.c_str() == NULL) { 119ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes return JNI_FALSE; 120ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes } 12147cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes int rc = TEMP_FAILURE_RETRY(access(path.c_str(), mode)); 122dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes if (rc == -1) { 1237e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, "access"); 124dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes } 125ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes return (rc == 0); 126ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes} 127ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 128b7190190e0ef8de883c952efb319ce7748831faaElliott Hughesstatic void Posix_chmod(JNIEnv* env, jobject, jstring javaPath, jint mode) { 129b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes ScopedUtfChars path(env, javaPath); 130b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes if (path.c_str() == NULL) { 131b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes return; 132b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes } 133b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes throwIfMinusOne(env, "chmod", TEMP_FAILURE_RETRY(chmod(path.c_str(), mode))); 134b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes} 135b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes 136ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jobjectArray Posix_environ(JNIEnv* env, jobject) { 137ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes extern char** environ; // Standard, but not in any header file. 138ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes return toStringArray(env, environ); 139ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes} 140ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 14152724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesstatic void Posix_fdatasync(JNIEnv* env, jobject, jobject javaFd) { 14252724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 1437e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwIfMinusOne(env, "fdatasync", TEMP_FAILURE_RETRY(fdatasync(fd))); 14452724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes} 14552724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes 14647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_fstat(JNIEnv* env, jobject, jobject javaFd) { 14747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 14847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes struct stat sb; 14947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes int rc = TEMP_FAILURE_RETRY(fstat(fd, &sb)); 150dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes if (rc == -1) { 1517e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, "fstat"); 15247cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return NULL; 15347cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes } 15447cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return makeStructStat(env, sb); 15547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes} 15647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes 15759fa7163774d6930a174bc038414a4b780581957Elliott Hughesstatic jobject Posix_fstatfs(JNIEnv* env, jobject, jobject javaFd) { 15859fa7163774d6930a174bc038414a4b780581957Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 15959fa7163774d6930a174bc038414a4b780581957Elliott Hughes struct statfs sb; 16059fa7163774d6930a174bc038414a4b780581957Elliott Hughes int rc = TEMP_FAILURE_RETRY(fstatfs(fd, &sb)); 16159fa7163774d6930a174bc038414a4b780581957Elliott Hughes if (rc == -1) { 16259fa7163774d6930a174bc038414a4b780581957Elliott Hughes throwErrnoException(env, "fstatfs"); 16359fa7163774d6930a174bc038414a4b780581957Elliott Hughes return NULL; 16459fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 16559fa7163774d6930a174bc038414a4b780581957Elliott Hughes return makeStructStatFs(env, sb); 16659fa7163774d6930a174bc038414a4b780581957Elliott Hughes} 16759fa7163774d6930a174bc038414a4b780581957Elliott Hughes 16852724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughesstatic void Posix_fsync(JNIEnv* env, jobject, jobject javaFd) { 16952724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 1707e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwIfMinusOne(env, "fsync", TEMP_FAILURE_RETRY(fsync(fd))); 171f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes} 172f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes 173f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughesstatic void Posix_ftruncate(JNIEnv* env, jobject, jobject javaFd, jlong length) { 174f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 1757e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwIfMinusOne(env, "ftruncate", TEMP_FAILURE_RETRY(ftruncate64(fd, length))); 17652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes} 17752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes 178ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughesstatic jstring Posix_getenv(JNIEnv* env, jobject, jstring javaName) { 179ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes ScopedUtfChars name(env, javaName); 180ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes if (name.c_str() == NULL) { 181ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes return NULL; 182ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes } 183ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes return env->NewStringUTF(getenv(name.c_str())); 184ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes} 185ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes 1869a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughesstatic jboolean Posix_isatty(JNIEnv* env, jobject, jobject javaFd) { 1879a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 1889a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes return TEMP_FAILURE_RETRY(isatty(fd)) == 0; 1899a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes} 1909a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes 191dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughesstatic jlong Posix_lseek(JNIEnv* env, jobject, jobject javaFd, jlong offset, jint whence) { 192dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 1937e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek64(fd, offset, whence))); 194dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes} 195dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes 19647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_lstat(JNIEnv* env, jobject, jstring javaPath) { 19747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return doStat(env, javaPath, true); 19847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes} 19947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes 2000f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughesstatic void Posix_mincore(JNIEnv* env, jobject, jlong address, jlong byteCount, jbyteArray javaVector) { 2010f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes ScopedByteArrayRW vector(env, javaVector); 2020f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes if (vector.get() == NULL) { 2030f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes return; 2040f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes } 2050f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2060f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes unsigned char* vec = reinterpret_cast<unsigned char*>(vector.get()); 2070f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes throwIfMinusOne(env, "mincore", TEMP_FAILURE_RETRY(mincore(ptr, byteCount, vec))); 2080f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes} 2090f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes 210c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughesstatic void Posix_mkdir(JNIEnv* env, jobject, jstring javaPath, jint mode) { 211c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes ScopedUtfChars path(env, javaPath); 212c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes if (path.c_str() == NULL) { 213c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes return; 214c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes } 215c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes throwIfMinusOne(env, "mkdir", TEMP_FAILURE_RETRY(mkdir(path.c_str(), mode))); 216c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes} 217c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes 2187e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughesstatic void Posix_mlock(JNIEnv* env, jobject, jlong address, jlong byteCount) { 2197e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2207e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes throwIfMinusOne(env, "mlock", TEMP_FAILURE_RETRY(mlock(ptr, byteCount))); 2217e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes} 2227e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes 2237e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic jlong Posix_mmap(JNIEnv* env, jobject, jlong address, jlong byteCount, jint prot, jint flags, jobject javaFd, jlong offset) { 2247e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes int fd = jniGetFDFromFileDescriptor(env, javaFd); 2257e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes void* suggestedPtr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2267e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes void* ptr = mmap(suggestedPtr, byteCount, prot, flags, fd, offset); 2277e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes if (ptr == MAP_FAILED) { 2287e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, "mmap"); 2297e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes } 2307e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes return static_cast<jlong>(reinterpret_cast<uintptr_t>(ptr)); 2317e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes} 2327e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes 2337e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic void Posix_msync(JNIEnv* env, jobject, jlong address, jlong byteCount, jint flags) { 2347e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2357e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwIfMinusOne(env, "msync", TEMP_FAILURE_RETRY(msync(ptr, byteCount, flags))); 2367e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes} 2377e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes 2387e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughesstatic void Posix_munlock(JNIEnv* env, jobject, jlong address, jlong byteCount) { 2397e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2407e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes throwIfMinusOne(env, "munlock", TEMP_FAILURE_RETRY(munlock(ptr, byteCount))); 2417e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes} 2427e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes 2437e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughesstatic void Posix_munmap(JNIEnv* env, jobject, jlong address, jlong byteCount) { 2447e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes void* ptr = reinterpret_cast<void*>(static_cast<uintptr_t>(address)); 2457e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwIfMinusOne(env, "munmap", TEMP_FAILURE_RETRY(munmap(ptr, byteCount))); 2467e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes} 2477e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes 2480ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughesstatic jobject Posix_open(JNIEnv* env, jobject, jstring javaPath, jint flags, jint mode) { 2490ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes ScopedUtfChars path(env, javaPath); 2500ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes if (path.c_str() == NULL) { 2510ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes return NULL; 2520ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes } 2530ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes int fd = throwIfMinusOne(env, "open", TEMP_FAILURE_RETRY(open(path.c_str(), flags, mode))); 2540ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes return fd != -1 ? jniCreateFileDescriptor(env, fd) : NULL; 2550ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes} 2560ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes 257c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughesstatic void Posix_remove(JNIEnv* env, jobject, jstring javaPath) { 258c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes ScopedUtfChars path(env, javaPath); 259c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes if (path.c_str() == NULL) { 260c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes return; 261c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes } 262c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes throwIfMinusOne(env, "remove", TEMP_FAILURE_RETRY(remove(path.c_str()))); 263c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes} 264c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes 265a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughesstatic void Posix_rename(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { 266a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes ScopedUtfChars oldPath(env, javaOldPath); 267a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes if (oldPath.c_str() == NULL) { 268a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes return; 269a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes } 270a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes ScopedUtfChars newPath(env, javaNewPath); 271a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes if (newPath.c_str() == NULL) { 272a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes return; 273a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes } 274a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes throwIfMinusOne(env, "rename", TEMP_FAILURE_RETRY(rename(oldPath.c_str(), newPath.c_str()))); 275a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes} 276a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes 27747cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughesstatic jobject Posix_stat(JNIEnv* env, jobject, jstring javaPath) { 27847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes return doStat(env, javaPath, false); 27947cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes} 28047cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes 28159fa7163774d6930a174bc038414a4b780581957Elliott Hughesstatic jobject Posix_statfs(JNIEnv* env, jstring javaPath) { 28259fa7163774d6930a174bc038414a4b780581957Elliott Hughes ScopedUtfChars path(env, javaPath); 28359fa7163774d6930a174bc038414a4b780581957Elliott Hughes if (path.c_str() == NULL) { 28459fa7163774d6930a174bc038414a4b780581957Elliott Hughes return NULL; 28559fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 28659fa7163774d6930a174bc038414a4b780581957Elliott Hughes struct statfs sb; 28759fa7163774d6930a174bc038414a4b780581957Elliott Hughes int rc = TEMP_FAILURE_RETRY(statfs(path.c_str(), &sb)); 28859fa7163774d6930a174bc038414a4b780581957Elliott Hughes if (rc == -1) { 28959fa7163774d6930a174bc038414a4b780581957Elliott Hughes throwErrnoException(env, "statfs"); 29059fa7163774d6930a174bc038414a4b780581957Elliott Hughes return NULL; 29159fa7163774d6930a174bc038414a4b780581957Elliott Hughes } 29259fa7163774d6930a174bc038414a4b780581957Elliott Hughes return makeStructStatFs(env, sb); 29359fa7163774d6930a174bc038414a4b780581957Elliott Hughes} 29459fa7163774d6930a174bc038414a4b780581957Elliott Hughes 295ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughesstatic jstring Posix_strerror(JNIEnv* env, jobject, jint errnum) { 29652724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes char buffer[BUFSIZ]; 297ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes const char* message = jniStrError(errnum, buffer, sizeof(buffer)); 298ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes return env->NewStringUTF(message); 299ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes} 300ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes 301a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughesstatic void Posix_symlink(JNIEnv* env, jobject, jstring javaOldPath, jstring javaNewPath) { 302a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes ScopedUtfChars oldPath(env, javaOldPath); 303a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes if (oldPath.c_str() == NULL) { 304a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes return; 305a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes } 306a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes ScopedUtfChars newPath(env, javaNewPath); 307a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes if (newPath.c_str() == NULL) { 308a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes return; 309a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes } 310a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes throwIfMinusOne(env, "symlink", TEMP_FAILURE_RETRY(symlink(oldPath.c_str(), newPath.c_str()))); 311a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes} 312a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes 3136fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughesstatic jlong Posix_sysconf(JNIEnv* env, jobject, jint name) { 3146fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes // Since -1 is a valid result from sysconf(3), detecting failure is a little more awkward. 3156fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes errno = 0; 3166fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes long result = sysconf(name); 3176fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes if (result == -1L && errno == EINVAL) { 3187e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes throwErrnoException(env, "sysconf"); 3196fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes } 3206fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes return result; 3216fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes} 3226fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes 323ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughesstatic JNINativeMethod gMethods[] = { 324ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes NATIVE_METHOD(Posix, access, "(Ljava/lang/String;I)Z"), 325b7190190e0ef8de883c952efb319ce7748831faaElliott Hughes NATIVE_METHOD(Posix, chmod, "(Ljava/lang/String;I)V"), 326ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes NATIVE_METHOD(Posix, environ, "()[Ljava/lang/String;"), 32752724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes NATIVE_METHOD(Posix, fdatasync, "(Ljava/io/FileDescriptor;)V"), 32847cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes NATIVE_METHOD(Posix, fstat, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStat;"), 32959fa7163774d6930a174bc038414a4b780581957Elliott Hughes NATIVE_METHOD(Posix, fstatfs, "(Ljava/io/FileDescriptor;)Llibcore/io/StructStatFs;"), 33052724d3ebd4ccaaa4b9f5576e329d4272cde8ea9Elliott Hughes NATIVE_METHOD(Posix, fsync, "(Ljava/io/FileDescriptor;)V"), 331f5333fd2094bdac4d6506177b1964b79afa64d77Elliott Hughes NATIVE_METHOD(Posix, ftruncate, "(Ljava/io/FileDescriptor;J)V"), 332ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes NATIVE_METHOD(Posix, getenv, "(Ljava/lang/String;)Ljava/lang/String;"), 3339a3f363523000704205df288f8b6f2f48c0d8563Elliott Hughes NATIVE_METHOD(Posix, isatty, "(Ljava/io/FileDescriptor;)Z"), 334dedaccdfa07c370a58cba08b096133ad9eec0ec3Elliott Hughes NATIVE_METHOD(Posix, lseek, "(Ljava/io/FileDescriptor;JI)J"), 33547cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes NATIVE_METHOD(Posix, lstat, "(Ljava/lang/String;)Llibcore/io/StructStat;"), 3360f746ff511162add42eeabaf14ba70ace874c6f4Elliott Hughes NATIVE_METHOD(Posix, mincore, "(JJ[B)V"), 337c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes NATIVE_METHOD(Posix, mkdir, "(Ljava/lang/String;I)V"), 3387e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes NATIVE_METHOD(Posix, mlock, "(JJ)V"), 3397e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes NATIVE_METHOD(Posix, mmap, "(JJIILjava/io/FileDescriptor;J)J"), 3407e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes NATIVE_METHOD(Posix, msync, "(JJI)V"), 3417e13c0f05ac9e7c55682d10e953dd4cbd5e6107cElliott Hughes NATIVE_METHOD(Posix, munlock, "(JJ)V"), 3427e25eff38a191d9c19e45093f4fde5102fb09d78Elliott Hughes NATIVE_METHOD(Posix, munmap, "(JJ)V"), 3430ac77ac8e915bff1a863e371f9b363033f9cf759Elliott Hughes NATIVE_METHOD(Posix, open, "(Ljava/lang/String;II)Ljava/io/FileDescriptor;"), 344c7fa20701d5e9398c38f4615ed293acfce1c0cf6Elliott Hughes NATIVE_METHOD(Posix, remove, "(Ljava/lang/String;)V"), 345a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes NATIVE_METHOD(Posix, rename, "(Ljava/lang/String;Ljava/lang/String;)V"), 34647cb338d43f75dd998b29caaaa9446c5705217d1Elliott Hughes NATIVE_METHOD(Posix, stat, "(Ljava/lang/String;)Llibcore/io/StructStat;"), 34759fa7163774d6930a174bc038414a4b780581957Elliott Hughes NATIVE_METHOD(Posix, statfs, "(Ljava/lang/String;)Llibcore/io/StructStatFs;"), 348ddfdbb9d172fe9b72e08e8d7deab0aa3b8acf044Elliott Hughes NATIVE_METHOD(Posix, strerror, "(I)Ljava/lang/String;"), 349a20cc6fca30d18e05db67ceeb0403b7b58ffd364Elliott Hughes NATIVE_METHOD(Posix, symlink, "(Ljava/lang/String;Ljava/lang/String;)V"), 3506fc1a0e1e68dc2e0d12341548e58fa7f1c5dafc4Elliott Hughes NATIVE_METHOD(Posix, sysconf, "(I)J"), 351ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes}; 352ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughesint register_libcore_io_Posix(JNIEnv* env) { 353ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes return jniRegisterNativeMethods(env, "libcore/io/Posix", gMethods, NELEM(gMethods)); 354ec617e2cb4a374f0fd8fbda4a633214cf23a59a9Elliott Hughes} 355