// 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 "bin/directory.h"

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

#include "bin/platform.h"


static int SetOsErrorMessage(char* os_error_message,
                             int os_error_message_len) {
  int error_code = GetLastError();
  DWORD message_size =
      FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                    NULL,
                    error_code,
                    MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                    os_error_message,
                    os_error_message_len,
                    NULL);
  if (message_size == 0) {
    if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
      fprintf(stderr, "FormatMessage failed %d\n", GetLastError());
    }
    snprintf(os_error_message, os_error_message_len, "OS Error %d", error_code);
  }
  os_error_message[os_error_message_len - 1] = '\0';
  return error_code;
}


// Forward declaration.
static bool ListRecursively(const char* dir_name,
                            bool recursive,
                            DirectoryListing* listing);
static bool DeleteRecursively(const char* dir_name);


static bool HandleDir(char* dir_name,
                      char* path,
                      int path_length,
                      bool recursive,
                      DirectoryListing* listing) {
  if (strcmp(dir_name, ".") != 0 &&
      strcmp(dir_name, "..") != 0) {
    size_t written = snprintf(path + path_length,
                              MAX_PATH - path_length,
                              "%s",
                              dir_name);
    if (written != strlen(dir_name)) {
      return false;
    }
    bool ok = listing->HandleDirectory(path);
    if (!ok) return ok;
    if (recursive) {
      return ListRecursively(path, recursive, listing);
    }
  }
  return true;
}


static bool HandleFile(char* file_name,
                       char* path,
                       int path_length,
                       DirectoryListing* listing) {
  size_t written = snprintf(path + path_length,
                            MAX_PATH - path_length,
                            "%s",
                            file_name);
  if (written != strlen(file_name)) {
    return false;
  };
  return listing->HandleFile(path);
}


static bool HandleEntry(LPWIN32_FIND_DATA find_file_data,
                        char* path,
                        int path_length,
                        bool recursive,
                        DirectoryListing* listing) {
  DWORD attributes = find_file_data->dwFileAttributes;
  if ((attributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
    return HandleDir(find_file_data->cFileName,
                     path,
                     path_length,
                     recursive,
                     listing);
  } else {
    return HandleFile(find_file_data->cFileName, path, path_length, listing);
  }
}


// ComputeFullSearchPath must be called with a path array of size at
// least MAX_PATH.
static bool ComputeFullSearchPath(const char* dir_name,
                                  char* path,
                                  int* path_length) {
  // GetFullPathName only works in a multi-threaded environment if
  // SetCurrentDirectory is not used. We currently have no plan for
  // exposing SetCurrentDirectory.
  size_t written = GetFullPathName(dir_name, MAX_PATH, path, NULL);
  // GetFullPathName only accepts input strings of size less than
  // MAX_PATH and returns 0 to indicate failure for paths longer than
  // that. Therefore the path buffer is always big enough.
  if (written == 0) {
    return false;
  }
  *path_length = written;
  written = snprintf(path + *path_length,
                     MAX_PATH - *path_length,
                     "%s",
                     "\\*");
  if (written != 2) {
    return false;
  }
  *path_length += written;
  return true;
}

static void PostError(DirectoryListing* listing,
                      const char* dir_name) {
  listing->HandleError(dir_name);
}


static bool ListRecursively(const char* dir_name,
                            bool recursive,
                            DirectoryListing* listing) {
  // Compute full path for the directory currently being listed.  The
  // path buffer will be used to construct the current path in the
  // recursive traversal. path_length does not always equal
  // strlen(path) but indicates the current prefix of path that is the
  // path of the current directory in the traversal.
  char* path = static_cast<char*>(malloc(MAX_PATH));
  int path_length = 0;
  bool valid = ComputeFullSearchPath(dir_name, path, &path_length);
  if (!valid) {
    PostError(listing, dir_name);
    free(path);
    return false;
  }

  WIN32_FIND_DATA find_file_data;
  HANDLE find_handle = FindFirstFile(path, &find_file_data);

  // Adjust the path by removing the '*' used for the search.
  path_length -= 1;
  path[path_length] = '\0';

  if (find_handle == INVALID_HANDLE_VALUE) {
    PostError(listing, path);
    free(path);
    return false;
  }

  bool success = HandleEntry(&find_file_data,
                             path,
                             path_length,
                             recursive,
                             listing);

  while ((FindNextFile(find_handle, &find_file_data) != 0)) {
    success = HandleEntry(&find_file_data,
                          path,
                          path_length,
                          recursive,
                          listing) && success;
  }

  if (GetLastError() != ERROR_NO_MORE_FILES) {
    success = false;
    PostError(listing, dir_name);
  }

  if (FindClose(find_handle) == 0) {
    success = false;
    PostError(listing, dir_name);
  }
  free(path);

  return success;
}


static bool DeleteFile(char* file_name,
                       char* path,
                       int path_length) {
  size_t written = snprintf(path + path_length,
                            MAX_PATH - path_length,
                            "%s",
                            file_name);
  if (written != strlen(file_name)) {
    return false;
  }

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

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

      if (SetFileAttributes(path, attributes) == 0) {
        return false;
      }

      return DeleteFile(path) != 0;
    }
  }

  return false;
}


static bool DeleteDir(char* dir_name,
                      char* path,
                      int path_length) {
  if (strcmp(dir_name, ".") != 0 &&
      strcmp(dir_name, "..") != 0) {
    size_t written = snprintf(path + path_length,
                              MAX_PATH - path_length,
                              "%s",
                              dir_name);
    if (written != strlen(dir_name)) {
      return false;
    }
    return DeleteRecursively(path);
  }
  return true;
}


static bool DeleteEntry(LPWIN32_FIND_DATA find_file_data,
                        char* path,
                        int path_length) {
  DWORD attributes = find_file_data->dwFileAttributes;

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


static bool DeleteRecursively(const char* dir_name) {
  // If the directory is a junction, it's pointing to some other place in the
  // filesystem that we do not want to recurse into.
  DWORD attributes = GetFileAttributes(dir_name);
  if ((attributes != INVALID_FILE_ATTRIBUTES) &&
      (attributes & FILE_ATTRIBUTE_REPARSE_POINT) != 0) {
    // Just delete the junction itself.
    return RemoveDirectory(dir_name) != 0;
  }

  // Compute full path for the directory currently being deleted.  The
  // path buffer will be used to construct the current path in the
  // recursive traversal. path_length does not always equal
  // strlen(path) but indicates the current prefix of path that is the
  // path of the current directory in the traversal.
  char* path = static_cast<char*>(malloc(MAX_PATH));
  int path_length = 0;
  bool valid = ComputeFullSearchPath(dir_name, path, &path_length);
  if (!valid) {
    free(path);
    return false;
  }

  WIN32_FIND_DATA find_file_data;
  HANDLE find_handle = FindFirstFile(path, &find_file_data);

  // Adjust the path by removing the '*' used for the search.
  path_length -= 1;
  path[path_length] = '\0';

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

  bool success = DeleteEntry(&find_file_data, path, path_length);

  while ((FindNextFile(find_handle, &find_file_data) != 0) && success) {
    success = success && DeleteEntry(&find_file_data, path, path_length);
  }

  free(path);

  if ((GetLastError() != ERROR_NO_MORE_FILES) ||
      (FindClose(find_handle) == 0) ||
      (RemoveDirectory(dir_name) == 0)) {
    return false;
  }

  return success;
}


bool Directory::List(const char* dir_name,
                     bool recursive,
                     DirectoryListing* listing) {
  bool completed = ListRecursively(dir_name, recursive, listing);
  return completed;
}


Directory::ExistsResult Directory::Exists(const char* dir_name) {
  DWORD attributes = GetFileAttributes(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 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 UNKNOWN;
    }
  }
  bool exists = (attributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
  return exists ? EXISTS : DOES_NOT_EXIST;
}


char* Directory::Current() {
  char* result;
  int length = GetCurrentDirectory(0, NULL);
  result = reinterpret_cast<char*>(malloc(length + 1));
  GetCurrentDirectory(length + 1, result);
  return result;
}


bool Directory::Create(const char* dir_name) {
  return (CreateDirectory(dir_name, NULL) != 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.
  char* path = static_cast<char*>(malloc(MAX_PATH));
  int path_length;
  if (0 == strncmp(const_template, "", 1)) {
    path_length = GetTempPath(MAX_PATH, path);
    if (path_length == 0) {
      free(path);
      return NULL;
    }
  } else {
    snprintf(path, MAX_PATH, "%s", const_template);
    path_length = strlen(path);
  }
  // Length of tempdir-xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx is 44.
  if (path_length > MAX_PATH - 44) {
    free(path);
    return NULL;
  }
  if ((path)[path_length - 1] == '\\') {
    // No base name for the directory - use "tempdir".
    snprintf(path + path_length, MAX_PATH - path_length, "tempdir");
    path_length = strlen(path);
  }

  UUID uuid;
  RPC_STATUS status = UuidCreateSequential(&uuid);
  if (status != RPC_S_OK && status != RPC_S_UUID_LOCAL_ONLY) {
    free(path);
    return NULL;
  }
  RPC_CSTR uuid_string;
  status = UuidToString(&uuid, &uuid_string);
  if (status != RPC_S_OK) {
    free(path);
    return NULL;
  }

  snprintf(path + path_length, MAX_PATH - path_length, "-%s", uuid_string);
  if (!CreateDirectory(path, NULL)) {
    free(path);
    return NULL;
  }
  return path;
}


bool Directory::Delete(const char* dir_name, bool recursive) {
  if (!recursive) {
    return (RemoveDirectory(dir_name) != 0);
  } else {
    return DeleteRecursively(dir_name);
  }
}


bool Directory::Rename(const char* path, const char* new_path) {
  ExistsResult exists = Exists(path);
  if (exists != EXISTS) return false;
  ExistsResult new_exists = Exists(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 = DeleteRecursively(new_path);
    if (!success) return false;
  }
  DWORD flags = MOVEFILE_WRITE_THROUGH;
  return (MoveFileEx(path, new_path, flags) != 0);
}
