blob: 99a2d049be879db88d717d6e2297d23fe9ab75c0 [file] [log] [blame]
Joe Onoratob1a7ffe2009-05-06 18:06:21 -07001/*
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 */
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080016
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070017//#define LOG_NDEBUG 0
18
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080019#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
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070032static struct parcel_file_descriptor_offsets_t
33{
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070034 jfieldID mFileDescriptor;
35} gParcelFileDescriptorOffsets;
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080036
Dianne Hackbornea2117bd2011-05-20 10:37:34 -070037static 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 }
Dianne Hackborn93946132011-05-23 14:08:12 -070045 return jniCreateFileDescriptor(env, fd);
Dianne Hackbornea2117bd2011-05-20 10:37:34 -070046}
47
48static jobject android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup(JNIEnv* env,
49 jobject clazz, jint fd)
50{
Dianne Hackborn93946132011-05-23 14:08:12 -070051 return jniCreateFileDescriptor(env, fd);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080052}
53
Dianne Hackbornea2117bd2011-05-20 10:37:34 -070054static void android_os_ParcelFileDescriptor_createPipeNative(JNIEnv* env,
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070055 jobject clazz, jobjectArray outFds)
56{
57 int fds[2];
58 if (pipe(fds) < 0) {
Dianne Hackbornea2117bd2011-05-20 10:37:34 -070059 int therr = errno;
60 jniThrowException(env, "java/io/IOException", strerror(therr));
61 return;
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070062 }
63
64 for (int i=0; i<2; i++) {
Elliott Hughesa3804cf2011-04-11 16:50:19 -070065 jobject fdObj = jniCreateFileDescriptor(env, fds[i]);
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070066 env->SetObjectArrayElement(outFds, i, fdObj);
67 }
Dianne Hackborn23fdaf62010-08-06 12:16:55 -070068}
69
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070070static jint getFd(JNIEnv* env, jobject clazz)
71{
72 jobject descriptor = env->GetObjectField(clazz, gParcelFileDescriptorOffsets.mFileDescriptor);
73 if (descriptor == NULL) return -1;
Elliott Hughesa3804cf2011-04-11 16:50:19 -070074 return jniGetFDFromFileDescriptor(env, descriptor);
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070075}
76
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080077static jlong android_os_ParcelFileDescriptor_getStatSize(JNIEnv* env,
78 jobject clazz)
79{
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -070080 jint fd = getFd(env, clazz);
81 if (fd < 0) {
82 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
83 return -1;
84 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -070085
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080086 struct stat st;
87 if (fstat(fd, &st) != 0) {
88 return -1;
89 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -070090
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080091 if (S_ISREG(st.st_mode) || S_ISLNK(st.st_mode)) {
92 return st.st_size;
93 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -070094
The Android Open Source Project9066cfe2009-03-03 19:31:44 -080095 return -1;
96}
97
98static jlong android_os_ParcelFileDescriptor_seekTo(JNIEnv* env,
99 jobject clazz, jlong pos)
100{
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700101 jint fd = getFd(env, clazz);
102 if (fd < 0) {
103 jniThrowException(env, "java/lang/IllegalArgumentException", "bad file descriptor");
104 return -1;
105 }
Elliott Hughesa3804cf2011-04-11 16:50:19 -0700106
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800107 return lseek(fd, pos, SEEK_SET);
108}
109
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800110static 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
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800121static const JNINativeMethod gParcelFileDescriptorMethods[] = {
Dianne Hackbornea2117bd2011-05-20 10:37:34 -0700122 {"getFileDescriptorFromFd", "(I)Ljava/io/FileDescriptor;",
123 (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFd},
124 {"getFileDescriptorFromFdNoDup", "(I)Ljava/io/FileDescriptor;",
125 (void*)android_os_ParcelFileDescriptor_getFileDescriptorFromFdNoDup},
Dianne Hackbornea2117bd2011-05-20 10:37:34 -0700126 {"createPipeNative", "([Ljava/io/FileDescriptor;)V",
Dianne Hackborn23fdaf62010-08-06 12:16:55 -0700127 (void*)android_os_ParcelFileDescriptor_createPipeNative},
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800128 {"getStatSize", "()J",
129 (void*)android_os_ParcelFileDescriptor_getStatSize},
130 {"seekTo", "(J)J",
Dianne Hackbornc9119f52011-02-28 18:03:26 -0800131 (void*)android_os_ParcelFileDescriptor_seekTo},
132 {"getFdNative", "()I",
133 (void*)android_os_ParcelFileDescriptor_getFdNative}
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800134};
135
136const char* const kParcelFileDescriptorPathName = "android/os/ParcelFileDescriptor";
137
138int register_android_os_ParcelFileDescriptor(JNIEnv* env)
139{
Elliott Hughes43907582011-04-12 14:25:23 -0700140 jclass clazz = env->FindClass(kParcelFileDescriptorPathName);
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800141 LOG_FATAL_IF(clazz == NULL, "Unable to find class android.os.ParcelFileDescriptor");
The Android Open Source Projectba87e3e2009-03-13 13:04:22 -0700142 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");
The Android Open Source Project9066cfe2009-03-03 19:31:44 -0800145
146 return AndroidRuntime::registerNativeMethods(
147 env, kParcelFileDescriptorPathName,
148 gParcelFileDescriptorMethods, NELEM(gParcelFileDescriptorMethods));
149}
150
151}