1/* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18 19#include "JNIHelp.h" 20 21#include <fcntl.h> 22#include <sys/stat.h> 23#include <stdio.h> 24 25#include <utils/Log.h> 26 27#include <android_runtime/AndroidRuntime.h> 28 29namespace android 30{ 31 32static struct parcel_file_descriptor_offsets_t 33{ 34 jfieldID mFileDescriptor; 35} gParcelFileDescriptorOffsets; 36 37static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFd(JNIEnv* env, 38 jobject clazz, jint origfd) 39{ 40 int fd = dup(origfd); 41 if (fd < 0) { 42 jniThrowException(env, "java/io/IOException", strerror(errno)); 43 return NULL; 44 } 45 return jniCreateFileDescriptor(env, fd); 46} 47 48static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup(JNIEnv* env, 49 jobject clazz, jint fd) 50{ 51 return jniCreateFileDescriptor(env, fd); 52} 53 54static void android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env, 55 jobject clazz, jobjectArray outFds) 56{ 57 int fds[2]; 58 if (pipe(fds) < 0) { 59 int therr = errno; 60 jniThrowException(env, "java/io/IOException", strerror(therr)); 61 return; 62 } 63 64 for (int i=0; i<2; i++) { 65 jobject fdObj = jniCreateFileDescriptor(env, fds[i]); 66 env->SetObjectArrayElement(outFds, i, fdObj); 67 } 68} 69 70static jint getFd(JNIEnv* env, jobject clazz) 71{ 72 jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor); 73 if (descriptor == NULL) return -1; 74 return jniGetFDFromFileDescriptor(env, descriptor); 75} 76 77static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env, 78 jobject clazz) 79{ 80 jint fd = getFd(env, clazz); 81 if (fd < 0) { 82 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 83 return -1; 84 } 85 86 struct stat st; 87 if (fstat(fd, &st) != 0) { 88 return -1; 89 } 90 91 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 92 return st.st_size; 93 } 94 95 return -1; 96} 97 98static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env, 99 jobject clazz, jlong pos) 100{ 101 jint fd = getFd(env, clazz); 102 if (fd < 0) { 103 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 104 return -1; 105 } 106 107 return lseek(fd, pos, SEEK_SET); 108} 109 110static jlong android_os_ParcelFileDescriptor_getFdNative(JNIEnv* env, jobject clazz) 111{ 112 jint fd = getFd(env, clazz); 113 if (fd < 0) { 114 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 115 return -1; 116 } 117 118 return fd; 119} 120 121static const JNINativeMethod gParcelFileDescriptorMethods[] = { 122 {"getFileDescriptorFromFd", "(I)Ljava/io/FileDescriptor;", 123 (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFd}, 124 {"getFileDescriptorFromFdNoDup", "(I)Ljava/io/FileDescriptor;", 125 (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup}, 126 {"createPipeNative", "([Ljava/io/FileDescriptor;)V", 127 (void*)android_os_ParcelFileDescriptor_createPipeNative}, 128 {"getStatSize", "()J", 129 (void*)android_os_ParcelFileDescriptor_getStatSize}, 130 {"seekTo", "(J)J", 131 (void*)android_os_ParcelFileDescriptor_seekTo}, 132 {"getFdNative", "()I", 133 (void*)android_os_ParcelFileDescriptor_getFdNative} 134}; 135 136const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor"; 137 138int register_android_os_ParcelFileDescriptor(JNIEnv* env) 139{ 140 jclass clazz = env->FindClass(kParcelFileDescriptorPathName); 141 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 142 gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;"); 143 LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL, 144 "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor"); 145 146 return AndroidRuntime::registerNativeMethods( 147 env, kParcelFileDescriptorPathName, 148 gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods)); 149} 150 151} 152