// Copyright (c) 2012, 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_WINDOWS)

#include "bin/directory.h"

#include <errno.h>     // NOLINT
#include <sys/stat.h>  // NOLINT

#include "bin/crypto.h"
#include "bin/dartutils.h"
#include "bin/file.h"
#include "bin/file_win.h"
#include "bin/namespace.h"
#include "bin/utils.h"
#include "bin/utils_win.h"
#include "platform/syslog.h"
#include "platform/utils.h"

#undef DeleteFile

namespace dart {
namespace bin {

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

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

char* PathBuffer::AsString() const {
  UNREACHABLE();
  return NULL;
}

wchar_t* PathBuffer::AsStringW() const {
  return reinterpret_cast<wchar_t*>(data_);
}

const char* PathBuffer::AsScopedString() const {
  return StringUtilsWin::WideToUtf8(AsStringW());
}

bool PathBuffer::Add(const char* name) {
  Utf8ToWideScope wide_name(name);
  return AddW(wide_name.wide());
}

bool PathBuffer::AddW(const wchar_t* name) {
  wchar_t* data = AsStringW();
  int written =
      _snwprintf(data + length_, MAX_LONG_PATH - length_, L"%s", name);
  data[MAX_LONG_PATH] = L'\0';
  if ((written <= MAX_LONG_PATH - length_) && (written >= 0) &&
      (static_cast<size_t>(written) == wcsnlen(name, MAX_LONG_PATH + 1))) {
    length_ += written;
    return true;
  } else {
    SetLastError(ERROR_BUFFER_OVERFLOW);
    return false;
  }
}

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

// If link_name points to a link, IsBrokenLink will return true if link_name
// points to an invalid target.
static bool IsBrokenLink(const wchar_t* link_name) {
  HANDLE handle = CreateFileW(
      link_name, 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
      NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
  if (handle == INVALID_HANDLE_VALUE) {
    return true;
  } else {
    CloseHandle(handle);
    return false;
  }
}

// A linked list structure holding a link target's unique file system ID.
// Used to detect loops in the file system when listing recursively.
struct LinkList {
  DWORD volume;
  DWORD id_low;
  DWORD id_high;
  LinkList* next;
};

// Forward declarations.
static bool DeleteRecursively(PathBuffer* path);

static ListType HandleFindFile(DirectoryListing* listing,
                               DirectoryListingEntry* entry,
                               const WIN32_FIND_DATAW& find_file_data) {
  if (!listing->path_buffer().AddW(find_file_data.cFileName)) {
    return kListError;
  }
  DWORD attributes = find_file_data.dwFileAttributes;
  if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
    if (!listing->follow_links()) {
      return kListLink;
    }
    HANDLE handle =
        CreateFileW(listing->path_buffer().AsStringW(), 0,
                    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                    NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL);
    if (handle == INVALID_HANDLE_VALUE) {
      // Report as (broken) link.
      return kListLink;
    }
    if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
      // Check the seen link targets to see if we are in a file system loop.
      LinkList current_link;
      BY_HANDLE_FILE_INFORMATION info;
      // Get info
      if (!GetFileInformationByHandle(handle, &info)) {
        DWORD error = GetLastError();
        CloseHandle(handle);
        SetLastError(error);
        return kListError;
      }
      CloseHandle(handle);
      current_link.volume = info.dwVolumeSerialNumber;
      current_link.id_low = info.nFileIndexLow;
      current_link.id_high = info.nFileIndexHigh;
      current_link.next = entry->link();
      LinkList* previous = entry->link();
      while (previous != NULL) {
        if ((previous->volume == current_link.volume) &&
            (previous->id_low == current_link.id_low) &&
            (previous->id_high == current_link.id_high)) {
          // Report the looping link as a link, rather than following it.
          return kListLink;
        }
        previous = previous->next;
      }
      // Recurse into the directory, adding current link to the seen links list.
      if ((wcscmp(find_file_data.cFileName, L".") == 0) ||
          (wcscmp(find_file_data.cFileName, L"..") == 0)) {
        return entry->Next(listing);
      }
      entry->set_link(new LinkList(current_link));
      return kListDirectory;
    }
  }
  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    if ((wcscmp(find_file_data.cFileName, L".") == 0) ||
        (wcscmp(find_file_data.cFileName, L"..") == 0)) {
      return entry->Next(listing);
    }
    return kListDirectory;
  } else {
    return kListFile;
  }
}

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

  WIN32_FIND_DATAW find_file_data;

  if (lister_ == 0) {
    const wchar_t* tail = parent_ == NULL ? L"*" : L"\\*";
    if (!listing->path_buffer().AddW(tail)) {
      done_ = true;
      return kListError;
    }

    path_length_ = listing->path_buffer().length() - 1;

    HANDLE find_handle =
        FindFirstFileW(listing->path_buffer().AsStringW(), &find_file_data);

    if (find_handle == INVALID_HANDLE_VALUE) {
      done_ = true;
      return kListError;
    }

    lister_ = reinterpret_cast<intptr_t>(find_handle);

    listing->path_buffer().Reset(path_length_);

    return HandleFindFile(listing, this, find_file_data);
  }

  // Reset.
  listing->path_buffer().Reset(path_length_);
  ResetLink();

  if (FindNextFileW(reinterpret_cast<HANDLE>(lister_), &find_file_data) != 0) {
    return HandleFindFile(listing, this, find_file_data);
  }

  done_ = true;

  if (GetLastError() != ERROR_NO_MORE_FILES) {
    return kListError;
  }

  return kListDone;
}

DirectoryListingEntry::~DirectoryListingEntry() {
  ResetLink();
  if (lister_ != 0) {
    FindClose(reinterpret_cast<HANDLE>(lister_));
  }
}

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

static bool DeleteFile(const wchar_t* file_name, PathBuffer* path) {
  if (!path->AddW(file_name)) {
    return false;
  }

  if (DeleteFileW(path->AsStringW()) != 0) {
    return true;
  }

  // If we failed because the file is read-only, make it writeable and try
  // again. This mirrors Linux/Mac where a directory containing read-only files
  // can still be recursively deleted.
  if (GetLastError() == ERROR_ACCESS_DENIED) {
    DWORD attributes = GetFileAttributesW(path->AsStringW());
    if (attributes == INVALID_FILE_ATTRIBUTES) {
      return false;
    }

    if ((attributes & FILE_ATTRIBUTE_READONLY) == FILE_ATTRIBUTE_READONLY) {
      attributes &= ~FILE_ATTRIBUTE_READONLY;

      if (SetFileAttributesW(path->AsStringW(), attributes) == 0) {
        return false;
      }

      return DeleteFileW(path->AsStringW()) != 0;
    }
  }

  return false;
}

static bool DeleteDir(const wchar_t* dir_name, PathBuffer* path) {
  if ((wcscmp(dir_name, L".") == 0) || (wcscmp(dir_name, L"..") == 0)) {
    return true;
  }
  return path->AddW(dir_name) && DeleteRecursively(path);
}

static bool DeleteEntry(LPWIN32_FIND_DATAW find_file_data, PathBuffer* path) {
  DWORD attributes = find_file_data->dwFileAttributes;

  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    return DeleteDir(find_file_data->cFileName, path);
  } else {
    return DeleteFile(find_file_data->cFileName, path);
  }
}

static bool DeleteRecursively(PathBuffer* path) {
  PathBuffer prefixed_path;
  if (!prefixed_path.Add(PrefixLongDirectoryPath(path->AsScopedString()))) {
    return false;
  }

  DWORD attributes = GetFileAttributesW(prefixed_path.AsStringW());
  if (attributes == INVALID_FILE_ATTRIBUTES) {
    return false;
  }
  // If the directory is a junction, it's pointing to some other place in the
  // filesystem that we do not want to recurse into.
  if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
    // Just delete the junction itself.
    return RemoveDirectoryW(prefixed_path.AsStringW()) != 0;
  }
  // If it's a file, remove it directly.
  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    return DeleteFile(L"", &prefixed_path);
  }

  if (!prefixed_path.AddW(L"\\*")) {
    return false;
  }

  WIN32_FIND_DATAW find_file_data;
  HANDLE find_handle =
      FindFirstFileW(prefixed_path.AsStringW(), &find_file_data);

  if (find_handle == INVALID_HANDLE_VALUE) {
    return false;
  }

  // Adjust the path by removing the '*' used for the search.
  int path_length = prefixed_path.length() - 1;
  prefixed_path.Reset(path_length);

  do {
    if (!DeleteEntry(&find_file_data, &prefixed_path)) {
      break;
    }
    prefixed_path.Reset(path_length);  // DeleteEntry adds to the path.
  } while (FindNextFileW(find_handle, &find_file_data) != 0);

  DWORD last_error = GetLastError();
  // Always close handle.
  FindClose(find_handle);
  if (last_error != ERROR_NO_MORE_FILES) {
    // Unexpected error, set and return.
    SetLastError(last_error);
    return false;
  }
  // All content deleted succesfully, try to delete directory.
  prefixed_path.Reset(path_length -
                      1);  // Drop the "\" from the end of the path.
  return RemoveDirectoryW(prefixed_path.AsStringW()) != 0;
}

static Directory::ExistsResult ExistsHelper(const wchar_t* dir_name) {
  DWORD attributes = GetFileAttributesW(dir_name);
  if (attributes == INVALID_FILE_ATTRIBUTES) {
    DWORD last_error = GetLastError();
    if ((last_error == ERROR_FILE_NOT_FOUND) ||
        (last_error == ERROR_PATH_NOT_FOUND)) {
      return Directory::DOES_NOT_EXIST;
    } else {
      // We might not be able to get the file attributes for other
      // reasons such as lack of permissions. In that case we do
      // not know if the directory exists.
      return Directory::UNKNOWN;
    }
  }
  bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  exists = exists && !IsBrokenLink(dir_name);
  return exists ? Directory::EXISTS : Directory::DOES_NOT_EXIST;
}

Directory::ExistsResult Directory::Exists(Namespace* namespc,
                                          const char* dir_name) {
  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
  Utf8ToWideScope system_name(prefixed_dir_name);
  return ExistsHelper(system_name.wide());
}

char* Directory::CurrentNoScope() {
  int length = GetCurrentDirectoryW(0, NULL);
  if (length == 0) {
    return NULL;
  }
  wchar_t* current = new wchar_t[length + 1];
  GetCurrentDirectoryW(length + 1, current);
  int utf8_len =
      WideCharToMultiByte(CP_UTF8, 0, current, -1, NULL, 0, NULL, NULL);
  char* result = reinterpret_cast<char*>(malloc(utf8_len));
  WideCharToMultiByte(CP_UTF8, 0, current, -1, result, utf8_len, NULL, NULL);
  delete[] current;
  return result;
}

bool Directory::Create(Namespace* namespc, const char* dir_name) {
  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
  Utf8ToWideScope system_name(prefixed_dir_name);
  int create_status = CreateDirectoryW(system_name.wide(), NULL);
  // If the directory already existed, treat it as a success.
  if ((create_status == 0) && (GetLastError() == ERROR_ALREADY_EXISTS) &&
      (ExistsHelper(system_name.wide()) == EXISTS)) {
    return true;
  }
  return (create_status != 0);
}

const char* Directory::SystemTemp(Namespace* namespc) {
  PathBuffer path;
  // Remove \ at end.
  path.Reset(GetTempPathW(MAX_LONG_PATH, path.AsStringW()) - 1);
  return path.AsScopedString();
}

// Creates a new temporary directory with a UUID as suffix.
static const char* CreateTempFromUUID(const char* prefix) {
  PathBuffer path;
  Utf8ToWideScope system_prefix(prefix);
  if (!path.AddW(system_prefix.wide())) {
    return NULL;
  }

  // Length of xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 36.
  if (path.length() > MAX_LONG_PATH - 36) {
    return NULL;
  }

  UUID uuid;
  RPC_STATUS status = UuidCreateSequential(&uuid);
  if ((status != RPC_S_OK) && (status != RPC_S_UUID_LOCAL_ONLY)) {
    return NULL;
  }
  RPC_WSTR uuid_string;
  status = UuidToStringW(&uuid, &uuid_string);
  if (status != RPC_S_OK) {
    return NULL;
  }

  // RPC_WSTR is an unsigned short*, so we cast to wchar_t*.
  if (!path.AddW(reinterpret_cast<wchar_t*>(uuid_string))) {
    return NULL;
  }
  RpcStringFreeW(&uuid_string);
  if (!CreateDirectoryW(path.AsStringW(), NULL)) {
    return NULL;
  }
  return path.AsScopedString();
}

// Creates a new, unused directory, adding characters to the end of prefix, and
// returns the directory's name.
//
// Creates this directory, with a default security descriptor inherited from its
// parent directory. The return value is Dart_ScopeAllocated.
//
// First, attempts appending a suffix created from a random uint32_t. If that
// name is already taken, falls back on using a UUID for the suffix.
//
// Note: More attempts at finding an available short suffix would more reliably
// avoid a uuid suffix. We choose one attempt here because it is simpler, and
// to have a small bound on the number of calls to CreateDirectoryW().
const char* Directory::CreateTemp(Namespace* namespc, const char* prefix) {
  PathBuffer path;
  Utf8ToWideScope system_prefix(prefix);
  if (!path.AddW(system_prefix.wide())) {
    return NULL;
  }

  // Adding 8 hex digits.
  if (path.length() > MAX_LONG_PATH - 8) {
    // No fallback, there won't be enough room for the UUID, either.
    return NULL;
  }

  // First try a short suffix using the rng, then if that fails fall back on
  // a uuid.
  uint32_t suffix_bytes = 0;
  const int kSuffixSize = sizeof(suffix_bytes);
  if (!Crypto::GetRandomBytes(kSuffixSize,
                              reinterpret_cast<uint8_t*>(&suffix_bytes))) {
    // Getting random bytes failed, maybe the UUID will work?
    return CreateTempFromUUID(prefix);
  }

  // Two digits per byte plus null.
  char suffix[kSuffixSize * 2 + 1];
  Utils::SNPrint(suffix, sizeof(suffix), "%x", suffix_bytes);
  if (!path.Add(suffix)) {
    // Adding to the path failed, maybe because of low-memory. Don't fall back.
    return NULL;
  }

  if (!CreateDirectoryW(path.AsStringW(), NULL)) {
    // Creation failed, possibly because an entry with the name already exists.
    // Fall back to using the UUID suffix.
    return CreateTempFromUUID(prefix);
  }
  return path.AsScopedString();
}

bool Directory::Delete(Namespace* namespc,
                       const char* dir_name,
                       bool recursive) {
  const char* prefixed_dir_name = PrefixLongDirectoryPath(dir_name);
  bool result = false;
  Utf8ToWideScope system_dir_name(prefixed_dir_name);
  if (!recursive) {
    if (File::GetType(namespc, prefixed_dir_name, true) == File::kIsDirectory) {
      result = (RemoveDirectoryW(system_dir_name.wide()) != 0);
    } else {
      SetLastError(ERROR_FILE_NOT_FOUND);
    }
  } else {
    PathBuffer path;
    if (path.AddW(system_dir_name.wide())) {
      result = DeleteRecursively(&path);
    }
  }
  return result;
}

bool Directory::Rename(Namespace* namespc,
                       const char* path,
                       const char* new_path) {
  const char* prefixed_dir = PrefixLongDirectoryPath(path);
  Utf8ToWideScope system_path(prefixed_dir);
  ExistsResult exists = ExistsHelper(system_path.wide());
  if (exists != EXISTS) {
    SetLastError(ERROR_FILE_NOT_FOUND);
    return false;
  }
  const char* prefixed_new_dir = PrefixLongDirectoryPath(new_path);
  Utf8ToWideScope system_new_path(prefixed_new_dir);
  DWORD flags = MOVEFILE_WRITE_THROUGH;
  int move_status =
      MoveFileExW(system_path.wide(), system_new_path.wide(), flags);
  return (move_status != 0);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(DART_HOST_OS_WINDOWS)
