Commit 01cae3f4 authored by trinity-1686a's avatar trinity-1686a 💜
Browse files

finish rust part of iOS

parent ba824008
......@@ -3,3 +3,4 @@ jniLibs
target
ndk
ndk.zip
arti-mobile.h
......@@ -18,7 +18,7 @@ tracing-subscriber = "0.3.3"
# dependancies specific to iOS
#[target.'cfg(target_os = "ios")'.dependencies]
[target.'cfg(target_os = "ios")'.dependencies]
tracing-oslog = "0.1.2"
......
......@@ -26,8 +26,11 @@ android-release: android-install-deps
ios: ios-release
ios-debug: ios-install-deps
ios-release: ios-install-deps
ios-debug: ios-install-deps arti-mobile.h
ios-release: ios-install-deps arti-mobile.h
arti-mobile.h:
cbindgen src/ios.rs -l c > arti-mobile.h
# Args:
# $1: Target name
......@@ -53,11 +56,11 @@ clean:
-rm -r ./jniLibs
clean-all: clean
-rm -r ndk ndk.zip
-rm -fr ndk ndk.zip
android-install-deps: ndk cargo-ndk android-targets
ios-install-deps: ios-targets
ios-install-deps: ios-targets cbindgen
ndk: ndk.zip
unzip ndk.zip -d $@
......@@ -80,6 +83,11 @@ ifeq ($(shell which cargo-ndk),)
cargo install cargo-ndk
endif
cbindgen:
ifeq ($(shell which cbindgen),)
cargo install cbindgen
endif
# Args:
# $1: Target name
# $2: Target operating system
......@@ -101,5 +109,5 @@ $(foreach target, $(ANDROID_TARGETS), $(eval $(call target-rules,$(target),andro
$(foreach target, $(IOS_TARGETS), $(eval $(call target-rules,$(target),ios)))
.PHONY: android-install-deps cargo-ndk android-debug android-release android android-targets
.PHONY: ios-install-deps ios-debug ios-release ios ios-targets
.PHONY: ios-install-deps cbindgen ios-debug ios-release ios ios-targets
.PHONY: all
#![allow(non_snake_case)]
use crate::run_arti;
use anyhow::Result;
use std::sync::Once;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
use jni::objects::{JClass, JString};
use jni::sys::jstring;
use jni::JNIEnv;
/// Create a static method myMethod on class net.example.MyClass
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_myMethod(
env: JNIEnv,
_: JClass,
target: JString,
cache_dir: JString,
) -> jstring {
// if logger initialization failed, there isn't much we can do, not even log it.
// it shouldn't stop Arti from functionning however!
let _ = init_logger();
let result = match run_arti(
&env.get_string(target)
.expect("target is invalid")
.to_string_lossy(),
&env.get_string(cache_dir)
.expect("cache_dir is invalid")
.to_string_lossy(),
) {
Ok(res) => format!("Http body: {}", res),
Err(e) => format!("Error: {}", e),
};
let output = env
.new_string(result)
.expect("failed to create java string");
output.into_inner()
}
static LOGGER: Once = Once::new();
fn init_logger() -> Result<()> {
if LOGGER.is_completed() {
let layer = tracing_android::layer("rust.arti")?;
LOGGER.call_once(|| Subscriber::new().with(layer).init());
}
Ok(())
}
/// Android 5.0 to 6.0 misses this function, which prevent Arti from running. This is a translation
/// to Rust of Musl implementation. If you don't plan to support anything below Android 7.0, you
/// should probably not copy this code.
/// It might be possible to support Android 4.4 and below with the same trick applied to more
/// functions (at least create_epoll1), but this might not be worth the effort.
#[no_mangle]
pub unsafe extern "C" fn lockf(fd: libc::c_int, cmd: libc::c_int, len: libc::off_t) -> libc::c_int {
use libc::*;
let mut l = flock {
l_type: F_WRLCK as i16,
l_whence: SEEK_CUR as i16,
l_len: len,
l_pid: 0,
l_start: 0,
};
match cmd {
F_TEST => {
l.l_type = F_RDLCK as i16;
if fcntl(fd, F_GETLK, &l) < 0 {
return -1;
}
if l.l_type == F_UNLCK as i16 || l.l_pid == getpid() {
return 0;
}
*__errno() = EACCES;
-1
}
F_ULOCK => {
l.l_type = F_UNLCK as i16;
fcntl(fd, F_SETLK, &l)
}
F_TLOCK => fcntl(fd, F_SETLK, &l),
F_LOCK => fcntl(fd, F_SETLKW, &l),
_ => {
*__errno() = EINVAL;
-1
}
}
}
#![allow(non_snake_case)]
use crate::run_arti;
use anyhow::Result;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::sync::Once;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
#[no_mangle]
pub extern "C" fn my_rust_function(target: *const c_char, cache_dir: *const c_char) -> *mut c_char {
let _ = init_logger();
let target = unsafe { CStr::from_ptr(target) }.to_string_lossy();
let cache_dir = unsafe { CStr::from_ptr(cache_dir) }.to_string_lossy();
let result = match run_arti(&target, &cache_dir) {
Ok(res) => format!("Http body: {}", res),
Err(e) => format!("Error: {}", e),
};
CString::new(result).unwrap().into_raw()
}
#[no_mangle]
pub extern "C" fn my_rust_function_free_result(s: *mut c_char) {
unsafe {
if !s.is_null() {
drop(CString::from_raw(s));
}
}
}
static LOGGER: Once = Once::new();
fn init_logger() -> Result<()> {
if LOGGER.is_completed() {
let layer = tracing_oslog::OsLogger::new("rust.arti", "default");
LOGGER.call_once(|| Subscriber::new().with(layer).init());
}
Ok(())
}
......@@ -31,150 +31,8 @@ fn run_arti(to: &str, cache: &str) -> Result<String> {
/// Expose the JNI interface for Android
#[cfg(target_os = "android")]
#[allow(non_snake_case)]
pub mod android {
use super::*;
use std::sync::Once;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
use jni::objects::{JClass, JString};
use jni::sys::jstring;
use jni::JNIEnv;
/// Create a static method myMethod on class net.example.MyClass
#[no_mangle]
pub extern "C" fn Java_net_example_MyClass_myMethod(
env: JNIEnv,
_: JClass,
target: JString,
cache_dir: JString,
) -> jstring {
// if logger initialization failed, there isn't much we can do, not even log it.
// it shouldn't stop Arti from functionning however!
let _ = init_logger();
let result = match run_arti(
&env.get_string(target)
.expect("target is invalid")
.to_string_lossy(),
&env.get_string(cache_dir)
.expect("cache_dir is invalid")
.to_string_lossy(),
) {
Ok(res) => format!("Http body: {}", res),
Err(e) => format!("Error: {}", e),
};
let output = env
.new_string(result)
.expect("failed to create java string");
output.into_inner()
}
static LOGGER: Once = Once::new();
fn init_logger() -> Result<()> {
if LOGGER.is_completed() {
let layer = tracing_android::layer("rust.arti")?;
LOGGER.call_once(|| Subscriber::new().with(layer).init());
}
Ok(())
}
/// Android 5.0 to 6.0 misses this function, which prevent Arti from running. This is a translation
/// to Rust of Musl implementation. If you don't plan to support anything below Android 7.0, you
/// should probably not copy this code.
/// It might be possible to support Android 4.4 and below with the same trick applied to more
/// functions (at least create_epoll1), but this might not be worth the effort.
#[no_mangle]
pub unsafe extern "C" fn lockf(
fd: libc::c_int,
cmd: libc::c_int,
len: libc::off_t,
) -> libc::c_int {
use libc::*;
let mut l = flock {
l_type: F_WRLCK as i16,
l_whence: SEEK_CUR as i16,
l_len: len,
l_pid: 0,
l_start: 0,
};
match cmd {
F_TEST => {
l.l_type = F_RDLCK as i16;
if fcntl(fd, F_GETLK, &l) < 0 {
return -1;
}
if l.l_type == F_UNLCK as i16 || l.l_pid == getpid() {
return 0;
}
*__errno() = EACCES;
-1
}
F_ULOCK => {
l.l_type = F_UNLCK as i16;
fcntl(fd, F_SETLK, &l)
}
F_TLOCK => fcntl(fd, F_SETLK, &l),
F_LOCK => fcntl(fd, F_SETLKW, &l),
_ => {
*__errno() = EINVAL;
-1
}
}
}
}
pub mod android;
/// Expose the native interface for iOS
#[cfg(target_os = "ios")]
#[allow(non_snake_case)]
pub mod ios {
use super::*;
use std::ffi::{CStr, CString};
use std::os::raw::c_char;
use std::sync::Once;
use tracing_subscriber::fmt::Subscriber;
use tracing_subscriber::prelude::*;
#[no_mangle]
pub extern "C" fn my_rust_function(
target: *const c_char,
cache_dir: *const c_char,
) -> *mut c_char {
let _ = init_logger();
let target = unsafe { CStr::from_ptr(target) }.to_string_lossy();
let cache_dir = unsafe { CStr::from_ptr(cache_dir) }.to_string_lossy();
let result = match run_arti(&target, &cache_dir) {
Ok(res) => format!("Http body: {}", res),
Err(e) => format!("Error: {}", e),
};
CString::new(result).unwrap().into_raw()
}
#[no_mangle]
pub extern "C" fn my_rust_function_free_result(s: *mut c_char) {
unsafe {
if !s.is_null() {
drop(CString::from_raw(s));
}
}
}
static LOGGER: Once = Once::new();
fn init_logger() -> Result<()> {
if LOGGER.is_completed() {
let layer = tracing_oslog::OsLogger::new("rust.arti", "default");
LOGGER.call_once(|| Subscriber::new().with(layer).init());
}
Ok(())
}
}
pub mod ios;
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment