// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

#include "platform/globals.h"
#if defined(DART_HOST_OS_FUCHSIA)

#include "bin/directory.h"

#include <dirent.h>              // NOLINT
#include <errno.h>               // NOLINT
#include <fcntl.h>               // NOLINT
#include <lib/fdio/namespace.h>  // NOLINT
#include <stdlib.h>              // NOLINT
#include <string.h>              // NOLINT
#include <sys/param.h>           // NOLINT
#include <sys/stat.h>            // NOLINT
#include <unistd.h>              // NOLINT

#include "bin/crypto.h"
#include "bin/dartutils.h"
#include "bin/fdutils.h"
#include "bin/file.h"
#include "bin/namespace.h"
#include "bin/platform.h"
#include "platform/signal_blocker.h"

namespace dart {
namespace bin {

PathBuffer::PathBuffer() : length_(0) {
  data_ = calloc(PATH_MAX + 1, sizeof(char));  // NOLINT
}

PathBuffer::~PathBuffer() {
  free(data_);
}

bool PathBuffer::AddW(const wchar_t* name) {
  UNREACHABLE();
  return false;
}

char* PathBuffer::AsString() const {
  return reinterpret_cast<char*>(data_);
}

wchar_t* PathBuffer::AsStringW() const {
  UNREACHABLE();
  return nullptr;
}

const char* PathBuffer::AsScopedString() const {
  return DartUtils::ScopedCopyCString(AsString());
}

bool PathBuffer::Add(const char* name) {
  const intptr_t name_length = strnlen(name, PATH_MAX + 1);
  if (name_length == 0) {
    errno = EINVAL;
    return false;
  }
  char* data = AsString();
  int written = snprintf(data + length_, PATH_MAX - length_, "%s", name);
  data[PATH_MAX] = '\0';
  if ((written <= (PATH_MAX - length_)) && (written > 0) &&
      (static_cast<size_t>(written) == strnlen(name, PATH_MAX + 1))) {
    length_ += written;
    return true;
  } else {
    errno = ENAMETOOLONG;
    return false;
  }
}

void PathBuffer::Reset(intptr_t new_length) {
  length_ = new_length;
  AsString()[length_] = '\0';
}

// A linked list of symbolic links, with their unique file system identifiers.
// These are scanned to detect loops while doing a recursive directory listing.
struct LinkList {
  dev_t dev;
  ino_t ino;
  LinkList* next;
};

ListType DirectoryListingEntry::Next(DirectoryListing* listing) {
  if (done_) {
    return kListDone;
  }

  if (fd_ == -1) {
    ASSERT(lister_ == 0);
    NamespaceScope ns(listing->namespc(), listing->path_buffer().AsString());
    const int listingfd =
        TEMP_FAILURE_RETRY(openat(ns.fd(), ns.path(), O_DIRECTORY));
    if (listingfd < 0) {
      done_ = true;
      return kListError;
    }
    fd_ = listingfd;
  }

  if (lister_ == 0) {
    do {
      lister_ = reinterpret_cast<intptr_t>(fdopendir(fd_));
    } while ((lister_ == 0) && (errno == EINTR));
    if (lister_ == 0) {
      done_ = true;
      return kListError;
    }
    if (parent_ != nullptr) {
      if (!listing->path_buffer().Add(File::PathSeparator())) {
        return kListError;
      }
    }
    path_length_ = listing->path_buffer().length();
  }
  // Reset.
  listing->path_buffer().Reset(path_length_);
  ResetLink();

  // Iterate the directory and post the directories and files to the
  // ports.
  errno = 0;
  dirent* entry = readdir(reinterpret_cast<DIR*>(lister_));
  if (entry != nullptr) {
    if (!listing->path_buffer().Add(entry->d_name)) {
      done_ = true;
      return kListError;
    }
    switch (entry->d_type) {
      case DT_DIR:
        if ((strcmp(entry->d_name, ".") == 0) ||
            (strcmp(entry->d_name, "..") == 0)) {
          return Next(listing);
        }
        return kListDirectory;
      case DT_BLK:
      case DT_CHR:
      case DT_FIFO:
      case DT_SOCK:
      case DT_REG:
        return kListFile;
      case DT_LNK:
        if (!listing->follow_links()) {
          return kListLink;
        }
        // Else fall through to next case.
        FALL_THROUGH;
      case DT_UNKNOWN: {
        // On some file systems the entry type is not determined by
        // readdir. For those and for links we use stat to determine
        // the actual entry type. Notice that stat returns the type of
        // the file pointed to.
        NamespaceScope ns(listing->namespc(),
                          listing->path_buffer().AsString());
        struct stat entry_info;
        int stat_success;
        stat_success = TEMP_FAILURE_RETRY(
            fstatat(ns.fd(), ns.path(), &entry_info, AT_SYMLINK_NOFOLLOW));
        if (stat_success == -1) {
          return kListError;
        }
        if (listing->follow_links() && S_ISLNK(entry_info.st_mode)) {
          // Check to see if we are in a loop created by a symbolic link.
          LinkList current_link = {entry_info.st_dev, entry_info.st_ino, link_};
          LinkList* previous = link_;
          while (previous != nullptr) {
            if ((previous->dev == current_link.dev) &&
                (previous->ino == current_link.ino)) {
              // Report the looping link as a link, rather than following it.
              return kListLink;
            }
            previous = previous->next;
          }
          stat_success =
              TEMP_FAILURE_RETRY(fstatat(ns.fd(), ns.path(), &entry_info, 0));
          if (stat_success == -1 || (S_IFMT & entry_info.st_mode) == 0) {
            // Report a broken link as a link, even if follow_links is true.
            // A symbolic link can potentially point to an anon_inode. For
            // example, an epoll file descriptor will have a symbolic link whose
            // content is the string anon_inode:[eventpoll]. In this case, the
            // target doesn't belong to any regular file category.
            return kListLink;
          }
          if (S_ISDIR(entry_info.st_mode)) {
            // Recurse into the subdirectory with current_link added to the
            // linked list of seen file system links.
            link_ = new LinkList(current_link);
            if ((strcmp(entry->d_name, ".") == 0) ||
                (strcmp(entry->d_name, "..") == 0)) {
              return Next(listing);
            }
            return kListDirectory;
          }
        }
        if (S_ISDIR(entry_info.st_mode)) {
          if ((strcmp(entry->d_name, ".") == 0) ||
              (strcmp(entry->d_name, "..") == 0)) {
            return Next(listing);
          }
          return kListDirectory;
        } else if (S_ISLNK(entry_info.st_mode)) {
          return kListLink;
        } else {
          // Regular files, character devices, block devices, fifos, sockets and
          // unknown types are all considered as files.
          return kListFile;
        }
      }

      default:
        // We should have covered all the bases. If not, let's get an error.
        FATAL("Unexpected d_type: %d\n", entry->d_type);
        return kListError;
    }
  }
  done_ = true;

  if (errno != 0) {
    return kListError;
  }

  return kListDone;
}

DirectoryListingEntry::~DirectoryListingEntry() {
  ResetLink();
  if (lister_ != 0) {
    // This also closes fd_.
    VOID_NO_RETRY_EXPECTED(closedir(reinterpret_cast<DIR*>(lister_)));
  }
}

void DirectoryListingEntry::ResetLink() {
  if ((link_ != nullptr) &&
      ((parent_ == nullptr) || (parent_->link_ != link_))) {
    delete link_;
    link_ = nullptr;
  }
  if (parent_ != nullptr) {
    link_ = parent_->link_;
  }
}

Directory::ExistsResult Directory::Exists(Namespace* namespc,
                                          const char* dir_name) {
  NamespaceScope ns(namespc, dir_name);
  struct stat entry_info;
  const int success =
      TEMP_FAILURE_RETRY(fstatat(ns.fd(), ns.path(), &entry_info, 0));
  if (success == 0) {
    if (S_ISDIR(entry_info.st_mode)) {
      return EXISTS;
    } else {
      // An OSError may be constructed based on the return value of this
      // function, so set errno to something that makes sense.
      errno = ENOTDIR;
      return DOES_NOT_EXIST;
    }
  } else {
    if ((errno == EACCES) || (errno == EBADF) || (errno == EFAULT) ||
        (errno == ENOMEM) || (errno == EOVERFLOW)) {
      // Search permissions denied for one of the directories in the
      // path or a low level error occurred. We do not know if the
      // directory exists.
      return UNKNOWN;
    }
    ASSERT((errno == ELOOP) || (errno == ENAMETOOLONG) || (errno == ENOENT) ||
           (errno == ENOTDIR));
    return DOES_NOT_EXIST;
  }
}

char* Directory::CurrentNoScope() {
  return getcwd(nullptr, 0);
}

bool Directory::Create(Namespace* namespc, const char* dir_name) {
  NamespaceScope ns(namespc, dir_name);
  // Create the directory with the permissions specified by the
  // process umask.
  const int result = NO_RETRY_EXPECTED(mkdirat(ns.fd(), ns.path(), 0777));
  // If the directory already exists, treat it as a success.
  if ((result == -1) && (errno == EEXIST)) {
    return (Exists(namespc, dir_name) == EXISTS);
  }
  return (result == 0);
}

const char* Directory::SystemTemp(Namespace* namespc) {
  PathBuffer path;
  const char* temp_dir = getenv("TMPDIR");
  if (temp_dir == nullptr) {
    temp_dir = getenv("TMP");
  }
  if (temp_dir == nullptr) {
    temp_dir = "/tmp";
  }
  NamespaceScope ns(namespc, temp_dir);
  if (!path.Add(ns.path())) {
    return nullptr;
  }

  // Remove any trailing slash.
  char* result = path.AsString();
  int length = strlen(result);
  if ((length > 1) && (result[length - 1] == '/')) {
    result[length - 1] = '\0';
  }
  return path.AsScopedString();
}

// Returns a new, unused directory name, adding characters to the end
// of prefix.  Creates the directory with the permissions specified
// by the process umask.
// The return value is Dart_ScopeAllocated.
const char* Directory::CreateTemp(Namespace* namespc, const char* prefix) {
  PathBuffer path;
  const int firstchar = 'A';
  const int numchars = 'Z' - 'A' + 1;
  uint8_t random_bytes[7];

  // mkdtemp doesn't have an "at" variant, so we have to simulate it.
  if (!path.Add(prefix)) {
    return nullptr;
  }
  intptr_t prefix_length = path.length();
  while (true) {
    Crypto::GetRandomBytes(6, random_bytes);
    for (intptr_t i = 0; i < 6; i++) {
      random_bytes[i] = (random_bytes[i] % numchars) + firstchar;
    }
    random_bytes[6] = '\0';
    if (!path.Add(reinterpret_cast<char*>(random_bytes))) {
      return nullptr;
    }
    NamespaceScope ns(namespc, path.AsString());
    const int result = NO_RETRY_EXPECTED(mkdirat(ns.fd(), ns.path(), 0777));
    if (result == 0) {
      return path.AsScopedString();
    } else if (errno == EEXIST) {
      path.Reset(prefix_length);
    } else {
      return nullptr;
    }
  }
}

static bool DeleteRecursively(int dirfd, PathBuffer* path);

static bool DeleteFile(int dirfd, char* file_name, PathBuffer* path) {
  return path->Add(file_name) &&
         (NO_RETRY_EXPECTED(unlinkat(dirfd, path->AsString(), 0)) == 0);
}

static bool DeleteDir(int dirfd, char* dir_name, PathBuffer* path) {
  if ((strcmp(dir_name, ".") == 0) || (strcmp(dir_name, "..") == 0)) {
    return true;
  }
  return path->Add(dir_name) && DeleteRecursively(dirfd, path);
}

static bool DeleteRecursively(int dirfd, PathBuffer* path) {
  // Do not recurse into links for deletion. Instead delete the link.
  // If it's a file, delete it.
  struct stat st;
  if (TEMP_FAILURE_RETRY(
          fstatat(dirfd, path->AsString(), &st, AT_SYMLINK_NOFOLLOW)) == -1) {
    return false;
  } else if (!S_ISDIR(st.st_mode)) {
    return (NO_RETRY_EXPECTED(unlinkat(dirfd, path->AsString(), 0)) == 0);
  }

  if (!path->Add(File::PathSeparator())) {
    return false;
  }

  // Not a link. Attempt to open as a directory and recurse into the
  // directory.
  const int fd =
      TEMP_FAILURE_RETRY(openat(dirfd, path->AsString(), O_DIRECTORY));
  if (fd < 0) {
    return false;
  }
  DIR* dir_pointer;
  do {
    dir_pointer = fdopendir(fd);
  } while ((dir_pointer == nullptr) && (errno == EINTR));
  if (dir_pointer == nullptr) {
    FDUtils::SaveErrorAndClose(fd);
    return false;
  }

  // Iterate the directory and delete all files and directories.
  int path_length = path->length();
  while (true) {
    // In case `readdir()` returns `nullptr` we distinguish between
    // end-of-stream and error by looking if `errno` was updated.
    errno = 0;
    // In glibc 2.24+, readdir_r is deprecated.
    // According to the man page for readdir:
    // "readdir(3) is not required to be thread-safe. However, in modern
    // implementations (including the glibc implementation), concurrent calls to
    // readdir(3) that specify different directory streams are thread-safe."
    dirent* entry = readdir(dir_pointer);
    if (entry == nullptr) {
      // Failed to read next directory entry.
      if (errno != 0) {
        break;
      }
      // End of directory.
      int status = NO_RETRY_EXPECTED(closedir(dir_pointer));
      if (status != 0) {
        return false;
      }
      status =
          NO_RETRY_EXPECTED(unlinkat(dirfd, path->AsString(), AT_REMOVEDIR));
      return status == 0;
    }
    bool ok = false;
    switch (entry->d_type) {
      case DT_DIR:
        ok = DeleteDir(dirfd, entry->d_name, path);
        break;
      case DT_BLK:
      case DT_CHR:
      case DT_FIFO:
      case DT_SOCK:
      case DT_REG:
      case DT_LNK:
        // Treat all links as files. This will delete the link which
        // is what we want no matter if the link target is a file or a
        // directory.
        ok = DeleteFile(dirfd, entry->d_name, path);
        break;
      case DT_UNKNOWN: {
        if (!path->Add(entry->d_name)) {
          break;
        }
        // On some file systems the entry type is not determined by
        // readdir. For those we use lstat to determine the entry
        // type.
        struct stat entry_info;
        if (TEMP_FAILURE_RETRY(fstatat(dirfd, path->AsString(), &entry_info,
                                       AT_SYMLINK_NOFOLLOW)) == -1) {
          break;
        }
        path->Reset(path_length);
        if (S_ISDIR(entry_info.st_mode)) {
          ok = DeleteDir(dirfd, entry->d_name, path);
        } else {
          // Treat links as files. This will delete the link which is
          // what we want no matter if the link target is a file or a
          // directory.
          ok = DeleteFile(dirfd, entry->d_name, path);
        }
        break;
      }
      default:
        // We should have covered all the bases. If not, let's get an error.
        FATAL("Unexpected d_type: %d\n", entry->d_type);
        break;
    }
    if (!ok) {
      break;
    }
    path->Reset(path_length);
  }
  // Only happens if an error.
  ASSERT(errno != 0);
  int err = errno;
  VOID_NO_RETRY_EXPECTED(closedir(dir_pointer));
  errno = err;
  return false;
}

bool Directory::Delete(Namespace* namespc,
                       const char* dir_name,
                       bool recursive) {
  NamespaceScope ns(namespc, dir_name);
  if (!recursive) {
    if ((File::GetType(namespc, dir_name, false) == File::kIsLink) &&
        (File::GetType(namespc, dir_name, true) == File::kIsDirectory)) {
      return NO_RETRY_EXPECTED(unlinkat(ns.fd(), ns.path(), 0)) == 0;
    }
    return NO_RETRY_EXPECTED(unlinkat(ns.fd(), ns.path(), AT_REMOVEDIR)) == 0;
  } else {
    PathBuffer path;
    if (!path.Add(ns.path())) {
      return false;
    }
    return DeleteRecursively(ns.fd(), &path);
  }
}

bool Directory::Rename(Namespace* namespc,
                       const char* old_path,
                       const char* new_path) {
  ExistsResult exists = Exists(namespc, old_path);
  if (exists != EXISTS) {
    return false;
  }
  NamespaceScope oldns(namespc, old_path);
  NamespaceScope newns(namespc, new_path);
  return (NO_RETRY_EXPECTED(renameat(oldns.fd(), oldns.path(), newns.fd(),
                                     newns.path())) == 0);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(DART_HOST_OS_FUCHSIA)
