Skip to main content

update_package/
lib.rs

1// Copyright 2020 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#![deny(missing_docs)]
6
7//! Typesafe wrappers around an "update" package.
8
9mod board;
10mod epoch;
11mod hash;
12mod image;
13pub mod images;
14pub mod manifest;
15mod name;
16mod packages;
17pub mod signed_manifest;
18mod update_mode;
19mod version;
20
21pub use crate::board::VerifyBoardError;
22pub use crate::epoch::ParseEpochError;
23pub use crate::hash::HashError;
24pub use crate::image::OpenImageError;
25pub use crate::images::{
26    ImageMetadata, ImageMetadataError, ImagePackagesError, ImagePackagesManifest,
27    ImagePackagesManifestBuilder, ImagesMetadata, ResolveImagesError, VerifyError,
28    VersionedImagePackagesManifest, ZbiAndOptionalVbmetaMetadata, parse_image_packages_json,
29};
30pub use crate::name::VerifyNameError;
31pub use crate::packages::{
32    ParsePackageError, SerializePackageError, parse_packages_json, serialize_packages_json,
33};
34pub use crate::signed_manifest::MANIFEST_DEV_KEY_PEM;
35pub use crate::update_mode::{ParseUpdateModeError, UpdateMode};
36pub use crate::version::{ReadVersionError, SystemVersion};
37
38use fidl_fuchsia_io as fio;
39use fuchsia_hash::Hash;
40use fuchsia_url::fuchsia_pkg::PinnedAbsolutePackageUrl;
41
42/// An open handle to an image package.
43#[cfg(target_os = "fuchsia")]
44pub struct UpdateImagePackage {
45    proxy: fio::DirectoryProxy,
46}
47
48#[cfg(target_os = "fuchsia")]
49impl UpdateImagePackage {
50    /// Creates a new [`UpdateImagePackage`] with a given proxy.
51    pub fn new(proxy: fio::DirectoryProxy) -> Self {
52        Self { proxy }
53    }
54
55    /// Opens the image at given `path` as a resizable VMO buffer.
56    pub async fn open_image(&self, path: &str) -> Result<fidl_fuchsia_mem::Buffer, OpenImageError> {
57        image::open_from_path(&self.proxy, path).await
58    }
59}
60
61/// An open handle to an "update" package.
62#[derive(Debug)]
63pub struct UpdatePackage {
64    proxy: fio::DirectoryProxy,
65}
66
67impl UpdatePackage {
68    /// Creates a new [`UpdatePackage`] with the given proxy.
69    pub fn new(proxy: fio::DirectoryProxy) -> Self {
70        Self { proxy }
71    }
72
73    /// Verifies that the package's name/variant is "update/0".
74    pub async fn verify_name(&self) -> Result<(), VerifyNameError> {
75        name::verify(&self.proxy).await
76    }
77
78    /// Loads the image packages manifest, or determines that it is not present.
79    pub async fn images_metadata(&self) -> Result<ImagesMetadata, ImagePackagesError> {
80        images::images_metadata(&self.proxy).await
81    }
82
83    /// Verifies the board file has the given `contents`.
84    pub async fn verify_board(&self, contents: &str) -> Result<(), VerifyBoardError> {
85        board::verify_board(&self.proxy, contents).await
86    }
87
88    /// Parses the update-mode file to obtain update mode. Returns `Ok(None)` if the update-mode
89    /// file is not present in the update package.
90    pub async fn update_mode(&self) -> Result<Option<UpdateMode>, ParseUpdateModeError> {
91        update_mode::update_mode(&self.proxy).await
92    }
93
94    /// Returns the list of package urls that go in the universe of this update package.
95    pub async fn packages(&self) -> Result<Vec<PinnedAbsolutePackageUrl>, ParsePackageError> {
96        packages::packages(&self.proxy).await
97    }
98
99    /// Returns the package hash of this update package.
100    pub async fn hash(&self) -> Result<Hash, HashError> {
101        hash::hash(&self.proxy).await
102    }
103
104    /// Returns the version of this update package.
105    pub async fn version(&self) -> Result<SystemVersion, ReadVersionError> {
106        version::read_version(&self.proxy).await
107    }
108
109    /// Parses the epoch.json file to obtain the epoch. Returns `Ok(None)` if the epoch.json file
110    /// is not present in the update package.
111    pub async fn epoch(&self) -> Result<Option<u64>, ParseEpochError> {
112        epoch::epoch(&self.proxy).await
113    }
114}
115
116#[cfg(test)]
117struct TestUpdatePackage {
118    update_pkg: UpdatePackage,
119    temp_dir: tempfile::TempDir,
120}
121
122#[cfg(test)]
123impl TestUpdatePackage {
124    #[cfg(not(target_os = "fuchsia"))]
125    compile_error!(
126        "Building tests for non-fuchsia targets requires a library to serve a temp dir using the fidl_fuchsia_io::Directory protocol"
127    );
128
129    fn new() -> Self {
130        let temp_dir = tempfile::tempdir().expect("/tmp to exist");
131        let update_pkg_proxy = fuchsia_fs::directory::open_in_namespace(
132            temp_dir.path().to_str().unwrap(),
133            fio::PERM_READABLE,
134        )
135        .expect("temp dir to open");
136        Self { temp_dir, update_pkg: UpdatePackage::new(update_pkg_proxy) }
137    }
138
139    fn proxy(&self) -> &fio::DirectoryProxy {
140        &self.update_pkg.proxy
141    }
142
143    async fn add_file(self, path: impl AsRef<std::path::Path>, contents: impl AsRef<[u8]>) -> Self {
144        let path = path.as_ref();
145        match path.parent() {
146            Some(empty) if empty == std::path::Path::new("") => {}
147            None => {}
148            Some(parent) => std::fs::create_dir_all(self.temp_dir.path().join(parent)).unwrap(),
149        }
150        fuchsia_fs::file::write_in_namespace(
151            self.temp_dir.path().join(path).to_str().unwrap(),
152            contents,
153        )
154        .await
155        .expect("create test update package file");
156        self
157    }
158}
159
160#[cfg(test)]
161impl std::ops::Deref for TestUpdatePackage {
162    type Target = UpdatePackage;
163
164    fn deref(&self) -> &Self::Target {
165        &self.update_pkg
166    }
167}
168
169#[cfg(test)]
170mod tests {
171    use super::*;
172
173    #[fuchsia::test]
174    async fn lifecycle() {
175        let (proxy, _server_end) = fidl::endpoints::create_proxy::<fio::DirectoryMarker>();
176        UpdatePackage::new(proxy);
177    }
178}