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

#include "bin/directory.h"
#include "bin/file.h"

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

#include "bin/log.h"

#undef DeleteFile

namespace dart {
namespace bin {

class PathBuffer {
 public:
  PathBuffer() : length(0) {
    data = new wchar_t[MAX_PATH + 1];
  }

  ~PathBuffer() {
    delete[] data;
  }

  wchar_t* data;
  int length;

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

  void Reset(int new_length) {
    length = new_length;
    data[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 ListRecursively(PathBuffer* path,
                            bool recursive,
                            bool follow_links,
                            LinkList* seen,
                            DirectoryListing* listing);
static bool DeleteRecursively(PathBuffer* path);


static void PostError(DirectoryListing* listing,
                      const wchar_t* dir_name) {
  const char* utf8_path = StringUtils::WideToUtf8(dir_name);
  listing->HandleError(utf8_path);
  free(const_cast<char*>(utf8_path));
}


static bool HandleDir(wchar_t* dir_name,
                      PathBuffer* path,
                      bool recursive,
                      bool follow_links,
                      LinkList* seen,
                      DirectoryListing* listing) {
  if (wcscmp(dir_name, L".") == 0) return true;
  if (wcscmp(dir_name, L"..") == 0) return true;
  if (!path->Add(dir_name)) {
    PostError(listing, path->data);
    return false;
  }
  char* utf8_path = StringUtils::WideToUtf8(path->data);
  bool ok = listing->HandleDirectory(utf8_path);
  free(utf8_path);
  return ok &&
      (!recursive ||
       ListRecursively(path, recursive, follow_links, seen, listing));
}


static bool HandleFile(wchar_t* file_name,
                       PathBuffer* path,
                       DirectoryListing* listing) {
  if (!path->Add(file_name)) {
    PostError(listing, path->data);
    return false;
  }
  char* utf8_path = StringUtils::WideToUtf8(path->data);
  bool ok = listing->HandleFile(utf8_path);
  free(utf8_path);
  return ok;
}


static bool HandleLink(wchar_t* link_name,
                       PathBuffer* path,
                       DirectoryListing* listing) {
  if (!path->Add(link_name)) {
    PostError(listing, path->data);
    return false;
  }
  char* utf8_path = StringUtils::WideToUtf8(path->data);
  bool ok = listing->HandleLink(utf8_path);
  free(utf8_path);
  return ok;
}


static bool HandleEntry(LPWIN32_FIND_DATAW find_file_data,
                        PathBuffer* path,
                        bool recursive,
                        bool follow_links,
                        LinkList* seen,
                        DirectoryListing* listing) {
  DWORD attributes = find_file_data->dwFileAttributes;
  if ((attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
    if (!follow_links) {
      return HandleLink(find_file_data->cFileName, path, listing);
    }
    int path_length = path->length;
    if (!path->Add(find_file_data->cFileName)) return false;
    HANDLE handle = CreateFileW(
        path->data,
        0,
        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
        NULL,
        OPEN_EXISTING,
        FILE_FLAG_BACKUP_SEMANTICS,
        NULL);
    path->Reset(path_length);
    if (handle == INVALID_HANDLE_VALUE) {
      // Report as (broken) link.
      return HandleLink(find_file_data->cFileName, path, listing);
    }
    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);
        PostError(listing, path->data);
        return false;
      }
      CloseHandle(handle);
      current_link.volume = info.dwVolumeSerialNumber;
      current_link.id_low = info.nFileIndexLow;
      current_link.id_high = info.nFileIndexHigh;
      current_link.next = seen;
      LinkList* previous = seen;
      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 HandleLink(find_file_data->cFileName, path, listing);
        }
        previous = previous->next;
      }
      // Recurse into the directory, adding current link to the seen links list.
      return HandleDir(find_file_data->cFileName,
                       path,
                       recursive,
                       follow_links,
                       &current_link,
                       listing);
    }
  }
  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    return HandleDir(find_file_data->cFileName,
                     path,
                     recursive,
                     follow_links,
                     seen,
                     listing);
  } else {
    return HandleFile(find_file_data->cFileName, path, listing);
  }
}


static bool ListRecursively(PathBuffer* path,
                            bool recursive,
                            bool follow_links,
                            LinkList* seen,
                            DirectoryListing* listing) {
  if (!path->Add(L"\\*")) {
    PostError(listing, path->data);
    return false;
  }

  WIN32_FIND_DATAW find_file_data;
  HANDLE find_handle = FindFirstFileW(path->data, &find_file_data);

  // Adjust the path by removing the '*' used for the search.
  path->Reset(path->length - 1);

  if (find_handle == INVALID_HANDLE_VALUE) {
    PostError(listing, path->data);
    return false;
  }

  int path_length = path->length;
  bool success = HandleEntry(&find_file_data,
                             path,
                             recursive,
                             follow_links,
                             seen,
                             listing);

  while ((FindNextFileW(find_handle, &find_file_data) != 0)) {
    path->Reset(path_length);  // HandleEntry adds the entry name to path.
    success = HandleEntry(&find_file_data,
                          path,
                          recursive,
                          follow_links,
                          seen,
                          listing) && success;
  }

  if (GetLastError() != ERROR_NO_MORE_FILES) {
    success = false;
    PostError(listing, path->data);
  }

  if (FindClose(find_handle) == 0) {
    success = false;
    PostError(listing, path->data);
  }

  return success;
}


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

  if (DeleteFileW(path->data) != 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->data);
    if (attributes == INVALID_FILE_ATTRIBUTES) {
      return false;
    }

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

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

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

  return false;
}


static bool DeleteDir(wchar_t* dir_name, PathBuffer* path) {
  if (wcscmp(dir_name, L".") == 0) return true;
  if (wcscmp(dir_name, L"..") == 0) return true;
  return path->Add(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) {
  DWORD attributes = GetFileAttributesW(path->data);
  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(path->data) != 0;
  }
  // If it's a file, remove it directly.
  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == 0) {
    return DeleteFile(L"", path);
  }

  if (!path->Add(L"\\*")) return false;

  WIN32_FIND_DATAW find_file_data;
  HANDLE find_handle = FindFirstFileW(path->data, &find_file_data);

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

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

  bool success = DeleteEntry(&find_file_data, path);

  while ((FindNextFileW(find_handle, &find_file_data) != 0) && success) {
    path->Reset(path_length);  // DeleteEntry adds to the path.
    success = success && DeleteEntry(&find_file_data, path);
  }

  path->Reset(path_length - 1);  // Drop the "\" from the end of the path.
  if ((GetLastError() != ERROR_NO_MORE_FILES) ||
      (FindClose(find_handle) == 0) ||
      (RemoveDirectoryW(path->data) == 0)) {
    return false;
  }

  return success;
}


bool Directory::List(const char* dir_name,
                     bool recursive,
                     bool follow_links,
                     DirectoryListing* listing) {
  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
  PathBuffer path;
  if (!path.Add(system_name)) {
    PostError(listing, system_name);
    return false;
  }
  free(const_cast<wchar_t*>(system_name));
  return ListRecursively(&path, recursive, follow_links, NULL, listing);
}


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(const char* dir_name) {
  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
  Directory::ExistsResult result = ExistsHelper(system_name);
  free(const_cast<wchar_t*>(system_name));
  return result;
}


char* Directory::Current() {
  int length = GetCurrentDirectoryW(0, NULL);
  wchar_t* current = new wchar_t[length + 1];
  GetCurrentDirectoryW(length + 1, current);
  char* result = StringUtils::WideToUtf8(current);
  delete[] current;
  return result;
}


bool Directory::Create(const char* dir_name) {
  const wchar_t* system_name = StringUtils::Utf8ToWide(dir_name);
  int create_status = CreateDirectoryW(system_name, NULL);
  // If the directory already existed, treat it as a success.
  if (create_status == 0 &&
      GetLastError() == ERROR_ALREADY_EXISTS &&
      ExistsHelper(system_name) == EXISTS) {
    free(const_cast<wchar_t*>(system_name));
    return true;
  }
  free(const_cast<wchar_t*>(system_name));
  return (create_status != 0);
}


char* Directory::CreateTemp(const char* const_template) {
  // Returns a new, unused directory name, modifying the contents of
  // dir_template.  Creates this directory, with a default security
  // descriptor inherited from its parent directory.
  // The return value must be freed by the caller.
  PathBuffer path;
  if (0 == strncmp(const_template, "", 1)) {
    path.length = GetTempPathW(MAX_PATH, path.data);
    if (path.length == 0) {
      return NULL;
    }
  } else {
    const wchar_t* system_template = StringUtils::Utf8ToWide(const_template);
    path.Add(system_template);
    free(const_cast<wchar_t*>(system_template));
  }
  // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44.
  if (path.length > MAX_PATH - 44) {
    return NULL;
  }
  if ((path.data)[path.length - 1] == L'\\') {
    // No base name for the directory - use "tempdir".
    path.Add(L"tempdir");
  }

  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;
  }

  path.Add(L"-");
  // RPC_WSTR is an unsigned short*, so we cast to wchar_t*.
  path.Add(reinterpret_cast<wchar_t*>(uuid_string));
  RpcStringFreeW(&uuid_string);
  if (!CreateDirectoryW(path.data, NULL)) {
    return NULL;
  }
  char* result = StringUtils::WideToUtf8(path.data);
  return result;
}


bool Directory::Delete(const char* dir_name, bool recursive) {
  bool result = false;
  const wchar_t* system_dir_name = StringUtils::Utf8ToWide(dir_name);
  if (!recursive) {
    if (File::GetType(dir_name, true) == File::kIsDirectory) {
      result = (RemoveDirectoryW(system_dir_name) != 0);
    } else {
      SetLastError(ERROR_FILE_NOT_FOUND);
    }
  } else {
    PathBuffer path;
    if (path.Add(system_dir_name)) {
      result = DeleteRecursively(&path);
    }
  }
  free(const_cast<wchar_t*>(system_dir_name));
  return result;
}


bool Directory::Rename(const char* path, const char* new_path) {
  const wchar_t* system_path = StringUtils::Utf8ToWide(path);
  const wchar_t* system_new_path = StringUtils::Utf8ToWide(new_path);
  ExistsResult exists = ExistsHelper(system_path);
  if (exists != EXISTS) return false;
  ExistsResult new_exists = ExistsHelper(system_new_path);
  // MoveFile does not allow replacing exising directories. Therefore,
  // if the new_path is currently a directory we need to delete it
  // first.
  if (new_exists == EXISTS) {
    bool success = Delete(new_path, true);
    if (!success) return false;
  }
  DWORD flags = MOVEFILE_WRITE_THROUGH;
  int move_status =
      MoveFileExW(system_path, system_new_path, flags);
  free(const_cast<wchar_t*>(system_path));
  free(const_cast<wchar_t*>(system_new_path));
  return (move_status != 0);
}

}  // namespace bin
}  // namespace dart

#endif  // defined(TARGET_OS_WINDOWS)
