// 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 <errno.h>
#include <fcntl.h>
#include <libgen.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include <wordexp.h>

#include <filesystem>

#include "platform_interface.h"
#include "src/virtualization/lib/guest_interaction/common.h"

int32_t PosixPlatform::OpenFile(std::string file_path, FileOpenMode mode) {
  int32_t flags = O_NONBLOCK;
  if (mode == WRITE) {
    flags |= O_WRONLY | O_TRUNC | O_CREAT;
  } else {
    flags |= O_RDONLY;
  }

  int32_t fd = open(file_path.c_str(), flags);
  if (fd < 0) {
    return -errno;
  }
  return fd;
}

int32_t PosixPlatform::WriteFile(int32_t fd, const char* file_contents, uint32_t write_size) {
  ssize_t bytes_written = 0;

  while (bytes_written < write_size) {
    ssize_t curr_bytes_written =
        write(fd, file_contents + bytes_written, write_size - bytes_written);
    if (curr_bytes_written < 0) {
      return -errno;
    }

    bytes_written += curr_bytes_written;
  }
  return bytes_written;
}

int32_t PosixPlatform::ReadFile(int32_t fd, char* file_buf, uint32_t read_size) {
  ssize_t bytes_read = read(fd, file_buf, read_size);
  if (bytes_read < 0) {
    return -errno;
  }
  return bytes_read;
}

int32_t PosixPlatform::CloseFile(int32_t fd) {
  int32_t close_status = close(fd);

  if (close_status < 0) {
    return -errno;
  }
  return close_status;
}

bool PosixPlatform::FileExists(std::string file_path) {
  struct stat file_stat;
  if (stat(file_path.c_str(), &file_stat) != 0) {
    return false;
  }

  return S_ISREG(file_stat.st_mode);
}

bool PosixPlatform::DirectoryExists(std::string dir_path) {
  struct stat dir_stat;
  if (stat(dir_path.c_str(), &dir_stat) != 0) {
    return false;
  }

  return S_ISDIR(dir_stat.st_mode);
}

bool PosixPlatform::CreateDirectory(std::string dir_path) {
  if (dir_path.size() == 0) {
    return false;
  }
  if (DirectoryExists(dir_path)) {
    return true;
  }

  char* dir_path_copy = strdup(dir_path.c_str());
  bool create_status = CreateDirectory(std::string(dirname(dir_path_copy)));
  free(dir_path_copy);

  if (!create_status) {
    return false;
  }
  if (mkdir(dir_path.c_str(), S_IRWXU | S_IRWXG | S_IRWXO) != 0) {
    return false;
  }
  return true;
}

int32_t PosixPlatform::GetStubFD(uint32_t cid, uint32_t port) {
  int sockfd = socket(AF_VSOCK, SOCK_STREAM | SOCK_NONBLOCK, 0);
  sockaddr_vm addr = {
      .svm_family = AF_VSOCK,
      .svm_reserved1 = 0,
      .svm_port = port,
      .svm_cid = cid,
      .svm_zero = {0},
  };
  return connect(sockfd, (sockaddr*)&addr, sizeof(sockaddr_vm));
}

int32_t PosixPlatform::GetServerFD(uint32_t cid, uint32_t port) {
  int sockfd = socket(AF_VSOCK, SOCK_STREAM | SOCK_NONBLOCK, 0);
  sockaddr_vm addr = {
      .svm_family = AF_VSOCK,
      .svm_reserved1 = 0,
      .svm_port = port,
      .svm_cid = cid,
      .svm_zero = {0},
  };
  if (bind(sockfd, (sockaddr*)&addr, sizeof(sockaddr_vm)) != 0) {
    return errno;
  }
  if (listen(sockfd, 100) != 0) {
    return errno;
  }
  return sockfd;
}

void PosixPlatform::AcceptClient(grpc::Server* server, uint32_t sockfd) {
  sockaddr addr;
  socklen_t addr_len;
  int new_fd = accept(sockfd, &addr, &addr_len);

  if (new_fd > 0) {
    fcntl(new_fd, F_SETFL, fcntl(new_fd, F_GETFL, 0) | O_NONBLOCK);
    grpc::AddInsecureChannelFromFd(server, new_fd);
  }
}

int32_t PosixPlatform::Exec(char** args, char** env, int32_t* user_std_in, int32_t* user_std_out,
                            int32_t* user_std_err) {
  int std_in[2];
  int std_out[2];
  int std_err[2];

  if (pipe(std_in) != 0 || pipe(std_out) != 0 || pipe(std_err) != 0) {
    return -errno;
  }

  pid_t child_pid = fork();

  if (child_pid == 0) {
    if (close(std_in[1]) != 0 || close(std_out[0]) != 0 || close(std_err[0]) != 0) {
      exit(-errno);
    }

    if (dup2(std_in[0], STDIN_FILENO) < 0 || dup2(std_out[1], STDOUT_FILENO) < 0 ||
        dup2(std_err[1], STDERR_FILENO) < 0) {
      exit(-errno);
    }

    execve(args[0], &args[0], &env[0]);
    exit(-errno);
  } else if (child_pid < 0) {
    return -errno;
  } else {
    if (close(std_in[0]) != 0 || close(std_out[1]) != 0 || close(std_err[1]) != 0) {
      return -errno;
    }

    // Set read FD's to nonblocking mode.
    int flags = fcntl(std_out[0], F_GETFL, 0);
    fcntl(std_out[0], F_SETFL, flags | O_NONBLOCK);

    flags = fcntl(std_err[0], F_GETFL, 0);
    fcntl(std_err[0], F_SETFL, flags | O_NONBLOCK);

    *user_std_in = std_in[1];
    *user_std_out = std_out[0];
    *user_std_err = std_err[0];

    return child_pid;
  }
}

int32_t PosixPlatform::WaitPid(int32_t pid, int32_t* status, int32_t flags) {
  int32_t poll_pid = waitpid(pid, status, flags);
  if (poll_pid < 0) {
    return -errno;
  }
  return poll_pid;
}

int32_t PosixPlatform::KillPid(int32_t pid, int32_t signal) {
  int32_t ret = kill(pid, signal);

  if (ret < 0) {
    return -errno;
  }
  return ret;
}

void PosixPlatform::SetFileNonblocking(int32_t fd) {
  int flags = fcntl(fd, F_GETFL, 0);
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);
}

std::vector<std::string> PosixPlatform::ParseCommand(std::string command) {
  wordexp_t command_line;
  int32_t parse_result = wordexp(command.c_str(), &command_line, 0);

  std::vector<std::string> argv;
  if (parse_result == 0) {
    for (uint32_t i = 0; i < command_line.we_wordc; i++) {
      argv.push_back(command_line.we_wordv[i]);
    }
  }

  wordfree(&command_line);

  return argv;
}
