update_package/
image.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
5use thiserror::Error;
6use zx_status::Status;
7
8#[cfg(target_os = "fuchsia")]
9use {fidl_fuchsia_io as fio, fidl_fuchsia_mem as fmem};
10
11/// An error encountered while opening an image.
12#[derive(Debug, Error)]
13#[allow(missing_docs)]
14pub enum OpenImageError {
15    #[error("while opening the file path {path:?}")]
16    OpenPath {
17        path: String,
18        #[source]
19        err: fuchsia_fs::node::OpenError,
20    },
21
22    #[error("while calling get_backing_memory for {path:?}")]
23    FidlGetBackingMemory {
24        path: String,
25        #[source]
26        err: fidl::Error,
27    },
28
29    #[error("while obtaining vmo of file for {path:?}: {status}")]
30    GetBackingMemory { path: String, status: Status },
31
32    #[error("while converting vmo to a resizable vmo for {path:?}: {status}")]
33    CloneBuffer { path: String, status: Status },
34}
35
36#[cfg(target_os = "fuchsia")]
37/// Opens the given `path` as a resizable VMO buffer and returns the buffer on success.
38pub(crate) async fn open_from_path(
39    proxy: &fio::DirectoryProxy,
40    path: &str,
41) -> Result<fmem::Buffer, OpenImageError> {
42    let file = fuchsia_fs::directory::open_file(proxy, path, fio::PERM_READABLE)
43        .await
44        .map_err(|err| OpenImageError::OpenPath { path: path.to_string(), err })?;
45
46    let vmo = file
47        .get_backing_memory(fio::VmoFlags::READ)
48        .await
49        .map_err(|err| OpenImageError::FidlGetBackingMemory { path: path.to_string(), err })?
50        .map_err(Status::from_raw)
51        .map_err(|status| OpenImageError::GetBackingMemory { path: path.to_string(), status })?;
52
53    let size = vmo
54        .get_content_size()
55        .map_err(|status| OpenImageError::GetBackingMemory { path: path.to_string(), status })?;
56
57    // The paver service requires VMOs that are resizable, and blobfs does not give out resizable
58    // VMOs. Fortunately, a copy-on-write child clone of the vmo can be made resizable.
59    let vmo = vmo
60        .create_child(
61            zx::VmoChildOptions::SNAPSHOT_AT_LEAST_ON_WRITE | zx::VmoChildOptions::RESIZABLE,
62            0,
63            size,
64        )
65        .map_err(|status| OpenImageError::CloneBuffer { path: path.to_string(), status })?;
66
67    Ok(fmem::Buffer { vmo, size })
68}