blob: c4c08b81bd85381dec862c28ad3dcd83efe68049 [file] [log] [blame] [edit]
// 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.
#include "garnet/bin/appmgr/realm_hub_holder.h"
#include "garnet/bin/appmgr/hub_holder.h"
#include "garnet/bin/appmgr/application_controller_impl.h"
#include "garnet/bin/appmgr/realm.h"
#include <fbl/ref_ptr.h>
#include <fs/pseudo-dir.h>
#include <zircon/types.h>
namespace component {
RealmHubHolder::RealmHubHolder(fbl::RefPtr<fs::PseudoDir> root)
: HubHolder(root) {}
zx_status_t RealmHubHolder::AddRealm(const Realm* realm) {
bool child_found = false;
fbl::RefPtr<fs::Vnode> realm_instance_vnode;
fbl::RefPtr<fs::PseudoDir> realm_instance_dir;
if (!realm_dir_) {
realm_dir_ = fbl::AdoptRef(new fs::PseudoDir());
AddEntry("r", realm_dir_);
} else {
zx_status_t status =
realm_dir_->Lookup(&realm_instance_vnode, realm->label());
child_found = (status != ZX_ERR_NOT_FOUND);
}
if (!child_found) {
realm_instance_dir = fbl::AdoptRef(new fs::PseudoDir());
realm_dir_->AddEntry(realm->label(), realm_instance_dir);
} else {
realm_instance_dir = fbl::RefPtr<fs::PseudoDir>(
static_cast<fs::PseudoDir*>(realm_instance_vnode.get()));
}
return realm_instance_dir->AddEntry(realm->koid(), realm->hub_dir());
}
zx_status_t RealmHubHolder::RemoveRealm(const Realm* realm) {
fbl::RefPtr<fs::Vnode> realm_instance_vnode;
zx_status_t status =
realm_dir_->Lookup(&realm_instance_vnode, realm->label());
if (status == ZX_OK) {
auto realm_instance_dir = fbl::RefPtr<fs::PseudoDir>(
static_cast<fs::PseudoDir*>(realm_instance_vnode.get()));
status = realm_instance_dir->RemoveEntry(realm->koid());
if (realm_instance_dir->IsEmpty()) {
realm_dir_->RemoveEntry(realm->label());
}
return status;
}
return ZX_ERR_NOT_FOUND;
}
zx_status_t RealmHubHolder::AddComponent(
const ApplicationControllerImpl* application) {
bool child_found = false;
fbl::RefPtr<fs::PseudoDir> component_instance_dir;
fbl::RefPtr<fs::Vnode> component_instance_vnode;
if (!component_dir_) {
component_dir_ = fbl::AdoptRef(new fs::PseudoDir());
AddEntry("c", component_dir_);
} else {
zx_status_t status =
component_dir_->Lookup(&component_instance_vnode, application->label());
child_found = (status != ZX_ERR_NOT_FOUND);
}
if (!child_found) {
component_instance_dir = fbl::AdoptRef(new fs::PseudoDir());
component_dir_->AddEntry(application->label(), component_instance_dir);
} else {
component_instance_dir = fbl::RefPtr<fs::PseudoDir>(
static_cast<fs::PseudoDir*>(component_instance_vnode.get()));
}
return component_instance_dir->AddEntry(application->koid(),
application->hub_dir());
}
zx_status_t RealmHubHolder::RemoveComponent(
const ApplicationControllerImpl* application) {
fbl::RefPtr<fs::Vnode> component_instance_vnode;
zx_status_t status =
component_dir_->Lookup(&component_instance_vnode, application->label());
if (status == ZX_OK) {
auto component_instance_dir = fbl::RefPtr<fs::PseudoDir>(
static_cast<fs::PseudoDir*>(component_instance_vnode.get()));
status = component_instance_dir->RemoveEntry(application->koid());
if (component_instance_dir->IsEmpty()) {
component_dir_->RemoveEntry(application->label());
}
return status;
}
return ZX_ERR_NOT_FOUND;
}
RealmHubHolder::~RealmHubHolder() = default;
} // namespace component