blob: ae473833de2b4013ab892c0c9c3abd3a12d71957 [file] [log] [blame]
// Copyright 2019 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/fdio.h>
#include <lib/zxio/ops.h>
#include <zircon/errors.h>
#include <variant>
#include <fbl/auto_lock.h>
#include "sdk/lib/fdio/fdio_unistd.h"
#include "sdk/lib/fdio/internal.h"
#include "sdk/lib/fdio/zxio.h"
__EXPORT
fdio_t* fdio_default_create(void) {
zx::result io = fdio_internal::zxio::create();
if (io.is_error()) {
return nullptr;
}
std::variant reference = GetLastReference(std::move(io.value()));
return std::get<fdio::last_reference>(reference).ExportToRawPtr();
}
__EXPORT
fdio_t* fdio_null_create(void) {
zx::result io = fdio_internal::zxio::create_null();
if (io.is_error()) {
return nullptr;
}
std::variant reference = GetLastReference(std::move(io.value()));
return std::get<fdio::last_reference>(reference).ExportToRawPtr();
}
__EXPORT
zx_status_t fdio_create(zx_handle_t h, fdio_t** out_io) {
zx::result io = fdio::create(zx::handle(h));
if (io.is_ok()) {
std::variant reference = GetLastReference(std::move(io.value()));
*out_io = std::get<fdio::last_reference>(reference).ExportToRawPtr();
}
return io.status_value();
}
__EXPORT
int fdio_fd_create_null(void) {
zx::result io = fdio_internal::zxio::create_null();
if (io.is_error()) {
return ERROR(io.status_value());
}
std::optional fd = bind_to_fd(io.value());
if (fd.has_value()) {
return fd.value();
}
return ERRNO(EMFILE);
}
__EXPORT
extern "C" zxio_t* fdio_get_zxio(fdio_t* io) { return &io->zxio_storage().io; }
__EXPORT
int fdio_bind_to_fd(fdio_t* io, int fd, int starting_fd) {
fdio_ptr owned = fbl::ImportFromRawPtr(io);
// If we are not given an |fd|, the |starting_fd| must be non-negative.
if ((fd < 0 && starting_fd < 0) || fd >= FDIO_MAX_FD) {
return ERRNO(EINVAL);
}
// Don't release under lock.
fdio_ptr io_to_close = nullptr;
{
fbl::AutoLock lock(&fdio_lock);
if (fd < 0) {
// A negative fd implies that any free fd value can be used
// TODO: bitmap, ffs, etc
for (fd = starting_fd; fd < FDIO_MAX_FD; fd++) {
if (fdio_fdtab[fd].try_set(owned)) {
return fd;
}
}
return ERRNO(EMFILE);
}
io_to_close = fdio_fdtab[fd].replace(owned);
}
return fd;
}
__EXPORT
zx_status_t fdio_unbind_from_fd(int fd, fdio_t** out) {
fdio_ptr io = unbind_from_fd(fd);
if (io == nullptr) {
return ZX_ERR_INVALID_ARGS;
}
std::variant reference = GetLastReference(std::move(io));
auto* ptr = std::get_if<fdio::last_reference>(&reference);
if (ptr) {
*out = ptr->ExportToRawPtr();
return ZX_OK;
}
return ZX_ERR_UNAVAILABLE;
}
__EXPORT
zx_status_t fdio_get_service_handle(int fd, zx_handle_t* out) { return fdio_fd_transfer(fd, out); }
__EXPORT
fdio_t* fdio_zxio_create(zxio_storage_t** out_storage) {
zx::result io = fdio_internal::zxio::create();
if (io.is_error()) {
return nullptr;
}
*out_storage = &io->zxio_storage();
std::variant reference = GetLastReference(std::move(io.value()));
return std::get<fdio::last_reference>(reference).ExportToRawPtr();
}
__EXPORT
size_t fdio_currently_allocated_fd_count(void) {
size_t count = 0;
fbl::AutoLock lock(&fdio_lock);
for (size_t fd = 0; fd < FDIO_MAX_FD; ++fd) {
if (fdio_fdtab[fd].allocated()) {
++count;
}
}
return count;
}