// 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(HOST_OS_FUCHSIA)

#include "bin/namespace.h"

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

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

namespace dart {
namespace bin {

class NamespaceImpl {
 public:
  explicit NamespaceImpl(fdio_ns_t* fdio_ns)
      : fdio_ns_(fdio_ns),
        rootfd_(fdio_ns_opendir(fdio_ns)),
        cwd_(strdup("/")) {
    ASSERT(rootfd_ > 0);
    cwdfd_ = dup(rootfd_);
    ASSERT(cwdfd_ > 0);
  }

  explicit NamespaceImpl(const char* path)
      : fdio_ns_(NULL),
        rootfd_(TEMP_FAILURE_RETRY(open64(path, O_DIRECTORY))),
        cwd_(strdup("/")) {
    ASSERT(rootfd_ > 0);
    cwdfd_ = dup(rootfd_);
    ASSERT(cwdfd_ > 0);
  }

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

  intptr_t rootfd() const { return rootfd_; }
  char* cwd() const { return cwd_; }
  intptr_t cwdfd() const { return cwdfd_; }

  bool SetCwd(Namespace* namespc, const char* new_path) {
    NamespaceScope ns(namespc, new_path);
    const intptr_t new_cwdfd =
        TEMP_FAILURE_RETRY(openat64(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.buf(), result, PATH_MAX);
    if (result_len < 0) {
      errno = ENAMETOOLONG;
      return false;
    }

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

 private:
  fdio_ns_t* fdio_ns_;  // native namespace object, if any.
  intptr_t rootfd_;     // dirfd for the namespace root.
  char* cwd_;           // cwd relative to the namespace.
  intptr_t cwdfd_;      // dirfd for the cwd.

  DISALLOW_COPY_AND_ASSIGN(NamespaceImpl);
};

Namespace* Namespace::Create(intptr_t namespc) {
  NamespaceImpl* namespc_impl = NULL;
  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) == NULL) {
      return NULL;
    }
    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 != NULL);
  ASSERT(resolved_path != NULL);
  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(HOST_OS_FUCHSIA)
