1 /*
2 * Copyright (C) 2024 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 #include <fcntl.h>
18 #include <sys/stat.h>
19 #include <string.h>
20 #include <unistd.h>
21 #include <nativehelper/JNIHelp.h>
22 #include "jni.h"
23 #include "utils/Log.h"
24 #include "utils/misc.h"
25
26 // Defined in ravenwood_os_constants.cpp
27 void register_android_system_OsConstants(JNIEnv* env);
28
29 // ---- Exception related ----
30
throwErrnoException(JNIEnv * env,const char * functionName)31 static void throwErrnoException(JNIEnv* env, const char* functionName) {
32 int error = errno;
33 jniThrowErrnoException(env, functionName, error);
34 }
35
36 template <typename rc_t>
throwIfMinusOne(JNIEnv * env,const char * name,rc_t rc)37 static rc_t throwIfMinusOne(JNIEnv* env, const char* name, rc_t rc) {
38 if (rc == rc_t(-1)) {
39 throwErrnoException(env, name);
40 }
41 return rc;
42 }
43
44 // ---- JNI methods ----
45
46 typedef void (*FreeFunction)(void*);
47
nApplyFreeFunction(JNIEnv *,jclass,jlong freeFunction,jlong ptr)48 static void nApplyFreeFunction(JNIEnv*, jclass, jlong freeFunction, jlong ptr) {
49 void* nativePtr = reinterpret_cast<void*>(static_cast<uintptr_t>(ptr));
50 FreeFunction nativeFreeFunction
51 = reinterpret_cast<FreeFunction>(static_cast<uintptr_t>(freeFunction));
52 nativeFreeFunction(nativePtr);
53 }
54
nFcntlInt(JNIEnv * env,jclass,jint fd,jint cmd,jint arg)55 static jint nFcntlInt(JNIEnv* env, jclass, jint fd, jint cmd, jint arg) {
56 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, cmd, arg)));
57 }
58
nLseek(JNIEnv * env,jclass,jint fd,jlong offset,jint whence)59 static jlong nLseek(JNIEnv* env, jclass, jint fd, jlong offset, jint whence) {
60 return throwIfMinusOne(env, "lseek", TEMP_FAILURE_RETRY(lseek(fd, offset, whence)));
61 }
62
nPipe2(JNIEnv * env,jclass,jint flags)63 static jintArray nPipe2(JNIEnv* env, jclass, jint flags) {
64 int fds[2];
65 throwIfMinusOne(env, "pipe2", TEMP_FAILURE_RETRY(pipe2(fds, flags)));
66
67 jintArray result;
68 result = env->NewIntArray(2);
69 if (result == NULL) {
70 return NULL; /* out of memory error thrown */
71 }
72 env->SetIntArrayRegion(result, 0, 2, fds);
73 return result;
74 }
75
nDup(JNIEnv * env,jclass,jint fd)76 static jlong nDup(JNIEnv* env, jclass, jint fd) {
77 return throwIfMinusOne(env, "fcntl", TEMP_FAILURE_RETRY(fcntl(fd, F_DUPFD_CLOEXEC, 0)));
78 }
79
80 // ---- Registration ----
81
82 static const JNINativeMethod sMethods[] =
83 {
84 { "applyFreeFunction", "(JJ)V", (void*)nApplyFreeFunction },
85 { "nFcntlInt", "(III)I", (void*)nFcntlInt },
86 { "nLseek", "(IJI)J", (void*)nLseek },
87 { "nPipe2", "(I)[I", (void*)nPipe2 },
88 { "nDup", "(I)I", (void*)nDup },
89 };
90
JNI_OnLoad(JavaVM * vm,void *)91 extern "C" jint JNI_OnLoad(JavaVM* vm, void* /* reserved */)
92 {
93 JNIEnv* env = NULL;
94 jint result = -1;
95
96 if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
97 ALOGE("GetEnv failed!");
98 return result;
99 }
100 ALOG_ASSERT(env, "Could not retrieve the env!");
101
102 ALOGI("%s: JNI_OnLoad", __FILE__);
103
104 jint res = jniRegisterNativeMethods(env, "com/android/ravenwood/common/RavenwoodRuntimeNative",
105 sMethods, NELEM(sMethods));
106 if (res < 0) {
107 return res;
108 }
109
110 register_android_system_OsConstants(env);
111
112 return JNI_VERSION_1_4;
113 }
114