blob: ddb3a6240be819651f3255ebf5dd181f1637785a [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 <errno.h>
#include <fcntl.h>
#include <fbl/ref_counted.h>
#include <fbl/ref_ptr.h>
#include <lib/fdio/namespace.h>
#include <lib/fdio/fd.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/directory.h>
#include <lib/zx/channel.h>
#include <zircon/types.h>
#include <zircon/processargs.h>
#include <zircon/device/vfs.h>
#include "local-connection.h"
#include "local-filesystem.h"
#include "local-vnode.h"
__BEGIN_CDECLS
__EXPORT
zx_status_t fdio_ns_connect(fdio_ns_t* ns, const char* path, uint32_t flags,
zx_handle_t raw_handle) {
zx::channel channel(raw_handle);
return ns->Connect(path, flags, std::move(channel));
}
__EXPORT
zx_status_t fdio_ns_open(fdio_ns_t* ns, const char* path, uint32_t flags, zx_handle_t* out) {
zx::channel client, server;
if (zx::channel::create(0, &client, &server) != ZX_OK) {
return ZX_ERR_INTERNAL;
}
zx_status_t status = fdio_ns_connect(ns, path, flags, server.release());
if (status != ZX_OK) {
return status;
}
*out = client.release();
return ZX_OK;
}
__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 = ns.leak_ref();
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::internal::MakeRefPtrNoAdopt<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) {
zx::channel remote(remote_raw);
return ns->Bind(path, std::move(remote));
}
__EXPORT
zx_status_t fdio_ns_unbind(fdio_ns_t* ns, const char* path) {
return ns->Unbind(path);
}
__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);
}
fdio_t* fdio_ns_open_root(fdio_ns_t* ns) {
return ns->OpenRoot();
}
__EXPORT
int fdio_ns_opendir(fdio_ns_t* ns) {
fdio_t* io = ns->OpenRoot();
if (io == nullptr) {
errno = ENOMEM;
return -1;
}
int fd = fdio_bind_to_fd(io, -1, 0);
if (fd < 0) {
fdio_release(io);
errno = ENOMEM;
}
return fd;
}
__EXPORT
zx_status_t fdio_ns_chdir(fdio_ns_t* ns) {
fdio_t* io = ns->OpenRoot();
if (io == nullptr) {
return ZX_ERR_NO_MEMORY;
}
fdio_chdir(io, "/");
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) {
zx_status_t status;
mtx_lock(&fdio_lock);
if (fdio_root_ns == nullptr) {
status = ZX_ERR_NOT_FOUND;
} else {
status = fdio_ns_export(fdio_root_ns, out);
}
mtx_unlock(&fdio_lock);
return status;
}
__EXPORT
void fdio_ns_free_flat_ns(fdio_flat_namespace_t* ns) {
zx_handle_close_many(ns->handle, ns->count);
free(ns);
}
__END_CDECLS