blob: 9c91c335a1fa61852affa6262d20cd0b0d4c4600 [file] [log] [blame]
// Copyright 2016 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.
#include "garnet/bin/appmgr/root_loader.h"
#include <fcntl.h>
#include <utility>
#include "garnet/bin/appmgr/url_resolver.h"
#include "lib/fidl/cpp/optional.h"
#include "lib/fsl/io/fd.h"
#include "lib/fsl/vmo/file.h"
#include "lib/fxl/files/unique_fd.h"
#include "lib/fxl/logging.h"
#include "lib/fxl/strings/concatenate.h"
namespace component {
RootLoader::RootLoader() = default;
RootLoader::~RootLoader() = default;
void RootLoader::LoadComponent(fidl::StringPtr url,
LoadComponentCallback callback) {
std::string path = GetPathFromURL(url);
if (path.empty()) {
// TODO(abarth): Support URL schemes other than file:// by querying the host
// for an application runner.
FXL_LOG(ERROR) << "Cannot load " << url
<< " because the scheme is not supported.";
} else {
fxl::UniqueFD fd(open(path.c_str(), O_RDONLY));
if (!fd.is_valid() && path[0] != '/') {
if (path.find('/') == std::string::npos) {
// TODO(abarth): We're currently hardcoding version 0 of the package,
// but we'll eventually need to do something smarter.
std::string pkg_path =
fxl::Concatenate({"/pkgfs/packages/", path, "/0"});
fd.reset(open(pkg_path.c_str(), O_DIRECTORY | O_RDONLY));
if (fd.is_valid()) {
zx::channel directory = fsl::CloneChannelFromFileDescriptor(fd.get());
if (directory) {
fuchsia::sys::Package package;
package.directory = std::move(directory);
package.resolved_url = fxl::Concatenate({"file://", pkg_path});
callback(fidl::MakeOptional(std::move(package)));
return;
}
}
}
for (const auto& entry : {"/system/bin", "/system/pkgs"}) {
std::string qualified_path =
fxl::Concatenate({fxl::StringView(entry), "/", path});
fd.reset(open(qualified_path.c_str(), O_RDONLY));
if (fd.is_valid()) {
path = qualified_path;
break;
}
}
}
fsl::SizedVmo data;
if (fd.is_valid() && fsl::VmoFromFd(std::move(fd), &data)) {
fuchsia::sys::Package package;
package.data = fidl::MakeOptional(std::move(data).ToTransport());
package.resolved_url = fxl::Concatenate({"file://", path});
callback(fidl::MakeOptional(std::move(package)));
return;
}
FXL_LOG(ERROR) << "Could not load url: " << url;
}
callback(nullptr);
}
void RootLoader::AddBinding(
fidl::InterfaceRequest<fuchsia::sys::Loader> request) {
bindings_.AddBinding(this, std::move(request));
}
} // namespace component