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