// Copyright (c) 2017, 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/namespace.h"
#include "bin/namespace_fuchsia.h"

#include <errno.h>
#include <fcntl.h>
#include <lib/fdio/namespace.h>
#include <zircon/status.h>

#include "bin/file.h"
#include "platform/signal_blocker.h"
#include "platform/text_buffer.h"

namespace dart {
namespace bin {

NamespaceImpl::NamespaceImpl(fdio_ns_t* fdio_ns)
    : fdio_ns_(fdio_ns), cwd_(strdup("/")) {
  rootfd_ = fdio_ns_opendir(fdio_ns);
  if (rootfd_ < 0) {
    FATAL("Failed to open file descriptor for namespace: errno=%d: %s", errno,
          strerror(errno));
  }
  cwdfd_ = dup(rootfd_);
  if (cwdfd_ < 0) {
    FATAL("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
          strerror(errno));
  }
}

NamespaceImpl::NamespaceImpl(const char* path)
    : fdio_ns_(nullptr), cwd_(strdup("/")) {
  rootfd_ = TEMP_FAILURE_RETRY(open(path, O_DIRECTORY));
  if (rootfd_ < 0) {
    FATAL("Failed to open file descriptor for namespace: errno=%d: %s", errno,
          strerror(errno));
  }
  cwdfd_ = dup(rootfd_);
  if (cwdfd_ < 0) {
    FATAL("Failed to dup() namespace file descriptor: errno=%d: %s", errno,
          strerror(errno));
  }
}

NamespaceImpl::~NamespaceImpl() {
  NO_RETRY_EXPECTED(close(rootfd_));
  free(cwd_);
  NO_RETRY_EXPECTED(close(cwdfd_));
  if (fdio_ns_ != nullptr) {
    zx_status_t status = fdio_ns_destroy(fdio_ns_);
    if (status != ZX_OK) {
      Syslog::PrintErr("fdio_ns_destroy: %s\n", zx_status_get_string(status));
    }
  }
}

bool NamespaceImpl::SetCwd(Namespace* namespc, const char* new_path) {
  NamespaceScope ns(namespc, new_path);
  const intptr_t new_cwdfd =
      TEMP_FAILURE_RETRY(openat(ns.fd(), ns.path(), O_DIRECTORY));
  if (new_cwdfd < 0) {
    return false;
  }

  // Build the new cwd.
  TextBuffer tbuf(PATH_MAX);
  if (!File::IsAbsolutePath(new_path)) {
    tbuf.AddString(cwd_);
  }
  tbuf.AddString(File::PathSeparator());
  tbuf.AddString(ns.path());

  // Normalize it.
  char result[PATH_MAX];
  const intptr_t result_len =
      File::CleanUnixPath(tbuf.buffer(), result, PATH_MAX);
  if (result_len < 0) {
    errno = ENAMETOOLONG;
    return false;
  }

  free(cwd_);
  cwd_ = strdup(result);
  close(cwdfd_);
  cwdfd_ = new_cwdfd;
  return true;
}

Namespace* Namespace::Create(intptr_t namespc) {
  NamespaceImpl* namespc_impl = nullptr;
  if (namespc != kNone) {
    namespc_impl = new NamespaceImpl(reinterpret_cast<fdio_ns_t*>(namespc));
  }
  return new Namespace(namespc_impl);
}

Namespace* Namespace::Create(const char* path) {
  return new Namespace(new NamespaceImpl(path));
}

Namespace::~Namespace() {
  delete namespc_;
}

intptr_t Namespace::Default() {
  return kNone;
}

const char* Namespace::GetCurrent(Namespace* namespc) {
  if (Namespace::IsDefault(namespc)) {
    char buffer[PATH_MAX];
    if (getcwd(buffer, PATH_MAX) == nullptr) {
      return nullptr;
    }
    return DartUtils::ScopedCopyCString(buffer);
  }
  return namespc->namespc()->cwd();
}

bool Namespace::SetCurrent(Namespace* namespc, const char* path) {
  if (Namespace::IsDefault(namespc)) {
    return (NO_RETRY_EXPECTED(chdir(path)) == 0);
  }
  return namespc->namespc()->SetCwd(namespc, path);
}

void Namespace::ResolvePath(Namespace* namespc,
                            const char* path,
                            intptr_t* dirfd,
                            const char** resolved_path) {
  ASSERT(dirfd != nullptr);
  ASSERT(resolved_path != nullptr);
  if (Namespace::IsDefault(namespc)) {
    *dirfd = AT_FDCWD;
    *resolved_path = path;
    return;
  }
  if (File::IsAbsolutePath(path)) {
    *dirfd = namespc->namespc()->rootfd();
    if (strcmp(path, File::PathSeparator()) == 0) {
      // Change "/" to ".".
      *resolved_path = ".";
    } else {
      // Otherwise strip off the leading "/".
      *resolved_path = &path[1];
    }
  } else {
    *dirfd = namespc->namespc()->cwdfd();
    *resolved_path = path;
  }
}

NamespaceScope::NamespaceScope(Namespace* namespc, const char* path) {
  Namespace::ResolvePath(namespc, path, &fd_, &path_);
}

NamespaceScope::~NamespaceScope() {}

}  // namespace bin
}  // namespace dart

#endif  // defined(DART_HOST_OS_FUCHSIA)
