// Copyright 2015 Google Inc. 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.

// Adapted from file_util_posix.cc.

#include "base/file_util.h"

#include <stack>
#include <string>

#include "base/base_paths.h"
#include "base/basictypes.h"
#include "base/file_path.h"
#include "base/logging.h"
#include "base/path_service.h"
#include "base/platform_file.h"
#include "base/threading/thread_restrictions.h"
#include "base/time.h"
#include "starboard/directory.h"
#include "starboard/file.h"
#include "starboard/system.h"

namespace {

// The list of portable filename characters as per POSIX. This should be the
// lowest-common-denominator of acceptable filename characters.
const char kPortableFilenameCharacters[] = {
  "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  "abcdefghijklmnopqrstuvwxyz"
  "0123456789"
  "_-"
};
const int kPortableFilenameCharactersLength =
    SB_ARRAY_SIZE_INT(kPortableFilenameCharacters) - 1;

// 8 characters = 65 ^ 8 possible filenames, which gives a nice wide space for
// avoiding collisions.
const char kTempSubstitution[] = "XXXXXXXX";
const int kTempSubstitutionLength = SB_ARRAY_SIZE_INT(kTempSubstitution) - 1;

std::string TempFileName() {
  return std::string(".com.youtube.Cobalt.XXXXXXXX");
}

// Takes the template defined in |in_out_template| and destructively replaces
// any 'X' characters at the end with randomized portable filename characters.
void GenerateTempFileName(FilePath::StringType *in_out_template) {
  size_t template_start = in_out_template->find(kTempSubstitution);
  if (template_start == FilePath::StringType::npos) {
    // No pattern.
    return;
  }

  for (int i = 0; i < kTempSubstitutionLength; ++i) {
    uint64_t random = SbSystemGetRandomUInt64();
    int index = random % kPortableFilenameCharactersLength;
    (*in_out_template)[template_start + i] = kPortableFilenameCharacters[index];
  }
}

// Creates a random filename based on the TempFileName() pattern, creates the
// file, leaving it open, placing the path in |out_path| and returning the open
// SbFile.
SbFile CreateAndOpenTemporaryFile(FilePath directory, FilePath *out_path) {
  base::ThreadRestrictions::AssertIOAllowed();
  DCHECK(out_path);
  FilePath path = directory.Append(TempFileName());
  FilePath::StringType tmpdir_string = path.value();
  GenerateTempFileName(&tmpdir_string);
  *out_path = FilePath(tmpdir_string);
  return SbFileOpen(tmpdir_string.c_str(), kSbFileCreateOnly | kSbFileWrite,
                    NULL, NULL);
}

// Retries creating a temporary file until it can win the race to create a
// unique one.
SbFile CreateAndOpenTemporaryFileSafely(FilePath directory,
                                        FilePath *out_path) {
  SbFile file = kSbFileInvalid;
  while (!SbFileIsValid(file)) {
    file = CreateAndOpenTemporaryFile(directory, out_path);
  }
  return file;
}

bool CreateTemporaryDirInDirImpl(const FilePath &base_dir,
                                 const FilePath::StringType &name_tmpl,
                                 FilePath *new_dir) {
  base::ThreadRestrictions::AssertIOAllowed();
  DCHECK(name_tmpl.find(kTempSubstitution) != FilePath::StringType::npos)
      << "Directory name template must contain \"XXXXXXXX\".";

  FilePath dir_template = base_dir.Append(name_tmpl);
  std::string dir_template_string = dir_template.value();
  FilePath sub_dir;
  while (true) {
    std::string sub_dir_string = dir_template_string;
    GenerateTempFileName(&sub_dir_string);
    sub_dir = FilePath(sub_dir_string);
    if (!file_util::DirectoryExists(sub_dir)) {
      break;
    }
  }

  // NOTE: This is not as secure as mkdtemp, because it doesn't atomically
  // guarantee that there is no collision. But, with 8 X's it should be good
  // enough for our purposes.
  if (!file_util::CreateDirectory(sub_dir)) {
    DPLOG(ERROR) << "CreateDirectory";
    return false;
  }

  *new_dir = sub_dir;
  return true;
}

}  // namespace

namespace file_util {

bool AbsolutePath(FilePath* path) {
  // We don't have cross-platform tools for this, so we will just return true if
  // the path is already absolute.
  return path->IsAbsolute();
}

bool Delete(const FilePath &path, bool recursive) {
  base::ThreadRestrictions::AssertIOAllowed();
  const char *path_str = path.value().c_str();

  bool directory = SbDirectoryCanOpen(path_str);
  if (!recursive || !directory) {
    return SbFileDelete(path_str);
  }

  bool success = true;
  std::stack<std::string> directories;
  directories.push(path.value());

  // NOTE: Right now, for Linux, SbFileGetInfo does not follow
  // symlinks. This is good for avoiding deleting through symlinks, but makes it
  // hard to use symlinks on platforms where they are supported. This seems
  // safest for the lowest-common-denominator approach of pretending symlinks
  // don't exist.
  FileEnumerator traversal(
      path, true, FileEnumerator::FILES | FileEnumerator::DIRECTORIES);

  // Delete all files and push all directories in depth order onto the stack.
  for (FilePath current = traversal.Next();
       success && !current.empty();
       current = traversal.Next()) {
    FileEnumerator::FindInfo info;
    traversal.GetFindInfo(&info);

    if (FileEnumerator::IsDirectory(info)) {
      directories.push(current.value());
    } else {
      success = SbFileDelete(current.value().c_str());
    }
  }

  // Delete all directories in reverse-depth order, now that they have no more
  // regular files.
  while (success && !directories.empty()) {
    success = SbFileDelete(directories.top().c_str());
    directories.pop();
  }

  return success;
}

bool CopyFile(const FilePath &from_path, const FilePath &to_path) {
  base::ThreadRestrictions::AssertIOAllowed();

  base::PlatformFile source_file = base::CreatePlatformFile(
      from_path, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL,
      NULL);
  if (source_file == base::kInvalidPlatformFileValue) {
    DPLOG(ERROR) << "CopyFile(): Unable to open source file: "
                 << from_path.value();
    return false;
  }

  base::PlatformFile destination_file = base::CreatePlatformFileUnsafe(
      to_path, base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
      NULL, NULL);
  if (destination_file == base::kInvalidPlatformFileValue) {
    DPLOG(ERROR) << "CopyFile(): Unable to open destination file: "
                 << to_path.value();
    ignore_result(base::ClosePlatformFile(destination_file));
    return false;
  }

  const size_t kBufferSize = 32768;
  std::vector<char> buffer(kBufferSize);
  bool result = true;

  while (result) {
    int bytes_read = base::ReadPlatformFileAtCurrentPos(source_file, &buffer[0],
                                                        buffer.size());
    if (bytes_read < 0) {
      result = false;
      break;
    }

    if (bytes_read == 0) {
      break;
    }

    int bytes_written = base::WritePlatformFileAtCurrentPos(
        destination_file, &buffer[0], bytes_read);
    if (bytes_written < bytes_read) {
      DLOG(ERROR) << "CopyFile(): bytes_read (" << bytes_read
                  << ") > bytes_written (" << bytes_written << ")";
      // Because we use a best-effort write, if we wrote less than what was
      // available, something went wrong.
      result = false;
      break;
    }
  }

  if (!base::ClosePlatformFile(source_file)) {
    result = false;
  }

  if (!base::ClosePlatformFile(destination_file)) {
    result = false;
  }

  return result;
}

bool PathExists(const FilePath &path) {
  base::ThreadRestrictions::AssertIOAllowed();
  return SbFileExists(path.value().c_str());
}

bool PathIsWritable(const FilePath &path) {
  base::ThreadRestrictions::AssertIOAllowed();
  return SbFileCanOpen(path.value().c_str(), kSbFileOpenAlways | kSbFileWrite);
}

bool DirectoryExists(const FilePath& path) {
  base::ThreadRestrictions::AssertIOAllowed();
  SbFileInfo info;
  if (!SbFileGetPathInfo(path.value().c_str(), &info)) {
    return false;
  }

  return info.is_directory;
}

bool GetTempDir(FilePath *path) {
  char buffer[SB_FILE_MAX_PATH + 1] = {0};
  bool result = SbSystemGetPath(kSbSystemPathTempDirectory, buffer,
                                SB_ARRAY_SIZE_INT(buffer));
  if (!result) {
    return false;
  }

  *path = FilePath(buffer);
  if (DirectoryExists(*path)) {
    return true;
  }

  return CreateDirectory(*path);
}

bool GetShmemTempDir(FilePath *path, bool executable) {
  return GetTempDir(path);
}

FilePath GetHomeDir() {
  FilePath path;
  bool result = PathService::Get(base::DIR_HOME, &path);
  DCHECK(result);
  return path;
}

bool CreateTemporaryFile(FilePath *path) {
  base::ThreadRestrictions::AssertIOAllowed();
  DCHECK(path);

  FilePath directory;
  if (!GetTempDir(&directory)) {
    return false;
  }

  return CreateTemporaryFileInDir(directory, path);
}

bool CreateTemporaryFileInDir(const FilePath &dir, FilePath *temp_file) {
  base::ThreadRestrictions::AssertIOAllowed();
  DCHECK(temp_file);
  SbFile file = CreateAndOpenTemporaryFileSafely(dir, temp_file);
  return (SbFileIsValid(file) && SbFileClose(file));
}

bool CreateTemporaryDirInDir(const FilePath &base_dir,
                             const FilePath::StringType &prefix,
                             FilePath *new_dir) {
  FilePath::StringType mkdtemp_template = prefix + kTempSubstitution;
  return CreateTemporaryDirInDirImpl(base_dir, mkdtemp_template, new_dir);
}

bool CreateNewTempDirectory(const FilePath::StringType &prefix,
                            FilePath *new_temp_path) {
  FilePath tmpdir;
  if (!GetTempDir(&tmpdir)) {
    return false;
  }

  return CreateTemporaryDirInDirImpl(tmpdir, TempFileName(), new_temp_path);
}

bool CreateDirectory(const FilePath &full_path) {
  base::ThreadRestrictions::AssertIOAllowed();

  // Fast-path: can the full path be resolved from the full path?
  if (DirectoryExists(full_path) ||
      SbDirectoryCreate(full_path.value().c_str())) {
    return true;
  }

  // Slow-path: iterate through the paths and resolve from the root
  // to the leaf.
  std::vector<FilePath> subpaths;

  // Collect a list of all parent directories.
  FilePath last_path = full_path;
  subpaths.push_back(full_path);
  for (FilePath path = full_path.DirName();
       path.value() != last_path.value();
       path = path.DirName()) {
    subpaths.push_back(path);
    last_path = path;
  }

  // Root path is now at index 0.
  std::reverse(subpaths.begin(), subpaths.end());

  int existing_directory_index = -1;

  // Some platforms disallow access to some parent folders in the hierarchy.
  for (size_t i = 0; i < subpaths.size(); ++i) {
    const auto& path = subpaths[i];
    if (DirectoryExists(path)) {
      existing_directory_index = static_cast<int>(i);
    }
  }

  // No sub-directories existed, including the root.
  if (existing_directory_index < 0) {
    return false;
  }

  // Iterate through the parents and create the missing ones.
  for (size_t i = static_cast<size_t>(existing_directory_index);
       i < subpaths.size(); ++i) {
    const auto& path = subpaths[i];
    if (DirectoryExists(path)) {
      continue;
    }

    if (!SbDirectoryCreate(path.value().c_str())) {
      return false;
    }
  }

  return true;
}

bool IsLink(const FilePath &file_path) {
  base::ThreadRestrictions::AssertIOAllowed();
  SbFileInfo info;

  // If we can't SbfileGetPathInfo on the file, it's safe to assume that the
  // file won't at least be a 'followable' link.
  if (!SbFileGetPathInfo(file_path.value().c_str(), &info)) {
    return false;
  }

  return info.is_symbolic_link;
}

bool GetFileInfo(const FilePath &file_path, base::PlatformFileInfo *results) {
  base::ThreadRestrictions::AssertIOAllowed();
  SbFileInfo info;
  if (!SbFileGetPathInfo(file_path.value().c_str(), &info)) {
    return false;
  }

  results->is_directory = info.is_directory;
  results->size = info.size;
  results->last_modified = base::Time::FromSbTime(info.last_modified);
  results->last_accessed = base::Time::FromSbTime(info.last_accessed);
  results->creation_time = base::Time::FromSbTime(info.creation_time);
  return true;
}

int ReadFile(const FilePath &filename, char *data, int size) {
  base::ThreadRestrictions::AssertIOAllowed();

  base::PlatformFile file = base::CreatePlatformFile(
      filename, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_READ, NULL,
      NULL);
  if (file == base::kInvalidPlatformFileValue) {
    DLOG(ERROR) << "ReadFile(" << filename.value() << "): Unable to open.";
    return -1;
  }

  // We use a best-effort read here.
  int bytes_read = base::ReadPlatformFileAtCurrentPos(file, data, size);
  if (!base::ClosePlatformFile(file)) {
    DLOG(ERROR) << "ReadFile(" << filename.value() << "): Unable to close.";
    return -1;
  }

  return bytes_read;
}

int WriteFile(const FilePath &filename, const char *data, int size) {
  base::ThreadRestrictions::AssertIOAllowed();

  base::PlatformFile file = base::CreatePlatformFile(
      filename, base::PLATFORM_FILE_CREATE_ALWAYS | base::PLATFORM_FILE_WRITE,
      NULL, NULL);
  if (file == base::kInvalidPlatformFileValue) {
    DLOG(ERROR) << "WriteFile(" << filename.value() << "): Unable to open.";
    return -1;
  }

  // We use a best-effort write here.
  int bytes_written = base::WritePlatformFileAtCurrentPos(file, data, size);
  if (!base::ClosePlatformFile(file)) {
    DLOG(ERROR) << "WriteFile(" << filename.value() << "): Unable to close.";
    return -1;
  }

  return bytes_written;
}

int AppendToFile(const FilePath &filename, const char *data, int size) {
  base::ThreadRestrictions::AssertIOAllowed();
  base::PlatformFile file = base::CreatePlatformFile(
      filename, base::PLATFORM_FILE_OPEN | base::PLATFORM_FILE_WRITE, NULL,
      NULL);
  if (file == base::kInvalidPlatformFileValue) {
    DLOG(ERROR) << "AppendToFile(" << filename.value() << "): Unable to open.";
    return -1;
  }

  if (!base::SeekPlatformFile(file, base::PLATFORM_FILE_FROM_END, 0)) {
    DLOG(ERROR) << "AppendToFile(" << filename.value()
                << "): Unable to truncate.";
    return -1;
  }

  int bytes_written = base::WritePlatformFileAtCurrentPos(file, data, size);
  if (!base::ClosePlatformFile(file)) {
    DLOG(ERROR) << "AppendToFile(" << filename.value() << "): Unable to close.";
    return -1;
  }

  return bytes_written;
}

bool HasFileBeenModifiedSince(const FileEnumerator::FindInfo &find_info,
                              const base::Time &cutoff_time) {
  return FileEnumerator::GetLastModifiedTime(find_info) >= cutoff_time;
}


///////////////////////////////////////////////
// FileEnumerator

FileEnumerator::FileEnumerator(const FilePath &root_path,
                               bool recursive,
                               int file_type)
    : current_directory_entry_(0),
      root_path_(root_path),
      recursive_(recursive),
      file_type_(file_type) {
  // INCLUDE_DOT_DOT must not be specified if recursive.
  DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
  pending_paths_.push(root_path);
}

FileEnumerator::FileEnumerator(const FilePath &root_path,
                               bool recursive,
                               int file_type,
                               const FilePath::StringType &pattern)
    : current_directory_entry_(0),
      root_path_(root_path),
      recursive_(recursive),
      file_type_(file_type),
      pattern_(root_path.Append(pattern).value()) {
  // INCLUDE_DOT_DOT must not be specified if recursive.
  DCHECK(!(recursive && (INCLUDE_DOT_DOT & file_type_)));
  // The Windows version of this code appends the pattern to the root_path,
  // potentially only matching against items in the top-most directory.
  // Do the same here.
  if (pattern.empty()) {
    pattern_ = FilePath::StringType();
  }
  pending_paths_.push(root_path);
}

FileEnumerator::~FileEnumerator() {
}

FilePath FileEnumerator::Next() {
  ++current_directory_entry_;

  // While we've exhausted the entries in the current directory, do the next
  while (current_directory_entry_ >= directory_entries_.size()) {
    if (pending_paths_.empty()) {
      return FilePath();
    }

    root_path_ = pending_paths_.top();
    root_path_ = root_path_.StripTrailingSeparators();
    pending_paths_.pop();

    std::vector<DirectoryEntryInfo> entries;
    if (!ReadDirectory(&entries, root_path_)) {
      continue;
    }

    directory_entries_.clear();
    current_directory_entry_ = 0;
    for (std::vector<DirectoryEntryInfo>::const_iterator i = entries.begin();
         i != entries.end(); ++i) {
      FilePath full_path = root_path_.Append(i->filename);
      if (ShouldSkip(full_path)) {
        continue;
      }

      if (pattern_.size()) {
        NOTREACHED() << "Patterns not supported in Starboard.";
        continue;
      }

      if (recursive_ && i->sb_info.is_directory) {
        pending_paths_.push(full_path);
      }

      if ((i->sb_info.is_directory && (file_type_ & DIRECTORIES)) ||
          (!i->sb_info.is_directory && (file_type_ & FILES))) {
        directory_entries_.push_back(*i);
      }
    }
  }

  return
      root_path_.Append(directory_entries_[current_directory_entry_].filename);
}

void FileEnumerator::GetFindInfo(FindInfo *info) {
  DCHECK(info);

  if (current_directory_entry_ >= directory_entries_.size()) {
    return;
  }

  DirectoryEntryInfo *cur_entry = &directory_entries_[current_directory_entry_];
  memcpy(&(info->sb_info), &(cur_entry->sb_info), sizeof(info->sb_info));
  info->filename.assign(cur_entry->filename.value());
}

// static
bool FileEnumerator::IsDirectory(const FindInfo &info) {
  return info.sb_info.is_directory;
}

// static
FilePath FileEnumerator::GetFilename(const FindInfo &find_info) {
  return FilePath(find_info.filename);
}

// static
int64 FileEnumerator::GetFilesize(const FindInfo &find_info) {
  return find_info.sb_info.size;
}

// static
base::Time FileEnumerator::GetLastModifiedTime(const FindInfo &find_info) {
  return base::Time::FromSbTime(find_info.sb_info.last_modified);
}

// static
bool FileEnumerator::ReadDirectory(std::vector<DirectoryEntryInfo> *entries,
                                   const FilePath &source) {
  base::ThreadRestrictions::AssertIOAllowed();
  SbDirectory dir = SbDirectoryOpen(source.value().c_str(), NULL);
  if (!SbDirectoryIsValid(dir)) {
    return false;
  }

  SbDirectoryEntry entry;
  while (SbDirectoryGetNext(dir, &entry)) {
    DirectoryEntryInfo info;
    info.filename = FilePath(entry.name);

    FilePath full_name = source.Append(entry.name);
    // TODO: Make sure this follows symlinks on relevant platforms.
    if (!SbFileGetPathInfo(full_name.value().c_str(), &info.sb_info)) {
      DPLOG(ERROR) << "Couldn't SbFileGetInfo on " << full_name.value();
      memset(&info.sb_info, 0, sizeof(info.sb_info));
    }

    entries->push_back(info);
  }

  ignore_result(SbDirectoryClose(dir));
  return true;
}

}  // namespace file_util
