// 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 "zxio.h"

#include <fuchsia/hardware/pty/llcpp/fidl.h>
#include <fuchsia/io/llcpp/fidl.h>
#include <lib/fdio/fdio.h>
#include <lib/fdio/io.h>
#include <lib/zxio/inception.h>
#include <lib/zxio/null.h>
#include <lib/zxio/zxio.h>
#include <poll.h>
#include <stdarg.h>
#include <sys/ioctl.h>
#include <zircon/device/vfs.h>
#include <zircon/rights.h>
#include <zircon/syscalls.h>
#include <zircon/types.h>

#include <fbl/auto_lock.h>

#include "fdio_unistd.h"

namespace fio = fuchsia_io;
namespace fpty = fuchsia_hardware_pty;

namespace fdio_internal {

zx::status<fdio_ptr> zxio::create() {
  fdio_ptr io = fbl::MakeRefCounted<zxio>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zxio_null_init(&io->zxio_storage().io);
  return zx::ok(io);
}

zx_status_t zxio::close() { return zxio_close(&zxio_storage().io); }

zx_status_t zxio::clone(zx_handle_t* out_handle) {
  return zxio_clone(&zxio_storage().io, out_handle);
}

zx_status_t zxio::unwrap(zx_handle_t* out_handle) {
  return zxio_release(&zxio_storage().io, out_handle);
}

void zxio::wait_begin(uint32_t events, zx_handle_t* out_handle, zx_signals_t* out_signals) {
  return wait_begin_inner(events, ZXIO_SIGNAL_NONE, out_handle, out_signals);
}

// TODO(fxbug.dev/45813): This is mainly used by pipes. Consider merging this with the
// POSIX-to-zxio signal translation in |remote::wait_begin|.
// TODO(fxbug.dev/47132): Do not change the signal mapping here and in |wait_end|
// until linked issue is resolved.
void zxio::wait_begin_inner(uint32_t events, zx_signals_t signals, zx_handle_t* out_handle,
                            zx_signals_t* out_signals) {
  if (events & POLLIN) {
    signals |= ZXIO_SIGNAL_READABLE | ZXIO_SIGNAL_PEER_CLOSED | ZXIO_SIGNAL_READ_DISABLED;
  }
  if (events & POLLOUT) {
    signals |= ZXIO_SIGNAL_WRITABLE | ZXIO_SIGNAL_WRITE_DISABLED;
  }
  if (events & POLLRDHUP) {
    signals |= ZXIO_SIGNAL_READ_DISABLED | ZXIO_SIGNAL_PEER_CLOSED;
  }
  zxio_wait_begin(&zxio_storage().io, signals, out_handle, out_signals);
}

void zxio::wait_end(zx_signals_t signals, uint32_t* out_events) {
  return wait_end_inner(signals, out_events, nullptr);
}

void zxio::wait_end_inner(zx_signals_t signals, uint32_t* out_events, zx_signals_t* out_signals) {
  zxio_signals_t zxio_signals;
  zxio_wait_end(&zxio_storage().io, signals, &zxio_signals);
  if (out_signals) {
    *out_signals = zxio_signals;
  }

  uint32_t events = 0;
  if (zxio_signals & (ZXIO_SIGNAL_READABLE | ZXIO_SIGNAL_PEER_CLOSED | ZXIO_SIGNAL_READ_DISABLED)) {
    events |= POLLIN;
  }
  if (zxio_signals & (ZXIO_SIGNAL_WRITABLE | ZXIO_SIGNAL_WRITE_DISABLED)) {
    events |= POLLOUT;
  }
  if (zxio_signals & (ZXIO_SIGNAL_READ_DISABLED | ZXIO_SIGNAL_PEER_CLOSED)) {
    events |= POLLRDHUP;
  }
  *out_events = events;
}

zx_status_t zxio::get_token(zx_handle_t* out) { return zxio_token_get(&zxio_storage().io, out); }

zx_status_t zxio::get_attr(zxio_node_attributes_t* out) {
  return zxio_attr_get(&zxio_storage().io, out);
}

zx_status_t zxio::set_attr(const zxio_node_attributes_t* attr) {
  return zxio_attr_set(&zxio_storage().io, attr);
}

zx_status_t zxio::dirent_iterator_init(zxio_dirent_iterator_t* iterator, zxio_t* directory) {
  return zxio_dirent_iterator_init(iterator, directory);
}

zx_status_t zxio::dirent_iterator_next(zxio_dirent_iterator_t* iterator,
                                       zxio_dirent_t** out_entry) {
  return zxio_dirent_iterator_next(iterator, out_entry);
}

void zxio::dirent_iterator_destroy(zxio_dirent_iterator_t* iterator) {
  return zxio_dirent_iterator_destroy(iterator);
}

zx_status_t zxio::unlink(const char* path, size_t len) {
  return zxio_unlink(&zxio_storage().io, path);
}

zx_status_t zxio::truncate(off_t off) { return zxio_truncate(&zxio_storage().io, off); }

zx_status_t zxio::rename(const char* src, size_t srclen, zx_handle_t dst_token, const char* dst,
                         size_t dstlen) {
  return zxio_rename(&zxio_storage().io, src, dst_token, dst);
}

zx_status_t zxio::link(const char* src, size_t srclen, zx_handle_t dst_token, const char* dst,
                       size_t dstlen) {
  return zxio_link(&zxio_storage().io, src, dst_token, dst);
}

zx_status_t zxio::get_flags(uint32_t* out_flags) {
  return zxio_flags_get(&zxio_storage().io, out_flags);
}

zx_status_t zxio::set_flags(uint32_t flags) { return zxio_flags_set(&zxio_storage().io, flags); }

zx_status_t zxio::recvmsg_inner(struct msghdr* msg, int flags, size_t* out_actual) {
  zxio_flags_t zxio_flags = 0;
  if (flags & MSG_PEEK) {
    zxio_flags |= ZXIO_PEEK;
    flags &= ~MSG_PEEK;
  }
  if (flags) {
    // TODO(https://fxbug.dev/67925): support MSG_OOB
    return ZX_ERR_NOT_SUPPORTED;
  }

  // Variable length arrays have to have nonzero sizes, so we can't allocate a zx_iov for an empty
  // io vector. Instead, we can ask to read zero entries with a null vector.
  if (msg->msg_iovlen == 0) {
    return zxio_readv(&zxio_storage().io, nullptr, 0, zxio_flags, out_actual);
  }

  zx_iovec_t zx_iov[msg->msg_iovlen];
  for (int i = 0; i < msg->msg_iovlen; ++i) {
    auto const& iov = msg->msg_iov[i];
    zx_iov[i] = {
        .buffer = iov.iov_base,
        .capacity = iov.iov_len,
    };
  }

  return zxio_readv(&zxio_storage().io, zx_iov, msg->msg_iovlen, zxio_flags, out_actual);
}

zx_status_t zxio::sendmsg_inner(const struct msghdr* msg, int flags, size_t* out_actual) {
  if (flags) {
    // TODO(https://fxbug.dev/67925): support MSG_NOSIGNAL
    // TODO(https://fxbug.dev/67925): support MSG_OOB
    return ZX_ERR_NOT_SUPPORTED;
  }

  // Variable length arrays have to have nonzero sizes, so we can't allocate a zx_iov for an empty
  // io vector. Instead, we can ask to write zero entries with a null vector.
  if (msg->msg_iovlen == 0) {
    return zxio_writev(&zxio_storage().io, nullptr, 0, 0, out_actual);
  }

  zx_iovec_t zx_iov[msg->msg_iovlen];
  for (int i = 0; i < msg->msg_iovlen; ++i) {
    zx_iov[i] = {
        .buffer = msg->msg_iov[i].iov_base,
        .capacity = msg->msg_iov[i].iov_len,
    };
  }
  return zxio_writev(&zxio_storage().io, zx_iov, msg->msg_iovlen, 0, out_actual);
}

zx_status_t zxio::recvmsg(struct msghdr* msg, int flags, size_t* out_actual, int16_t* out_code) {
  *out_code = 0;
  return recvmsg_inner(msg, flags, out_actual);
}

zx_status_t zxio::sendmsg(const struct msghdr* msg, int flags, size_t* out_actual,
                          int16_t* out_code) {
  *out_code = 0;
  return sendmsg_inner(msg, flags, out_actual);
}

zx::status<fdio_ptr> remote::open(const char* path, uint32_t flags, uint32_t mode) {
  size_t length;
  zx_status_t status = fdio_validate_path(path, &length);
  if (status != ZX_OK) {
    return zx::error(status);
  }

  zx::status endpoints = fidl::CreateEndpoints<fio::Node>();
  if (endpoints.is_error()) {
    return endpoints.take_error();
  }

  status = zxio_open_async(&zxio_storage().io, flags, mode, path, length,
                           endpoints->server.channel().release());
  if (status != ZX_OK) {
    return zx::error(status);
  }

  if (flags & ZX_FS_FLAG_DESCRIBE) {
    return fdio::create_with_on_open(std::move(endpoints->client));
  }

  return remote::create(std::move(endpoints->client), zx::eventpair{});
}

zx_status_t remote::borrow_channel(zx_handle_t* out_borrowed) {
  *out_borrowed = zxio_remote().control;
  return ZX_OK;
}

void remote::wait_begin(uint32_t events, zx_handle_t* handle, zx_signals_t* out_signals) {
  // POLLERR is always detected.
  events |= POLLERR;

  zxio_signals_t signals = ZXIO_SIGNAL_NONE;
  if (events & POLLIN) {
    signals |= ZXIO_SIGNAL_READABLE;
  }
  if (events & POLLPRI) {
    signals |= ZXIO_SIGNAL_OUT_OF_BAND;
  }
  if (events & POLLOUT) {
    signals |= ZXIO_SIGNAL_WRITABLE;
  }
  if (events & POLLERR) {
    signals |= ZXIO_SIGNAL_ERROR;
  }
  if (events & POLLHUP) {
    signals |= ZXIO_SIGNAL_PEER_CLOSED;
  }
  if (events & POLLRDHUP) {
    signals |= ZXIO_SIGNAL_READ_DISABLED;
  }
  zxio_wait_begin(&zxio_storage().io, signals, handle, out_signals);
}

void remote::wait_end(zx_signals_t signals, uint32_t* out_events) {
  zxio_signals_t zxio_signals = 0;
  zxio_wait_end(&zxio_storage().io, signals, &zxio_signals);

  uint32_t events = 0;
  if (zxio_signals & ZXIO_SIGNAL_READABLE) {
    events |= POLLIN;
  }
  if (zxio_signals & ZXIO_SIGNAL_OUT_OF_BAND) {
    events |= POLLPRI;
  }
  if (zxio_signals & ZXIO_SIGNAL_WRITABLE) {
    events |= POLLOUT;
  }
  if (zxio_signals & ZXIO_SIGNAL_ERROR) {
    events |= POLLERR;
  }
  if (zxio_signals & ZXIO_SIGNAL_PEER_CLOSED) {
    events |= POLLHUP;
  }
  if (zxio_signals & ZXIO_SIGNAL_READ_DISABLED) {
    events |= POLLRDHUP;
  }
  *out_events = events;
}

zx::status<fdio_ptr> remote::create(fidl::ClientEnd<fuchsia_io::Node> node, zx::eventpair event) {
  fdio_ptr io = fbl::MakeRefCounted<remote>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status =
      zxio_remote_init(&io->zxio_storage(), node.channel().release(), event.release());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

zx::status<fdio_ptr> remote::create(fidl::ClientEnd<fio::File> file, zx::event event,
                                    zx::stream stream) {
  fdio_ptr io = fbl::MakeRefCounted<remote>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status = zxio_file_init(&io->zxio_storage(), file.channel().release(),
                                      event.release(), stream.release());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

zx::status<fdio_ptr> remote::create(zx::vmo vmo, zx::stream stream) {
  fdio_ptr io = fbl::MakeRefCounted<remote>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status = zxio_vmo_init(&io->zxio_storage(), std::move(vmo), std::move(stream));
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

zx::status<fdio_ptr> remote::create(fidl::ClientEnd<fio::File> file, zx::vmo vmo, zx_off_t offset,
                                    zx_off_t length, zx_off_t seek) {
  // NB: vmofile doesn't support some of the operations, but it can fail in zxio.
  fdio_ptr io = fbl::MakeRefCounted<remote>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status = zxio_vmofile_init(&io->zxio_storage(), fidl::BindSyncClient(std::move(file)),
                                         std::move(vmo), offset, length, seek);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

zx::status<fdio_ptr> dir::create(fidl::ClientEnd<fio::Directory> directory) {
  fdio_ptr io = fbl::MakeRefCounted<dir>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status = zxio_dir_init(&io->zxio_storage(), directory.channel().release());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

uint32_t dir::convert_to_posix_mode(zxio_node_protocols_t protocols, zxio_abilities_t abilities) {
  return zxio_node_protocols_to_posix_type(protocols) |
         zxio_abilities_to_posix_permissions_for_directory(abilities);
}

zx::status<fdio_ptr> pty::create(fidl::ClientEnd<fpty::Device> device, zx::eventpair event) {
  fdio_ptr io = fbl::MakeRefCounted<pty>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_status_t status =
      zxio_remote_init(&io->zxio_storage(), device.channel().release(), event.release());
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

Errno pty::posix_ioctl(int request, va_list va) {
  switch (request) {
    case TIOCGWINSZ: {
      fidl::UnownedClientEnd<fpty::Device> device(zxio_remote().control);
      if (!device.is_valid()) {
        return Errno(ENOTTY);
      }

      auto result = fidl::WireCall(device).GetWindowSize();
      if (result.status() != ZX_OK || result->status != ZX_OK) {
        return Errno(ENOTTY);
      }

      struct winsize size = {
          .ws_row = static_cast<uint16_t>(result->size.height),
          .ws_col = static_cast<uint16_t>(result->size.width),
      };
      struct winsize* out_size = va_arg(va, struct winsize*);
      *out_size = size;
      return Errno(Errno::Ok);
    }
    case TIOCSWINSZ: {
      fidl::UnownedClientEnd<fpty::Device> device(zxio_remote().control);
      if (!device.is_valid()) {
        return Errno(ENOTTY);
      }

      const struct winsize* in_size = va_arg(va, const struct winsize*);
      fpty::wire::WindowSize size = {};
      size.width = in_size->ws_col;
      size.height = in_size->ws_row;

      auto result = fidl::WireCall(device).SetWindowSize(size);
      if (result.status() != ZX_OK || result->status != ZX_OK) {
        return Errno(ENOTTY);
      }
      return Errno(Errno::Ok);
    }
    default:
      return Errno(ENOTTY);
  }
}

zx::status<fdio_ptr> pipe::create(zx::socket socket) {
  fdio_ptr io = fbl::MakeRefCounted<pipe>();
  if (io == nullptr) {
    return zx::error(ZX_ERR_NO_MEMORY);
  }
  zx_info_socket_t info;
  zx_status_t status = socket.get_info(ZX_INFO_SOCKET, &info, sizeof(info), nullptr, nullptr);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  status = zxio_pipe_init(&io->zxio_storage(), std::move(socket), info);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  return zx::ok(io);
}

zx::status<std::pair<fdio_ptr, fdio_ptr>> pipe::create_pair(uint32_t options) {
  zx::socket h0, h1;
  zx_status_t status = zx::socket::create(options, &h0, &h1);
  if (status != ZX_OK) {
    return zx::error(status);
  }
  zx::status a = pipe::create(std::move(h0));
  if (a.is_error()) {
    return a.take_error();
  }
  zx::status b = pipe::create(std::move(h1));
  if (b.is_error()) {
    return b.take_error();
  }
  return zx::ok(std::make_pair(a.value(), b.value()));
}

Errno pipe::posix_ioctl(int request, va_list va) {
  return posix_ioctl_inner(zxio_pipe().socket, request, va);
}

Errno pipe::posix_ioctl_inner(const zx::socket& socket, int request, va_list va) {
  switch (request) {
    case FIONREAD: {
      zx_info_socket_t info;
      memset(&info, 0, sizeof(info));
      zx_status_t status = socket.get_info(ZX_INFO_SOCKET, &info, sizeof(info), nullptr, nullptr);
      if (status != ZX_OK) {
        return Errno(fdio_status_to_errno(status));
      }
      size_t available = info.rx_buf_available;
      if (available > INT_MAX) {
        available = INT_MAX;
      }
      int* actual = va_arg(va, int*);
      *actual = static_cast<int>(available);
      return Errno(Errno::Ok);
    }
    default:
      return Errno(ENOTTY);
  }
}

zx_status_t pipe::shutdown(int how, int16_t* out_code) {
  *out_code = 0;
  return shutdown_inner(zxio_pipe().socket, how);
}

zx_status_t pipe::shutdown_inner(const zx::socket& socket, int how) {
  uint32_t options;
  switch (how) {
    case SHUT_RD:
      options = ZX_SOCKET_SHUTDOWN_READ;
      break;
    case SHUT_WR:
      options = ZX_SOCKET_SHUTDOWN_WRITE;
      break;
    case SHUT_RDWR:
      options = ZX_SOCKET_SHUTDOWN_READ | ZX_SOCKET_SHUTDOWN_WRITE;
      break;
  }
  return socket.shutdown(options);
}

}  // namespace fdio_internal
