composd: prepare staging directory w/ libartpalette-system
Output files are staged until they are fully generated, then move to the
final location. The staging directory has a different SELinux context to
prevent misuse, and should change when it's moved to the final
directory.
This change makes composd to follow the same setup, using libartpalette.
As a result, the output are no longer stored in CompOS's own apexdata
(which was not intentional).
This change does not use bindgen, which seems have some difficulty to
bridge `const char**` correctly. Neither cxx, since it doesn't seem to
simplify the (already simple) call.
Bug: 205750213
Test: See odrefresh produces output in the staging directory
Change-Id: Ifc97b31a98052a31209556449d1642089a8c0e2e
diff --git a/compos/composd/native/lib.rs b/compos/composd/native/lib.rs
index ace9600..cbec7fd 100644
--- a/compos/composd/native/lib.rs
+++ b/compos/composd/native/lib.rs
@@ -12,12 +12,13 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-//! Bindings native helpers for composd.
+//! Native helpers for composd.
-pub use ffi::*;
+pub use art::*;
+pub use crypto::*;
#[cxx::bridge]
-mod ffi {
+mod crypto {
/// Contains either a key or a reason why the key could not be extracted.
struct KeyResult {
/// The extracted key. If empty, the attempt to extract the key failed.
@@ -36,3 +37,38 @@
fn extract_rsa_public_key(der_certificate: &[u8]) -> KeyResult;
}
}
+
+mod art {
+ use anyhow::{anyhow, Result};
+ use libc::c_char;
+ use std::ffi::{CStr, OsStr};
+ use std::io::Error;
+ use std::os::unix::ffi::OsStrExt;
+ use std::path::Path;
+ use std::ptr::null;
+
+ // From libartpalette(-system)
+ extern "C" {
+ fn PaletteCreateOdrefreshStagingDirectory(out_staging_dir: *mut *const c_char) -> i32;
+ }
+ const PALETTE_STATUS_OK: i32 = 0;
+ const PALETTE_STATUS_CHECK_ERRNO: i32 = 1;
+
+ /// Creates and returns the staging directory for odrefresh.
+ pub fn palette_create_odrefresh_staging_directory() -> Result<&'static Path> {
+ let mut staging_dir: *const c_char = null();
+ // SAFETY: The C function always returns a non-null C string (after created the directory).
+ let status = unsafe { PaletteCreateOdrefreshStagingDirectory(&mut staging_dir) };
+ match status {
+ PALETTE_STATUS_OK => {
+ // SAFETY: The previously returned `*const c_char` should point to a legitimate C
+ // string.
+ let cstr = unsafe { CStr::from_ptr(staging_dir) };
+ let path = OsStr::from_bytes(cstr.to_bytes()).as_ref();
+ Ok(path)
+ }
+ PALETTE_STATUS_CHECK_ERRNO => Err(anyhow!(Error::last_os_error().to_string())),
+ _ => Err(anyhow!("Failed with palette status {}", status)),
+ }
+ }
+}