From e9898f393a2c9e96dd23e298f661e6e7121951dd Mon Sep 17 00:00:00 2001 From: Joel Galenson Date: Thu, 29 Jul 2021 15:45:07 -0700 Subject: [PATCH] Move the Rust system property bindings into librustutils. Bug: 182498247 Test: Build Change-Id: I688a1c7654d94b349b6903d9e7735656d31e7629 --- libc/NOTICE | 16 -- libc/rust/Android.bp | 30 ---- libc/rust/system_properties.rs | 227 ------------------------ libc/rust/system_properties_bindgen.hpp | 19 -- 4 files changed, 292 deletions(-) delete mode 100644 libc/rust/Android.bp delete mode 100644 libc/rust/system_properties.rs delete mode 100644 libc/rust/system_properties_bindgen.hpp diff --git a/libc/NOTICE b/libc/NOTICE index 8260112ce..ff16da7aa 100644 --- a/libc/NOTICE +++ b/libc/NOTICE @@ -882,22 +882,6 @@ SUCH DAMAGE. ------------------------------------------------------------------- -Copyright (C) 2021 The Android Open Source Project - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. - -------------------------------------------------------------------- - Copyright (C) 2021 The Android Open Source Project All rights reserved. diff --git a/libc/rust/Android.bp b/libc/rust/Android.bp deleted file mode 100644 index 44cf848b4..000000000 --- a/libc/rust/Android.bp +++ /dev/null @@ -1,30 +0,0 @@ -rust_bindgen { - name: "libsystem_properties_bindgen", - wrapper_src: "system_properties_bindgen.hpp", - crate_name: "system_properties_bindgen", - source_stem: "bindings", - - bindgen_flags: [ - "--size_t-is-usize", - "--allowlist-function=__system_property_find", - "--allowlist-function=__system_property_read_callback", - "--allowlist-function=__system_property_set", - "--allowlist-function=__system_property_wait", - ], -} - -rust_library { - name: "libsystem_properties-rust", - crate_name: "system_properties", - srcs: [ - "system_properties.rs", - ], - rustlibs: [ - "libanyhow", - "libsystem_properties_bindgen", - "libthiserror", - ], - shared_libs: [ - "libbase", - ], -} diff --git a/libc/rust/system_properties.rs b/libc/rust/system_properties.rs deleted file mode 100644 index 189e8ee56..000000000 --- a/libc/rust/system_properties.rs +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -//! This crate provides the PropertyWatcher type, which watches for changes -//! in Android system properties. - -use anyhow::{anyhow, Context, Result as AnyhowResult}; -use system_properties_bindgen::prop_info as PropInfo; -use std::os::raw::c_char; -use std::ptr::null; -use std::{ - ffi::{c_void, CStr, CString}, - str::Utf8Error, -}; -use thiserror::Error; - -/// Errors this crate can generate -#[derive(Error, Debug)] -pub enum PropertyWatcherError { - /// We can't watch for a property whose name contains a NUL character. - #[error("Cannot convert name to C string")] - BadNameError(#[from] std::ffi::NulError), - /// We can only watch for properties that exist when the watcher is created. - #[error("System property is absent")] - SystemPropertyAbsent, - /// __system_property_wait timed out despite being given no timeout. - #[error("Wait failed")] - WaitFailed, - /// read callback was not called - #[error("__system_property_read_callback did not call callback")] - ReadCallbackNotCalled, - /// read callback gave us a NULL pointer - #[error("__system_property_read_callback gave us a NULL pointer instead of a string")] - MissingCString, - /// read callback gave us a bad C string - #[error("__system_property_read_callback gave us a non-UTF8 C string")] - BadCString(#[from] Utf8Error), - /// read callback returned an error - #[error("Callback failed")] - CallbackError(#[from] anyhow::Error), - /// Failure in setting the system property - #[error("__system_property_set failed.")] - SetPropertyFailed, -} - -/// Result type specific for this crate. -pub type Result = std::result::Result; - -/// PropertyWatcher takes the name of an Android system property such -/// as `keystore.boot_level`; it can report the current value of this -/// property, or wait for it to change. -pub struct PropertyWatcher { - prop_name: CString, - prop_info: *const PropInfo, - serial: system_properties_bindgen::__uint32_t, -} - -impl PropertyWatcher { - /// Create a PropertyWatcher for the named system property. - pub fn new(name: &str) -> Result { - Ok(Self { prop_name: CString::new(name)?, prop_info: null(), serial: 0 }) - } - - // Lazy-initializing accessor for self.prop_info. - fn get_prop_info(&mut self) -> Option<*const PropInfo> { - if self.prop_info.is_null() { - // Unsafe required for FFI call. Input and output are both const. - // The returned pointer is valid for the lifetime of the program. - self.prop_info = unsafe { - system_properties_bindgen::__system_property_find(self.prop_name.as_ptr()) - }; - } - if self.prop_info.is_null() { - None - } else { - Some(self.prop_info) - } - } - - fn read_raw(prop_info: *const PropInfo, mut f: impl FnOnce(Option<&CStr>, Option<&CStr>)) { - // Unsafe function converts values passed to us by - // __system_property_read_callback to Rust form - // and pass them to inner callback. - unsafe extern "C" fn callback( - res_p: *mut c_void, - name: *const c_char, - value: *const c_char, - _: system_properties_bindgen::__uint32_t, - ) { - let name = if name.is_null() { None } else { Some(CStr::from_ptr(name)) }; - let value = if value.is_null() { None } else { Some(CStr::from_ptr(value)) }; - let f = &mut *res_p.cast::<&mut dyn FnMut(Option<&CStr>, Option<&CStr>)>(); - f(name, value); - } - - let mut f: &mut dyn FnOnce(Option<&CStr>, Option<&CStr>) = &mut f; - - // Unsafe block for FFI call. We convert the FnOnce - // to a void pointer, and unwrap it in our callback. - unsafe { - system_properties_bindgen::__system_property_read_callback( - prop_info, - Some(callback), - &mut f as *mut _ as *mut c_void, - ) - } - } - - /// Call the passed function, passing it the name and current value - /// of this system property. See documentation for - /// `__system_property_read_callback` for details. - /// Returns an error if the property is empty or doesn't exist. - pub fn read(&mut self, f: F) -> Result - where - F: FnOnce(&str, &str) -> anyhow::Result, - { - let prop_info = self.get_prop_info().ok_or(PropertyWatcherError::SystemPropertyAbsent)?; - let mut result = Err(PropertyWatcherError::ReadCallbackNotCalled); - Self::read_raw(prop_info, |name, value| { - // use a wrapping closure as an erzatz try block. - result = (|| { - let name = name.ok_or(PropertyWatcherError::MissingCString)?.to_str()?; - let value = value.ok_or(PropertyWatcherError::MissingCString)?.to_str()?; - f(name, value).map_err(PropertyWatcherError::CallbackError) - })() - }); - result - } - - // Waits for the property that self is watching to be created. Returns immediately if the - // property already exists. - fn wait_for_property_creation(&mut self) -> Result<()> { - let mut global_serial = 0; - loop { - match self.get_prop_info() { - Some(_) => return Ok(()), - None => { - // Unsafe call for FFI. The function modifies only global_serial, and has - // no side-effects. - if !unsafe { - // Wait for a global serial number change, then try again. On success, - // the function will update global_serial with the last version seen. - system_properties_bindgen::__system_property_wait( - null(), - global_serial, - &mut global_serial, - null(), - ) - } { - return Err(PropertyWatcherError::WaitFailed); - } - } - } - } - } - - /// Wait for the system property to change. This - /// records the serial number of the last change, so - /// race conditions are avoided. - pub fn wait(&mut self) -> Result<()> { - // If the property is null, then wait for it to be created. Subsequent waits will - // skip this step and wait for our specific property to change. - if self.prop_info.is_null() { - return self.wait_for_property_creation(); - } - - let mut new_serial = self.serial; - // Unsafe block to call __system_property_wait. - // All arguments are private to PropertyWatcher so we - // can be confident they are valid. - if !unsafe { - system_properties_bindgen::__system_property_wait( - self.prop_info, - self.serial, - &mut new_serial, - null(), - ) - } { - return Err(PropertyWatcherError::WaitFailed); - } - self.serial = new_serial; - Ok(()) - } -} - -/// Reads a system property. -pub fn read(name: &str) -> AnyhowResult { - PropertyWatcher::new(name) - .context("Failed to create a PropertyWatcher.")? - .read(|_name, value| Ok(value.to_owned())) - .with_context(|| format!("Failed to read the system property {}.", name)) -} - -/// Writes a system property. -pub fn write(name: &str, value: &str) -> AnyhowResult<()> { - if - // Unsafe required for FFI call. Input and output are both const and valid strings. - unsafe { - // If successful, __system_property_set returns 0, otherwise, returns -1. - system_properties_bindgen::__system_property_set( - CString::new(name) - .context("Failed to construct CString from name.")? - .as_ptr(), - CString::new(value) - .context("Failed to construct CString from value.")? - .as_ptr(), - ) - } == 0 - { - Ok(()) - } else { - Err(anyhow!(PropertyWatcherError::SetPropertyFailed)) - } -} diff --git a/libc/rust/system_properties_bindgen.hpp b/libc/rust/system_properties_bindgen.hpp deleted file mode 100644 index 307cd6cff..000000000 --- a/libc/rust/system_properties_bindgen.hpp +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright (C) 2021 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#pragma once - -#include "sys/system_properties.h"