blob: bc3a79579202bf1bd65cdf163616b303f7668709 [file] [log] [blame]
// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
use failure::Error;
use fidl::endpoints::{ClientEnd, RequestStream, ServerEnd};
use fidl_fuchsia_io::{self, DirectoryMarker, DirectoryProxy};
use fidl_fuchsia_pkg::{BlobFetcherMarker, PackageCacheRequest, PackageCacheRequestStream};
use fidl_fuchsia_pkg_ext::BlobId;
use fuchsia_async as fasync;
use fuchsia_syslog::{fx_log_err, fx_log_info, fx_log_warn};
use fuchsia_zircon::Status;
use futures::prelude::*;
pub async fn serve(pkgfs: DirectoryProxy, chan: fasync::Channel) -> Result<(), Error> {
let mut stream = PackageCacheRequestStream::from_channel(chan);
while let Some(event) = await!(stream.try_next())? {
match event {
PackageCacheRequest::Fetch {
meta_far_blob_id,
meta_far_length,
selectors,
fetcher,
dir,
responder,
} => {
let status = await!(fetch(
&pkgfs,
meta_far_blob_id.into(),
meta_far_length,
selectors,
fetcher,
dir
));
responder.send(Status::from(status).into_raw())?;
}
PackageCacheRequest::Open {
meta_far_blob_id,
selectors,
dir,
responder,
} => {
let status = await!(open(&pkgfs, BlobId::from(meta_far_blob_id), selectors, dir));
responder.send(Status::from(status).into_raw())?;
}
}
}
Ok(())
}
/// Fetch a package, and optionally mount it.
///
/// TODO: implement this method. This stub can't simply proxy to amber for now, since it doesn't
/// know the name of the package, and amber needs it to lookup the package in its TUF repo.
async fn fetch<'a>(
pkgfs: &'a DirectoryProxy, meta_far_blob_id: BlobId, _meta_far_length: u64,
selectors: Vec<String>, _fetcher: ClientEnd<BlobFetcherMarker>,
dir_request: Option<ServerEnd<DirectoryMarker>>,
) -> Result<(), Status> {
fx_log_info!(
"fetching {:?} with the selectors {:?}",
meta_far_blob_id,
selectors
);
if let Some(dir_request) = dir_request {
await!(open(
pkgfs,
meta_far_blob_id,
selectors.clone(),
dir_request
))?;
Ok(())
} else {
Err(Status::NOT_SUPPORTED)
}
}
/// Open a package directory.
async fn open<'a>(
pkgfs: &'a DirectoryProxy, meta_far_blob_id: BlobId, selectors: Vec<String>,
dir_request: ServerEnd<DirectoryMarker>,
) -> Result<(), Status> {
fx_log_info!(
"opening {:?} with the selectors {:?}",
meta_far_blob_id,
selectors
);
// FIXME: need to implement selectors.
if !selectors.is_empty() {
fx_log_warn!("resolve does not support selectors yet");
}
// FIXME: this is a bit of a hack but there isn't a formal way to convert a Directory request
// into a Node request.
let node_request = ServerEnd::new(dir_request.into_channel());
let flags = fidl_fuchsia_io::OPEN_RIGHT_READABLE | fidl_fuchsia_io::OPEN_FLAG_DIRECTORY;
pkgfs
.open(flags, 0, &meta_far_blob_id.to_string(), node_request)
.map_err(|err| {
fx_log_err!("error opening {}: {:?}", meta_far_blob_id, err);
Status::INTERNAL
})?;
Ok(())
}