blob: 92db65fc94269ce1a35a76dfc0b05ae8d34935a4 [file] [log] [blame]
// Copyright 2017 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 <lib/fdio/fd.h>
#include <lib/fdio/namespace.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
#include <cerrno>
#include <fbl/auto_lock.h>
#include <fbl/ref_ptr.h>
#include "../fdio_unistd.h"
#include "local-connection.h"
#include "local-filesystem.h"
zx::status<fdio_ptr> fdio_ns_open_root(fdio_ns_t* ns) { return ns->OpenRoot(); }
zx_status_t fdio_ns_set_root(fdio_ns_t* ns, fdio_t* io) { return ns->SetRoot(io); }
__BEGIN_CDECLS
__EXPORT
zx_status_t fdio_ns_connect(fdio_ns_t* ns, const char* path, uint32_t flags, zx_handle_t request) {
if (path == nullptr) {
return ZX_ERR_INVALID_ARGS;
}
fdio_internal::PathBuffer clean;
bool is_dir;
if (!fdio_internal::CleanPath(path, &clean, &is_dir)) {
return ZX_ERR_BAD_PATH;
}
auto remote = fidl::ServerEnd<fuchsia_io::Node>(zx::channel(request));
return ns->Connect(clean, static_cast<fuchsia_io::wire::OpenFlags>(flags), std::move(remote));
}
__EXPORT
zx_status_t fdio_ns_create(fdio_ns_t** out) {
// Create a ref-counted object, and leak the reference that is returned
// via the C API.
//
// This reference is reclaimed in fdio_ns_destroy.
fbl::RefPtr<fdio_namespace> ns = fdio_namespace::Create();
*out = fbl::ExportToRawPtr(&ns);
return ZX_OK;
}
__EXPORT
zx_status_t fdio_ns_destroy(fdio_ns_t* raw_ns) {
// This function reclaims a reference which was leaked in fdio_ns_create.
__UNUSED auto ns = fbl::ImportFromRawPtr<fdio_namespace>(raw_ns);
return ZX_OK;
}
__EXPORT
zx_status_t fdio_ns_bind(fdio_ns_t* ns, const char* path, zx_handle_t remote_raw) {
if (path == nullptr) {
return ZX_ERR_INVALID_ARGS;
}
fdio_internal::PathBuffer clean;
bool is_dir;
if (!fdio_internal::CleanPath(path, &clean, &is_dir)) {
return ZX_ERR_BAD_PATH;
}
auto remote = fidl::ClientEnd<fuchsia_io::Directory>(zx::channel(remote_raw));
return ns->Bind(clean, std::move(remote));
}
__EXPORT
zx_status_t fdio_ns_unbind(fdio_ns_t* ns, const char* path) {
if (path == nullptr) {
return ZX_ERR_INVALID_ARGS;
}
fdio_internal::PathBuffer clean;
bool is_dir;
if (!fdio_internal::CleanPath(path, &clean, &is_dir)) {
return ZX_ERR_BAD_PATH;
}
return ns->Unbind(clean);
}
__EXPORT
bool fdio_ns_is_bound(fdio_ns_t* ns, const char* path) {
if (path == nullptr) {
return false;
}
fdio_internal::PathBuffer clean;
bool is_dir;
if (!fdio_internal::CleanPath(path, &clean, &is_dir)) {
return false;
}
return ns->IsBound(clean);
}
__EXPORT
zx_status_t fdio_ns_bind_fd(fdio_ns_t* ns, const char* path, int fd) {
zx_handle_t handle = ZX_HANDLE_INVALID;
zx_status_t status = fdio_fd_clone(fd, &handle);
if (status != ZX_OK) {
return status;
}
return fdio_ns_bind(ns, path, handle);
}
__EXPORT
int fdio_ns_opendir(fdio_ns_t* ns) {
zx::status io = ns->OpenRoot();
if (io.is_error()) {
errno = ENOMEM;
return -1;
}
std::optional fd = bind_to_fd(io.value());
if (fd.has_value()) {
return fd.value();
}
return ERRNO(EMFILE);
}
__EXPORT
zx_status_t fdio_ns_chdir(fdio_ns_t* ns) {
zx::status io = ns->OpenRoot();
if (io.is_error()) {
return ZX_ERR_NO_MEMORY;
}
fdio_chdir(io.value(), "/");
return ZX_OK;
}
__EXPORT
zx_status_t fdio_ns_export(fdio_ns_t* ns, fdio_flat_namespace_t** out) { return ns->Export(out); }
__EXPORT
zx_status_t fdio_ns_export_root(fdio_flat_namespace_t** out) {
fbl::AutoLock lock(&fdio_lock);
return fdio_ns_export(fdio_root_ns, out);
}
__EXPORT
void fdio_ns_free_flat_ns(fdio_flat_namespace_t* ns) {
zx_handle_close_many(ns->handle, ns->count);
free(ns);
}
__END_CDECLS