// Copyright 2016 The Bazel Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#include <wchar.h>   // wcslen
#include <wctype.h>  // iswalpha
#include <windows.h>

#include <memory>  // unique_ptr
#include <sstream>
#include <string>
#include <vector>

#include "src/main/cpp/util/errors.h"
#include "src/main/cpp/util/exit_code.h"
#include "src/main/cpp/util/file.h"
#include "src/main/cpp/util/logging.h"
#include "src/main/cpp/util/path_platform.h"
#include "src/main/cpp/util/strings.h"
#include "src/main/native/windows/file.h"
#include "src/main/native/windows/util.h"

namespace blaze_util {

using bazel::windows::AutoHandle;
using bazel::windows::GetLongPath;
using bazel::windows::HasUncPrefix;
using std::basic_string;
using std::pair;
using std::string;
using std::unique_ptr;
using std::vector;
using std::wstring;

static constexpr DWORD kAllShare =
    FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE;

// Returns true if `path` refers to a directory or (non-dangling) junction.
// `path` must be a normalized Windows path, with UNC prefix (and absolute) if
// necessary.
bool IsDirectoryW(const wstring& path);

// Returns true the file or junction at `path` is successfully deleted.
// Returns false otherwise, or if `path` doesn't exist or is a directory.
// `path` must be a normalized Windows path, with UNC prefix (and absolute) if
// necessary.
static bool UnlinkPathW(const wstring& path);

static bool CanReadFileW(const wstring& path);

template <typename char_type>
static bool IsPathSeparator(char_type ch) {
  return ch == '/' || ch == '\\';
}

class WindowsPipe : public IPipe {
 public:
  WindowsPipe(const HANDLE& read_handle, const HANDLE& write_handle)
      : _read_handle(read_handle), _write_handle(write_handle) {}

  WindowsPipe() = delete;

  bool Send(const void* buffer, int size) override {
    DWORD actually_written = 0;
    return ::WriteFile(_write_handle, buffer, size, &actually_written,
                       nullptr) == TRUE;
  }

  int Receive(void* buffer, int size, int* error) override {
    DWORD actually_read = 0;
    BOOL result =
        ::ReadFile(_read_handle, buffer, size, &actually_read, nullptr);
    if (error != nullptr) {
      // TODO(laszlocsomor): handle the error mode that is errno=EINTR on Linux.
      *error = result ? IPipe::SUCCESS : IPipe::OTHER_ERROR;
    }
    return result ? actually_read : -1;
  }

 private:
  AutoHandle _read_handle;
  AutoHandle _write_handle;
};

IPipe* CreatePipe() {
  // The pipe HANDLEs can be inherited.
  SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), nullptr, TRUE};
  HANDLE read_handle = INVALID_HANDLE_VALUE;
  HANDLE write_handle = INVALID_HANDLE_VALUE;
  if (!CreatePipe(&read_handle, &write_handle, &sa, 0)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "CreatePipe failed: " << GetLastErrorString();
  }
  return new WindowsPipe(read_handle, write_handle);
}

static FILETIME GetNow() {
  FILETIME now;
  GetSystemTimeAsFileTime(&now);
  return now;
}

static FILETIME GetYearsInFuture(WORD years) {
  FILETIME result;
  GetSystemTimeAsFileTime(&result);

  // 1 year in FILETIME.
  constexpr ULONGLONG kOneYear = 365ULL * 24 * 60 * 60 * 10000000;

  ULARGE_INTEGER result_value;
  result_value.LowPart = result.dwLowDateTime;
  result_value.HighPart = result.dwHighDateTime;
  result_value.QuadPart += kOneYear * years;
  result.dwLowDateTime = result_value.LowPart;
  result.dwHighDateTime = result_value.HighPart;
  return result;
}

static bool SetMtime(const Path& path, FILETIME time) {
  AutoHandle handle(::CreateFileW(
      /* lpFileName */ path.AsNativePath().c_str(),
      /* dwDesiredAccess */ FILE_WRITE_ATTRIBUTES,
      /* dwShareMode */ FILE_SHARE_READ,
      /* lpSecurityAttributes */ nullptr,
      /* dwCreationDisposition */ OPEN_EXISTING,
      /* dwFlagsAndAttributes */
      IsDirectoryW(path.AsNativePath())
          ? (FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS)
          : FILE_ATTRIBUTE_NORMAL,
      /* hTemplateFile */ nullptr));
  if (!handle.IsValid()) {
    return false;
  }
  return ::SetFileTime(
             /* hFile */ handle,
             /* lpCreationTime */ nullptr,
             /* lpLastAccessTime */ nullptr,
             /* lpLastWriteTime */ &time) == TRUE;
}

static const FILETIME kNearFuture = GetYearsInFuture(9);
static const FILETIME kDistantFuture = GetYearsInFuture(10);

bool IsUntampered(const Path& path) {
  if (path.IsEmpty() || path.IsNull()) {
    return false;
  }

  // Get attributes, to check if the file exists. (It may still be a dangling
  // junction.)
  DWORD attrs = GetFileAttributesW(path.AsNativePath().c_str());
  if (attrs == INVALID_FILE_ATTRIBUTES) {
    return false;
  }

  bool is_directory = attrs & FILE_ATTRIBUTE_DIRECTORY;
  AutoHandle handle(CreateFileW(
      /* lpFileName */ path.AsNativePath().c_str(),
      /* dwDesiredAccess */ GENERIC_READ,
      /* dwShareMode */ FILE_SHARE_READ,
      /* lpSecurityAttributes */ nullptr,
      /* dwCreationDisposition */ OPEN_EXISTING,
      /* dwFlagsAndAttributes */
      // Per CreateFile's documentation on MSDN, opening directories requires
      // the FILE_FLAG_BACKUP_SEMANTICS flag.
      is_directory ? FILE_FLAG_BACKUP_SEMANTICS : FILE_ATTRIBUTE_NORMAL,
      /* hTemplateFile */ nullptr));

  if (!handle.IsValid()) {
    return false;
  }

  if (is_directory) {
    return true;
  } else {
    BY_HANDLE_FILE_INFORMATION info;
    if (!GetFileInformationByHandle(handle, &info)) {
      return false;
    }

    // Compare with kNearFuture, not with kDistantFuture.
    // This way we don't need to worry about a potentially unreliable equality
    // check if precision isn't preserved.
    return CompareFileTime(&kNearFuture, &info.ftLastWriteTime) == -1;
  }
}

bool SetMtimeToNow(const Path& path) { return SetMtime(path, GetNow()); }

bool SetMtimeToNowIfPossible(const Path& path) {
  bool okay = SetMtimeToNow(path);
  if (!okay) {
    // `SetToNow` is backed by `CreateFileW` + `SetFileTime`; the former can
    // return `ERROR_ACCESS_DENIED` if there's a permissions issue:
    if (GetLastError() == ERROR_ACCESS_DENIED) {
      okay = true;
    }
  }

  return okay;
}

bool SetMtimeToDistantFuture(const Path& path) {
  return SetMtime(path, kDistantFuture);
}

static bool OpenFileForReading(const Path& path, HANDLE* result) {
  *result = ::CreateFileW(
      /* lpFileName */ path.AsNativePath().c_str(),
      /* dwDesiredAccess */ GENERIC_READ,
      /* dwShareMode */ kAllShare,
      /* lpSecurityAttributes */ nullptr,
      /* dwCreationDisposition */ OPEN_EXISTING,
      /* dwFlagsAndAttributes */ FILE_ATTRIBUTE_NORMAL,
      /* hTemplateFile */ nullptr);
  return true;
}

int ReadFromHandle(file_handle_type handle, void* data, size_t size,
                   int* error) {
  DWORD actually_read = 0;
  bool success = ::ReadFile(handle, data, size, &actually_read, nullptr);
  if (error != nullptr) {
    // TODO(laszlocsomor): handle the error cases that are errno=EINTR and
    // errno=EAGAIN on Linux.
    *error = success ? ReadFileResult::SUCCESS : ReadFileResult::OTHER_ERROR;
  }
  return success ? actually_read : -1;
}

bool ReadFile(const string& filename, string* content, int max_size) {
  return ReadFile(filename, content, nullptr, max_size);
}

bool ReadFile(const string& filename, string* content, string* error_message,
              int max_size) {
  if (IsDevNull(filename.c_str())) {
    // mimic read(2) behavior: we can always read 0 bytes from /dev/null
    content->clear();
    return true;
  }

  // In order for try-imports to be ignored gracefully we need to check for an
  // error with the path and return false rather than die.
  std::string errorText;
  Path path = Path(filename, &errorText);
  if (!errorText.empty()) {
    std::string message = "Path is not valid: " + filename + " :" + errorText;
    BAZEL_LOG(WARNING) << message;
    if (error_message != nullptr) {
      *error_message = std::move(message);
    }
    return false;
  }
  return ReadFile(path, content, max_size);
}

bool ReadFile(const Path& path, std::string* content, int max_size) {
  if (path.IsEmpty()) {
    return false;
  }
  // TODO(laszlocsomor): remove the following check; it won't allow opening NUL.
  if (path.IsNull()) {
    return true;
  }

  HANDLE handle;
  if (!OpenFileForReading(path, &handle)) {
    return false;
  }

  AutoHandle autohandle(handle);
  if (!autohandle.IsValid()) {
    return false;
  }
  content->clear();
  return ReadFrom(handle, content, max_size);
}

bool ReadFile(const string& filename, void* data, size_t size) {
  return ReadFile(Path(filename), data, size);
}

bool ReadFile(const Path& path, void* data, size_t size) {
  if (path.IsEmpty()) {
    return false;
  }
  if (path.IsNull()) {
    // mimic read(2) behavior: we can always read 0 bytes from /dev/null
    return true;
  }
  HANDLE handle;
  if (!OpenFileForReading(path, &handle)) {
    return false;
  }

  AutoHandle autohandle(handle);
  if (!autohandle.IsValid()) {
    return false;
  }
  return ReadFrom(handle, data, size);
}

bool WriteFile(const void* data, size_t size, const string& filename,
               unsigned int perm) {
  if (IsDevNull(filename.c_str())) {
    return true;  // mimic write(2) behavior with /dev/null
  }
  return WriteFile(data, size, Path(filename), perm);
}

bool WriteFile(const void* data, size_t size, const Path& path,
               unsigned int perm) {
  UnlinkPathW(path.AsNativePath());  // We don't care about the success of this.
  AutoHandle handle(::CreateFileW(
      /* lpFileName */ path.AsNativePath().c_str(),
      /* dwDesiredAccess */ GENERIC_WRITE,
      /* dwShareMode */ FILE_SHARE_READ,
      /* lpSecurityAttributes */ nullptr,
      /* dwCreationDisposition */ CREATE_ALWAYS,
      /* dwFlagsAndAttributes */ FILE_ATTRIBUTE_NORMAL,
      /* hTemplateFile */ nullptr));
  if (!handle.IsValid()) {
    return false;
  }

  // TODO(laszlocsomor): respect `perm` and set the file permissions accordingly
  DWORD actually_written = 0;
  ::WriteFile(handle, data, size, &actually_written, nullptr);
  return actually_written == size;
}

void InitializeStdOutErrForUtf8() { SetConsoleOutputCP(CP_UTF8); }

int WriteToStdOutErr(const void* data, size_t size, bool to_stdout) {
  DWORD written = 0;
  HANDLE h = ::GetStdHandle(to_stdout ? STD_OUTPUT_HANDLE : STD_ERROR_HANDLE);
  if (h == INVALID_HANDLE_VALUE) {
    return WriteResult::OTHER_ERROR;
  }

  if (::WriteFile(h, data, size, &written, nullptr)) {
    return (written == size) ? WriteResult::SUCCESS : WriteResult::OTHER_ERROR;
  } else {
    return (GetLastError() == ERROR_NO_DATA) ? WriteResult::BROKEN_PIPE
                                             : WriteResult::OTHER_ERROR;
  }
}

int RenameDirectory(const std::string& old_name, const std::string& new_name) {
  wstring wold_name;
  string error;
  if (!AsAbsoluteWindowsPath(old_name, &wold_name, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "RenameDirectory(" << old_name << ", " << new_name
        << "): AsAbsoluteWindowsPath(" << old_name << ") failed: " << error;
    return kRenameDirectoryFailureOtherError;
  }

  wstring wnew_name;
  if (!AsAbsoluteWindowsPath(new_name, &wnew_name, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "RenameDirectory(" << old_name << ", " << new_name
        << "): AsAbsoluteWindowsPath(" << new_name << ") failed: " << error;
    return kRenameDirectoryFailureOtherError;
  }

  if (!::MoveFileExW(wold_name.c_str(), wnew_name.c_str(),
                     MOVEFILE_COPY_ALLOWED | MOVEFILE_FAIL_IF_NOT_TRACKABLE |
                         MOVEFILE_WRITE_THROUGH)) {
    return GetLastError() == ERROR_ALREADY_EXISTS
               ? kRenameDirectoryFailureNotEmpty
               : kRenameDirectoryFailureOtherError;
  }
  return kRenameDirectorySuccess;
}

static bool UnlinkPathW(const wstring& path) {
  DWORD attrs = ::GetFileAttributesW(path.c_str());
  if (attrs == INVALID_FILE_ATTRIBUTES) {
    // Path does not exist.
    return false;
  }
  if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
    if (!(attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
      // Path is a directory; unlink(2) also cannot remove directories.
      return false;
    }
    // Otherwise it's a junction, remove using RemoveDirectoryW.
    return ::RemoveDirectoryW(path.c_str()) == TRUE;
  } else {
    // Otherwise it's a file, remove using DeleteFileW.
    return ::DeleteFileW(path.c_str()) == TRUE;
  }
}

bool UnlinkPath(const string& file_path) {
  if (IsDevNull(file_path.c_str())) {
    return false;
  }
  return UnlinkPath(Path(file_path));
}

bool UnlinkPath(const Path& path) { return UnlinkPathW(path.AsNativePath()); }

static bool RealPath(const WCHAR* path, unique_ptr<WCHAR[]>* result = nullptr) {
  // Attempt opening the path, which may be anything -- a file, a directory, a
  // symlink, even a dangling symlink is fine.
  // Follow reparse points, getting us that much closer to the real path.
  AutoHandle h(CreateFileW(path, 0, kAllShare, nullptr, OPEN_EXISTING,
                           FILE_FLAG_BACKUP_SEMANTICS, nullptr));
  if (!h.IsValid()) {
    // Path does not exist or it's a dangling junction/symlink.
    return false;
  }

  if (!result) {
    // The caller is only interested in whether the file exists, they aren't
    // interested in its real path. Since we just successfully opened the file
    // we already know it exists.
    // Also, GetFinalPathNameByHandleW is slow so avoid calling it if we can.
    return true;
  }

  // kMaxPath value: according to MSDN, maximum path length is 32767, and with
  // an extra null terminator that's exactly 0x8000.
  static constexpr size_t kMaxPath = 0x8000;
  std::unique_ptr<WCHAR[]> buf(new WCHAR[kMaxPath]);
  DWORD res = GetFinalPathNameByHandleW(h, buf.get(), kMaxPath, 0);
  if (res > 0 && res < kMaxPath) {
    *result = std::move(buf);
    return true;
  } else {
    return false;
  }
}

bool ReadDirectorySymlink(const blaze_util::Path& name, string* result) {
  unique_ptr<WCHAR[]> result_ptr;
  if (!RealPath(name.AsNativePath().c_str(), &result_ptr)) {
    return false;
  }
  *result = WstringToCstring(RemoveUncPrefixMaybe(result_ptr.get()));
  return true;
}

bool PathExists(const string& path) { return PathExists(Path(path)); }

bool PathExists(const Path& path) {
  if (path.IsEmpty()) {
    return false;
  }
  if (path.IsNull()) {
    return true;
  }
  return RealPath(path.AsNativePath().c_str(), nullptr);
}

string MakeCanonical(const char* path) {
  if (IsDevNull(path)) {
    return "NUL";
  }
  if (path == nullptr || path[0] == 0) {
    return "";
  }

  std::wstring wpath;
  string error;
  if (!AsAbsoluteWindowsPath(path, &wpath, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "MakeCanonical(" << path
        << "): AsAbsoluteWindowsPath failed: " << error;
  }

  std::unique_ptr<WCHAR[]> long_realpath;
  if (!RealPath(wpath.c_str(), &long_realpath)) {
    return "";
  }

  // Convert the path to lower-case.
  size_t size =
      wcslen(long_realpath.get()) - (HasUncPrefix(long_realpath.get()) ? 4 : 0);
  unique_ptr<WCHAR[]> lcase_realpath(new WCHAR[size + 1]);
  const WCHAR* p_from = RemoveUncPrefixMaybe(long_realpath.get());
  WCHAR* p_to = lcase_realpath.get();
  while (size-- > 0) {
    *p_to++ = towlower(*p_from++);
  }
  *p_to = 0;
  return WstringToCstring(lcase_realpath.get());
}

static bool CanReadFileW(const wstring& path) {
  AutoHandle handle(CreateFileW(path.c_str(), GENERIC_READ, kAllShare, nullptr,
                                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr));
  return handle.IsValid();
}

bool CanReadFile(const std::string& path) {
  return CanReadFile(Path(path));
}

bool CanReadFile(const Path& path) {
  return CanReadFileW(path.AsNativePath());
}

bool CanExecuteFile(const std::string& path) {
  return CanExecuteFile(Path(path));
}

bool CanExecuteFile(const Path& path) {
  std::wstring p = path.AsNativePath();
  if (p.size() < 4) {
    return false;
  }
  std::wstring ext = p.substr(p.size() - 4);
  return CanReadFileW(p) &&
         (ext == L".exe" || ext == L".com" || ext == L".cmd" || ext == L".bat");
}

bool CanAccessDirectory(const std::string& path) {
  return CanAccessDirectory(Path(path));
}

bool CanAccessDirectory(const Path& path) {
  DWORD attr = ::GetFileAttributesW(path.AsNativePath().c_str());
  if ((attr == INVALID_FILE_ATTRIBUTES) || !(attr & FILE_ATTRIBUTE_DIRECTORY)) {
    // The path doesn't exist or is not a directory.
    return false;
  }

  // The only easy way to know if a directory is writable is by attempting to
  // open a file for writing in it.
  // File name with Thread ID avoids races among concurrent Bazel processes.
  std::string dummy_name = "bazel_directory_access_test_";
  dummy_name += std::to_string(::GetCurrentThreadId());

  Path dummy_path = path.GetRelative(dummy_name);

  // Attempt to open the dummy file for read/write access.
  // If the file happens to exist, no big deal, we won't overwrite it thanks to
  // OPEN_ALWAYS.
  HANDLE handle = ::CreateFileW(
      /* lpFileName */ dummy_path.AsNativePath().c_str(),
      /* dwDesiredAccess */ GENERIC_WRITE | GENERIC_READ,
      /* dwShareMode */ kAllShare,
      /* lpSecurityAttributes */ nullptr,
      /* dwCreationDisposition */ OPEN_ALWAYS,
      /* dwFlagsAndAttributes */ FILE_ATTRIBUTE_NORMAL,
      /* hTemplateFile */ nullptr);
  DWORD err = GetLastError();
  if (handle == INVALID_HANDLE_VALUE) {
    // We couldn't open the file, and not because the dummy file already exists.
    // Consequently it is because `path` doesn't exist.
    return false;
  }
  // The fact that we could open the file, regardless of it existing beforehand
  // or not, means the directory also exists and we can read/write in it.
  CloseHandle(handle);
  if (err != ERROR_ALREADY_EXISTS) {
    // The file didn't exist before, but due to OPEN_ALWAYS we created it just
    // now, so do delete it.
    ::DeleteFileW(dummy_path.AsNativePath().c_str());
  }  // Otherwise the file existed before, leave it alone.
  return true;
}

bool IsDirectoryW(const wstring& path) {
  // Attempt opening the path, which may be anything -- a file, a directory, a
  // symlink, even a dangling symlink is fine.
  // Follow reparse points in order to return false for dangling ones.
  AutoHandle h(CreateFileW(path.c_str(), 0, kAllShare, nullptr, OPEN_EXISTING,
                           FILE_FLAG_BACKUP_SEMANTICS, nullptr));
  BY_HANDLE_FILE_INFORMATION info;
  return h.IsValid() && GetFileInformationByHandle(h, &info) &&
         info.dwFileAttributes != INVALID_FILE_ATTRIBUTES &&
         (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
}

bool IsDirectory(const string& path) { return IsDirectory(Path(path)); }

bool IsDirectory(const Path& path) {
  if (path.IsEmpty() || path.IsNull()) {
    return false;
  }
  return IsDirectoryW(path.AsNativePath());
}

void SyncFile(const string& path) {
  // No-op on Windows native; unsupported by Cygwin.
  // fsync always fails on Cygwin with "Permission denied" for some reason.
}

void SyncFile(const Path& path) {}

bool MakeDirectoriesW(const wstring& path, unsigned int mode) {
  if (path.empty()) {
    return false;
  }
  std::wstring abs_path;
  std::string error;
  if (!AsAbsoluteWindowsPath(path, &abs_path, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "MakeDirectoriesW(" << blaze_util::WstringToCstring(path)
        << "): " << error;
  }
  if (IsRootDirectoryW(abs_path) || IsDirectoryW(abs_path)) {
    return true;
  }
  wstring parent = SplitPathW(abs_path).first;
  if (parent.empty()) {
    // Since `abs_path` is not a root directory, there should have been at least
    // one directory above it.
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "MakeDirectoriesW(" << blaze_util::WstringToCstring(abs_path)
        << ") could not find dirname: " << GetLastErrorString();
  }
  return MakeDirectoriesW(parent, mode) &&
         ::CreateDirectoryW(abs_path.c_str(), nullptr) == TRUE;
}

bool MakeDirectories(const string& path, unsigned int mode) {
  // TODO(laszlocsomor): respect `mode` to the extent that it's possible on
  // Windows; it's currently ignored.
  if (path.empty() || IsDevNull(path.c_str())) {
    return false;
  }
  wstring wpath;
  // According to MSDN, CreateDirectory's limit without the UNC prefix is
  // 248 characters (so it could fit another filename before reaching MAX_PATH).
  string error;
  if (!AsAbsoluteWindowsPath(path, &wpath, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "MakeDirectories(" << path
        << "): AsAbsoluteWindowsPath failed: " << error;
    return false;
  }
  return MakeDirectoriesW(wpath, mode);
}

bool MakeDirectories(const Path& path, unsigned int mode) {
  return MakeDirectoriesW(path.AsNativePath(), mode);
}

string CreateTempDir(const std::string &prefix) {
  string result = prefix + blaze_util::ToString(GetCurrentProcessId());
  if (!blaze_util::MakeDirectories(result, 0777)) {
    BAZEL_DIE(blaze_exit_code::INTERNAL_ERROR)
        << "couldn't create '" << result
        << "': " << blaze_util::GetLastErrorString();
  }
  return result;
}

static bool RemoveContents(wstring path) {
  static const wstring kDot(L".");
  static const wstring kDotDot(L"..");

  if (path.find(L"\\\\?\\") != 0) {
    path = wstring(L"\\\\?\\") + path;
  }
  if (path.back() != '\\') {
    path.push_back('\\');
  }

  WIN32_FIND_DATAW metadata;
  HANDLE handle = FindFirstFileW((path + L"*").c_str(), &metadata);
  if (handle == INVALID_HANDLE_VALUE) {
    return true;  // directory doesn't exist
  }

  bool result = true;
  do {
    wstring childname = metadata.cFileName;
    if (kDot != childname && kDotDot != childname) {
      wstring childpath = path + childname;
      if ((metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
        // If this is not a junction, delete its contents recursively.
        // Finally delete this directory/junction too.
        if (((metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) == 0 &&
             !RemoveContents(childpath)) ||
            !::RemoveDirectoryW(childpath.c_str())) {
          result = false;
          break;
        }
      } else {
        if (!::DeleteFileW(childpath.c_str())) {
          result = false;
          break;
        }
      }
    }
  } while (FindNextFileW(handle, &metadata));
  FindClose(handle);
  return result;
}

static bool RemoveRecursivelyW(const wstring& path) {
  DWORD attrs = ::GetFileAttributesW(path.c_str());
  if (attrs == INVALID_FILE_ATTRIBUTES) {
    // Path does not exist.
    return true;
  }
  if (attrs & FILE_ATTRIBUTE_DIRECTORY) {
    if (!(attrs & FILE_ATTRIBUTE_REPARSE_POINT)) {
      // Path is a directory; unlink(2) also cannot remove directories.
      return RemoveContents(path) && ::RemoveDirectoryW(path.c_str());
    }
    // Otherwise it's a junction, remove using RemoveDirectoryW.
    return ::RemoveDirectoryW(path.c_str()) == TRUE;
  } else {
    // Otherwise it's a file, remove using DeleteFileW.
    return ::DeleteFileW(path.c_str()) == TRUE;
  }
}

bool RemoveRecursively(const string& path) {
  return RemoveRecursivelyW(Path(path).AsNativePath());
}

static inline void ToLowerW(WCHAR* p) {
  while (*p) {
    *p++ = towlower(*p);
  }
}

std::wstring GetCwdW() {
  static constexpr size_t kBufSmall = MAX_PATH;
  WCHAR buf[kBufSmall];
  DWORD len = GetCurrentDirectoryW(kBufSmall, buf);
  if (len == 0) {
    DWORD err = GetLastError();
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "GetCurrentDirectoryW failed (error " << err << ")";
  }

  if (len < kBufSmall) {
    ToLowerW(buf);
    return std::wstring(buf);
  }

  unique_ptr<WCHAR[]> buf_big(new WCHAR[len]);
  len = GetCurrentDirectoryW(len, buf_big.get());
  if (len == 0) {
    DWORD err = GetLastError();
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "GetCurrentDirectoryW failed (error " << err << ")";
  }
  ToLowerW(buf_big.get());
  return std::wstring(buf_big.get());
}

string GetCwd() {
  return WstringToCstring(RemoveUncPrefixMaybe(GetCwdW().c_str()));
}

bool ChangeDirectory(const string& path) {
  string spath;
  string error;
  if (!AsShortWindowsPath(path, &spath, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "ChangeDirectory(" << path << "): failed: " << error;
  }
  return ::SetCurrentDirectoryA(spath.c_str()) == TRUE;
}

class DirectoryTreeWalkerW : public DirectoryEntryConsumerW {
 public:
  DirectoryTreeWalkerW(vector<wstring>* files,
                       _ForEachDirectoryEntryW walk_entries)
      : _files(files), _walk_entries(walk_entries) {}

  void Consume(const wstring& path, bool follow_directory) override {
    if (follow_directory) {
      Walk(path);
    } else {
      _files->push_back(path);
    }
  }

  void Walk(const wstring& path) { _walk_entries(path, this); }

 private:
  vector<wstring>* _files;
  _ForEachDirectoryEntryW _walk_entries;
};

void ForEachDirectoryEntryW(const wstring& path,
                            DirectoryEntryConsumerW* consume) {
  wstring wpath;
  if (path.empty() || IsDevNull(path.c_str())) {
    return;
  }
  string error;
  if (!AsWindowsPath(path, &wpath, &error)) {
    std::string err = GetLastErrorString();
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "ForEachDirectoryEntryW(" << WstringToCstring(path)
        << "): AsWindowsPath failed: " << err;
  }

  static const wstring kUncPrefix(L"\\\\?\\");
  static const wstring kDot(L".");
  static const wstring kDotDot(L"..");
  // Always add an UNC prefix to ensure we can work with long paths.
  if (!HasUncPrefix(wpath.c_str())) {
    wpath = kUncPrefix + wpath;
  }
  // Unconditionally add a trailing backslash. We know `wpath` has no trailing
  // backslash because it comes from AsWindowsPath whose output is always
  // normalized (see NormalizeWindowsPath).
  wpath.append(L"\\");
  WIN32_FIND_DATAW metadata;
  HANDLE handle = ::FindFirstFileW((wpath + L"*").c_str(), &metadata);
  if (handle == INVALID_HANDLE_VALUE) {
    return;  // directory does not exist or is empty
  }

  do {
    if (kDot != metadata.cFileName && kDotDot != metadata.cFileName) {
      wstring wname = wpath + metadata.cFileName;
      wstring name(/* omit prefix */ 4 + wname.c_str());
      bool is_dir = (metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
      bool is_junc =
          (metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
      consume->Consume(name, is_dir && !is_junc);
    }
  } while (::FindNextFileW(handle, &metadata));
  ::FindClose(handle);
}

void GetAllFilesUnderW(const wstring& path, vector<wstring>* result) {
  _GetAllFilesUnderW(path, result, &ForEachDirectoryEntryW);
}

void _GetAllFilesUnderW(const wstring& path, vector<wstring>* result,
                        _ForEachDirectoryEntryW walk_entries) {
  DirectoryTreeWalkerW(result, walk_entries).Walk(path);
}

void ForEachDirectoryEntry(const string &path,
                           DirectoryEntryConsumer *consume) {
  wstring wpath;
  if (path.empty() || IsDevNull(path.c_str())) {
    return;
  }
  string error;
  if (!AsWindowsPath(path, &wpath, &error)) {
    BAZEL_DIE(blaze_exit_code::LOCAL_ENVIRONMENTAL_ERROR)
        << "ForEachDirectoryEntry(" << path
        << "): AsWindowsPath failed: " << GetLastErrorString();
  }

  static const wstring kUncPrefix(L"\\\\?\\");
  static const wstring kDot(L".");
  static const wstring kDotDot(L"..");
  // Always add an UNC prefix to ensure we can work with long paths.
  if (!HasUncPrefix(wpath.c_str())) {
    wpath = kUncPrefix + wpath;
  }
  // Unconditionally add a trailing backslash. We know `wpath` has no trailing
  // backslash because it comes from AsWindowsPath whose output is always
  // normalized (see NormalizeWindowsPath).
  wpath.append(L"\\");
  WIN32_FIND_DATAW metadata;
  HANDLE handle = ::FindFirstFileW((wpath + L"*").c_str(), &metadata);
  if (handle == INVALID_HANDLE_VALUE) {
    return;  // directory does not exist or is empty
  }

  do {
    if (kDot != metadata.cFileName && kDotDot != metadata.cFileName) {
      wstring wname = wpath + metadata.cFileName;
      string name(WstringToCstring(/* omit prefix */ 4 + wname.c_str()));
      bool is_dir = (metadata.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
      bool is_junc =
          (metadata.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0;
      consume->Consume(name, is_dir && !is_junc);
    }
  } while (::FindNextFileW(handle, &metadata));
  ::FindClose(handle);
}

}  // namespace blaze_util
