1 /*
2  * Copyright (C) 2023 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 //! A FFI wrapper for APEX support library
18 
19 mod apexinfo;
20 
21 use apexinfo::{AApexInfo, AApexInfoError};
22 use std::ffi::c_char;
23 
24 /// NOTE: Keep these constants in sync with apexsupport.h
25 const AAPEXINFO_OK: i32 = 0;
26 const AAPEXINFO_NO_APEX: i32 = 1;
27 const AAPEXINFO_ERROR_GET_EXECUTABLE_PATH: i32 = 2;
28 const AAPEXINFO_INALID_APEX: i32 = 3;
29 
as_error_code(err: &AApexInfoError) -> i3230 fn as_error_code(err: &AApexInfoError) -> i32 {
31     match err {
32         AApexInfoError::PathNotFromApex(_) => AAPEXINFO_NO_APEX,
33         AApexInfoError::ExePathUnavailable(_) => AAPEXINFO_ERROR_GET_EXECUTABLE_PATH,
34         AApexInfoError::InvalidApex(_) => AAPEXINFO_INALID_APEX,
35     }
36 }
37 
38 #[no_mangle]
39 /// Creates AApexInfo object when called by the executable from an APEX
40 ///
41 /// # Safety
42 ///
43 /// The provided pointer must be valid and have no aliases for the duration of the call.
AApexInfo_create(out: *mut *mut AApexInfo) -> i3244 pub unsafe extern "C" fn AApexInfo_create(out: *mut *mut AApexInfo) -> i32 {
45     match AApexInfo::create() {
46         Ok(info) => {
47             let ptr = Box::into_raw(Box::new(info));
48             // SAFETY: We have checked that `out` is not null, so the caller guarantees that it is
49             // valid and unaliased.
50             unsafe { *out = ptr };
51             AAPEXINFO_OK
52         }
53         Err(err) => {
54             // TODO(b/271488212): Use Rust logger.
55             eprintln!("AApexInfo_create(): {err:?}");
56             as_error_code(&err)
57         }
58     }
59 }
60 
61 #[no_mangle]
62 /// Destroys AApexInfo object created by AApexInfo_create().
63 ///
64 /// # Safety
65 ///
66 /// The provided pointer must point to a valid object previously allocated by
67 /// `AApexInfo_create` (and not yet destroyed).
AApexInfo_destroy(info: *mut AApexInfo)68 pub unsafe extern "C" fn AApexInfo_destroy(info: *mut AApexInfo) {
69     // SAFETY: The pointer is not null, so the caller guarantees that it was previously returned by
70     // AApexInfo_create. AApexInfo_create got the pointer from `Box::into_raw`, so converting it
71     // back with `Box::from_raw` is valid.
72     unsafe { drop(Box::from_raw(info)) };
73 }
74 
75 #[no_mangle]
76 /// Returns a C-string for APEX name.
77 ///
78 /// # Safety
79 ///
80 /// The provided pointer must point to a valid object.
AApexInfo_getName(info: *const AApexInfo) -> *const c_char81 pub unsafe extern "C" fn AApexInfo_getName(info: *const AApexInfo) -> *const c_char {
82     // SAFETY: The pointer is not null, so the caller guarantees that it is valid.
83     unsafe { (*info).name.as_ptr() }
84 }
85 
86 #[no_mangle]
87 /// Returns a version of the APEX.
88 ///
89 /// # Safety
90 ///
91 /// The provided pointer must point to a valid object.
AApexInfo_getVersion(info: *const AApexInfo) -> i6492 pub unsafe extern "C" fn AApexInfo_getVersion(info: *const AApexInfo) -> i64 {
93     // SAFETY: The pointer is not null, so the caller guarantees that it is valid.
94     unsafe { (*info).version }
95 }
96