1b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato/* 2b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Copyright (C) 2008 The Android Open Source Project 3b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 4b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Licensed under the Apache License, Version 2.0 (the "License"); 5b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * you may not use this file except in compliance with the License. 6b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * You may obtain a copy of the License at 7b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 8b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * http://www.apache.org/licenses/LICENSE-2.0 9b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * 10b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * Unless required by applicable law or agreed to in writing, software 11b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * distributed under the License is distributed on an "AS IS" BASIS, 12b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * See the License for the specific language governing permissions and 14b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato * limitations under the License. 15b1a7ffef3a0007b6991b8338460f6aac8cbb11e8Joe Onorato */ 169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 17ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project//#define LOG_NDEBUG 0 18ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include "JNIHelp.h" 209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <fcntl.h> 229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <sys/stat.h> 239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <stdio.h> 249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <utils/Log.h> 269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project#include <android_runtime/AndroidRuntime.h> 289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectnamespace android 309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 32ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectstatic struct parcel_file_descriptor_offsets_t 33ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project{ 34ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jfieldID mFileDescriptor; 35ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project} gParcelFileDescriptorOffsets; 369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 37ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackbornstatic jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFd(JNIEnv* env, 38ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn jobject clazz, jint origfd) 39ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn{ 40ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn int fd = dup(origfd); 41ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn if (fd < 0) { 42ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn jniThrowException(env, "java/io/IOException", strerror(errno)); 43ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn return NULL; 44ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn } 45939461300a0283a9f370a0425d4061d32b36f952Dianne Hackborn return jniCreateFileDescriptor(env, fd); 46ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn} 47ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn 48ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackbornstatic jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup(JNIEnv* env, 49ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn jobject clazz, jint fd) 50ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn{ 51939461300a0283a9f370a0425d4061d32b36f952Dianne Hackborn return jniCreateFileDescriptor(env, fd); 529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 54ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackbornstatic void android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env, 5523fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn jobject clazz, jobjectArray outFds) 5623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn{ 5723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn int fds[2]; 5823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn if (pipe(fds) < 0) { 59ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn int therr = errno; 60ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn jniThrowException(env, "java/io/IOException", strerror(therr)); 61ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn return; 6223fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 6323fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 6423fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn for (int i=0; i<2; i++) { 65a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes jobject fdObj = jniCreateFileDescriptor(env, fds[i]); 6623fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn env->SetObjectArrayElement(outFds, i, fdObj); 6723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn } 6823fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn} 6923fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn 70ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Projectstatic jint getFd(JNIEnv* env, jobject clazz) 71ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project{ 72ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor); 73ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (descriptor == NULL) return -1; 74a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes return jniGetFDFromFileDescriptor(env, descriptor); 75ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project} 76ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project 779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env, 789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject clazz) 799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 80ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jint fd = getFd(env, clazz); 81ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (fd < 0) { 82ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 83ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return -1; 84ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 85a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes 869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project struct stat st; 879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (fstat(fd, &st) != 0) { 889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 90a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes 919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) { 929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return st.st_size; 939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project } 94a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes 959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return -1; 969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env, 999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project jobject clazz, jlong pos) 1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 101ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jint fd = getFd(env, clazz); 102ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project if (fd < 0) { 103ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 104ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project return -1; 105ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project } 106a3804cf77f0edd93f6247a055cdafb856b117eecElliott Hughes 1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return lseek(fd, pos, SEEK_SET); 1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 110c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackbornstatic jlong android_os_ParcelFileDescriptor_getFdNative(JNIEnv* env, jobject clazz) 111c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn{ 112c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn jint fd = getFd(env, clazz); 113c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn if (fd < 0) { 114c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor"); 115c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn return -1; 116c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn } 117c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn 118c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn return fd; 119c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn} 120c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn 1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectstatic const JNINativeMethod gParcelFileDescriptorMethods[] = { 122ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn {"getFileDescriptorFromFd", "(I)Ljava/io/FileDescriptor;", 123ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFd}, 124ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn {"getFileDescriptorFromFdNoDup", "(I)Ljava/io/FileDescriptor;", 125ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup}, 126ea2117bdc03316a9292e2344c6fd157c85c13167Dianne Hackborn {"createPipeNative", "([Ljava/io/FileDescriptor;)V", 12723fdaf6fb62a9b5154b2508916a21c678462c5d0Dianne Hackborn (void*)android_os_ParcelFileDescriptor_createPipeNative}, 1289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"getStatSize", "()J", 1299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project (void*)android_os_ParcelFileDescriptor_getStatSize}, 1309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project {"seekTo", "(J)J", 131c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn (void*)android_os_ParcelFileDescriptor_seekTo}, 132c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn {"getFdNative", "()I", 133c9119f5034d36f548bbddd8f60291e24ab4e270bDianne Hackborn (void*)android_os_ParcelFileDescriptor_getFdNative} 1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}; 1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectconst char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor"; 1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectint register_android_os_ParcelFileDescriptor(JNIEnv* env) 1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project{ 1404390758f277645de6e81f6482d582473383cc917Elliott Hughes jclass clazz = env->FindClass(kParcelFileDescriptorPathName); 1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor"); 142ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project gParcelFileDescriptorOffsets.mFileDescriptor = env->GetFieldID(clazz, "mFileDescriptor", "Ljava/io/FileDescriptor;"); 143ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project LOG_FATAL_IF(gParcelFileDescriptorOffsets.mFileDescriptor == NULL, 144ba87e3e6c985e7175152993b5efcc7dd2f0e1c93The Android Open Source Project "Unable to find mFileDescriptor field in android.os.ParcelFileDescriptor"); 1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project return AndroidRuntime::registerNativeMethods( 1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project env, kParcelFileDescriptorPathName, 1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods)); 1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project 1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project} 152