Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0a45b9e8 authored by Dennis Shen's avatar Dennis Shen Committed by Gerrit Code Review
Browse files

Merge "aconfig: update mapped_file" into main

parents 0296ef00 7bb9cda6
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ rust_defaults {
        "libaconfig_storage_protos",
        "libonce_cell",
        "libprotobuf",
        "libtempfile",
    ],
}

+1 −0
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@ anyhow = "1.0.69"
memmap2 = "0.8.0"
protobuf = "3.2.0"
once_cell = "1.19.0"
tempfile = "3.9.0"

[build-dependencies]
protobuf-codegen = "3.2.0"
+40 −81
Original line number Diff line number Diff line
@@ -29,8 +29,7 @@ use crate::protos::{
use crate::StorageFileSelection;

/// Cache for already mapped files
static ALL_MAPPED_FILES: Lazy<Mutex<HashMap<String, MappedStorageFileSet>>> =
    Lazy::new(|| {
static ALL_MAPPED_FILES: Lazy<Mutex<HashMap<String, MappedStorageFileSet>>> = Lazy::new(|| {
    let mapped_files = HashMap::new();
    Mutex::new(mapped_files)
});
@@ -62,19 +61,14 @@ fn find_container_storage_location(
    bail!("Storage file does not exist for {}", container)
}

/// Map all storage files for a particular container
fn map_container_storage_files(
    location_pb_file: &str,
    container: &str,
) -> Result<MappedStorageFileSet> {
    let files_location = find_container_storage_location(location_pb_file, container)?;

    let package_map_file = File::open(files_location.package_map())?;
    let metadata = package_map_file.metadata()?;
/// Verify the file is read only and then map it
fn verify_read_only_and_map(file_path: &str) -> Result<Mmap> {
    let file = File::open(file_path)?;
    let metadata = file.metadata()?;
    ensure!(
        metadata.permissions().readonly(),
        "Cannot mmap file {} as it is not read only",
        files_location.package_map()
        file_path
    );
    // SAFETY:
    //
@@ -89,28 +83,18 @@ fn map_container_storage_files(
    // We should remove this restriction if we need to support mmap non read only file in
    // the future (by making this api unsafe). But for now, all flags are boot stable, so
    // the boot flag file copy should be readonly.
    let package_map = Arc::new(unsafe { Mmap::map(&package_map_file)? });

    let flag_map_file = File::open(files_location.flag_map())?;
    let metadata = flag_map_file.metadata()?;
    ensure!(
        metadata.permissions().readonly(),
        "Cannot mmap file {} as it is not read only",
        files_location.flag_map()
    );
    // SAFETY: Refer to the previous safety statement
    let flag_map = Arc::new(unsafe { Mmap::map(&flag_map_file)? });

    let flag_val_file = File::open(files_location.flag_val())?;
    let metadata = flag_val_file.metadata()?;
    ensure!(
        metadata.permissions().readonly(),
        "Cannot mmap file {} as it is not read only",
        files_location.flag_val()
    );
    // SAFETY: Refer to the previous safety statement
    let flag_val = Arc::new(unsafe { Mmap::map(&flag_val_file)? });
    unsafe { Ok(Mmap::map(&file)?) }
}

/// Map all storage files for a particular container
fn map_container_storage_files(
    location_pb_file: &str,
    container: &str,
) -> Result<MappedStorageFileSet> {
    let files_location = find_container_storage_location(location_pb_file, container)?;
    let package_map = Arc::new(verify_read_only_and_map(files_location.package_map())?);
    let flag_map = Arc::new(verify_read_only_and_map(files_location.flag_map())?);
    let flag_val = Arc::new(verify_read_only_and_map(files_location.flag_val())?);
    Ok(MappedStorageFileSet { package_map, flag_map, flag_val })
}

@@ -143,8 +127,7 @@ pub fn get_mapped_file(
#[cfg(test)]
mod tests {
    use super::*;
    use crate::test_utils::get_binary_storage_proto_bytes;
    use std::io::Write;
    use crate::test_utils::{get_binary_storage_proto_bytes, write_bytes_to_temp_file};

    #[test]
    fn test_find_storage_file_location() {
@@ -167,11 +150,10 @@ files {
}
"#;
        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
        let file_full_path = "./tests/temp_location_file_1.pb";
        let mut file = File::create(&file_full_path).unwrap();
        file.write_all(&binary_proto_bytes).unwrap();
        let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
        let file_full_path = file.path().display().to_string();

        let file_info = find_container_storage_location(file_full_path, "system").unwrap();
        let file_info = find_container_storage_location(&file_full_path, "system").unwrap();
        assert_eq!(file_info.version(), 0);
        assert_eq!(file_info.container(), "system");
        assert_eq!(file_info.package_map(), "/system/etc/package.map");
@@ -179,7 +161,7 @@ files {
        assert_eq!(file_info.flag_val(), "/metadata/aconfig/system.val");
        assert_eq!(file_info.timestamp(), 12345);

        let file_info = find_container_storage_location(file_full_path, "product").unwrap();
        let file_info = find_container_storage_location(&file_full_path, "product").unwrap();
        assert_eq!(file_info.version(), 1);
        assert_eq!(file_info.container(), "product");
        assert_eq!(file_info.package_map(), "/product/etc/package.map");
@@ -187,7 +169,7 @@ files {
        assert_eq!(file_info.flag_val(), "/metadata/aconfig/product.val");
        assert_eq!(file_info.timestamp(), 54321);

        let err = find_container_storage_location(file_full_path, "vendor").unwrap_err();
        let err = find_container_storage_location(&file_full_path, "vendor").unwrap_err();
        assert_eq!(format!("{:?}", err), "Storage file does not exist for vendor");
    }

@@ -217,25 +199,14 @@ files {
}
"#;
        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
        let location_file_full_path = "./tests/temp_location_file_2.pb";
        let mut file = File::create(&location_file_full_path).unwrap();
        file.write_all(&binary_proto_bytes).unwrap();
        let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
        let file_full_path = file.path().display().to_string();

        map_and_verify(
            location_file_full_path,
            StorageFileSelection::PackageMap,
            "./tests/package.map",
        );
        map_and_verify(&file_full_path, StorageFileSelection::PackageMap, "./tests/package.map");

        map_and_verify(
            location_file_full_path,
            StorageFileSelection::FlagMap,
            "./tests/flag.map");
        map_and_verify(&file_full_path, StorageFileSelection::FlagMap, "./tests/flag.map");

        map_and_verify(
            location_file_full_path,
            StorageFileSelection::FlagVal,
            "./tests/flag.val");
        map_and_verify(&file_full_path, StorageFileSelection::FlagVal, "./tests/flag.val");
    }

    #[test]
@@ -251,14 +222,10 @@ files {
}
"#;
        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
        let location_file_full_path = "./tests/temp_location_file_3.pb";
        let mut file = File::create(&location_file_full_path).unwrap();
        file.write_all(&binary_proto_bytes).unwrap();
        let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
        let file_full_path = file.path().display().to_string();

        let error = map_container_storage_files(
            location_file_full_path,
            "system",
        ).unwrap_err();
        let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
        assert_eq!(
            format!("{:?}", error),
            "Cannot mmap file ./tests/rw.package.map as it is not read only"
@@ -275,14 +242,10 @@ files {
}
"#;
        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
        let location_file_full_path = "./tests/temp_location_file_3.pb";
        let mut file = File::create(&location_file_full_path).unwrap();
        file.write_all(&binary_proto_bytes).unwrap();
        let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
        let file_full_path = file.path().display().to_string();

        let error = map_container_storage_files(
            location_file_full_path,
            "system",
        ).unwrap_err();
        let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
        assert_eq!(
            format!("{:?}", error),
            "Cannot mmap file ./tests/rw.flag.map as it is not read only"
@@ -299,14 +262,10 @@ files {
}
"#;
        let binary_proto_bytes = get_binary_storage_proto_bytes(text_proto).unwrap();
        let location_file_full_path = "./tests/temp_location_file_3.pb";
        let mut file = File::create(&location_file_full_path).unwrap();
        file.write_all(&binary_proto_bytes).unwrap();
        let file = write_bytes_to_temp_file(&binary_proto_bytes).unwrap();
        let file_full_path = file.path().display().to_string();

        let error = map_container_storage_files(
            location_file_full_path,
            "system",
        ).unwrap_err();
        let error = map_container_storage_files(&file_full_path, "system").unwrap_err();
        assert_eq!(
            format!("{:?}", error),
            "Cannot mmap file ./tests/rw.flag.val as it is not read only"
+8 −0
Original line number Diff line number Diff line
@@ -17,6 +17,8 @@
use crate::protos::ProtoStorageFiles;
use anyhow::Result;
use protobuf::Message;
use std::io::Write;
use tempfile::NamedTempFile;

pub fn get_binary_storage_proto_bytes(text_proto: &str) -> Result<Vec<u8>> {
    let storage_files: ProtoStorageFiles = protobuf::text_format::parse_from_str(text_proto)?;
@@ -24,3 +26,9 @@ pub fn get_binary_storage_proto_bytes(text_proto: &str) -> Result<Vec<u8>> {
    storage_files.write_to_vec(&mut binary_proto)?;
    Ok(binary_proto)
}

pub fn write_bytes_to_temp_file(bytes: &[u8]) -> Result<NamedTempFile> {
    let mut file = NamedTempFile::new()?;
    let _ = file.write_all(&bytes);
    Ok(file)
}