// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/drive/chromeos/file_cache.h"

#include <linux/fs.h>
#include <sys/ioctl.h>
#include <sys/xattr.h>

#include <memory>
#include <queue>
#include <vector>

#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/callback_helpers.h"
#include "base/files/file.h"
#include "base/files/file_enumerator.h"
#include "base/files/file_util.h"
#include "base/location.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
#include "base/stl_util.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/system/sys_info.h"
#include "build/build_config.h"
#include "components/drive/drive.pb.h"
#include "components/drive/drive_api_util.h"
#include "components/drive/file_system_core_util.h"
#include "components/drive/resource_metadata_storage.h"
#include "google_apis/drive/task_util.h"
#include "net/base/filename_util.h"
#include "net/base/mime_sniffer.h"
#include "net/base/mime_util.h"

namespace drive {
namespace internal {
namespace {

typedef std::pair<base::File::Info, ResourceEntry> CacheInfo;
typedef long FileAttributes;  // NOLINT(runtime/int)

// Returns ID extracted from the path.
std::string GetIdFromPath(const base::FilePath& path) {
  return util::UnescapeCacheFileName(path.BaseName().AsUTF8Unsafe());
}

base::FilePath GetPathForId(const base::FilePath& cache_directory,
                            const std::string& id) {
  return cache_directory.Append(
      base::FilePath::FromUTF8Unsafe(util::EscapeCacheFileName(id)));
}

// Returns if the filesystem backing |path| supports file attributes.
// This will return false if the filesystem is for example tmpfs, which is used
// for ephemeral mode.
bool IsFileAttributesSupported(const base::FilePath& path) {
  if (getxattr(path.value().c_str(), "user.foo", nullptr, 0) >= 0) {
    return true;
  }
  return errno != ENOTSUP;
}

// Sets extended file attribute as |name| |value| pair.
bool SetExtendedFileAttributes(const base::FilePath& path,
    const std::string& name, const std::string& value) {
  if (setxattr(path.value().c_str(), name.c_str(), value.c_str(),
               value.size() + 1, 0) != 0) {
    PLOG(ERROR) << "setxattr: " << path.value();
    return false;
  }
  return true;
}

// Remove extended file attribute with |name|.
bool UnsetExtendedFileAttributes(const base::FilePath& path,
                                 const std::string& name) {
  if (removexattr(path.value().c_str(), name.c_str()) != 0) {
    PLOG_IF(ERROR, errno != ENODATA) << "removexattr: " << path.value();
    return false;
  }
  return true;
}

// Changes attributes of the file with |flags|, e.g. FS_NODUMP_FL (cryptohome
// will remove Drive caches with this attribute).
// See linux/fs.h for available flags, and chattr(1) which does similar thing.
// Returns whether operation succeeded.
bool SetFileAttributes(const base::FilePath& path, FileAttributes flags) {
  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) {
    PLOG(ERROR) << "Failed to open file: " << path.value();
    return false;
  }
  if (ioctl(file.GetPlatformFile(), FS_IOC_SETFLAGS, &flags) < 0) {
    PLOG(ERROR) << "ioctl: " << path.value();
    return false;
  }
  return true;
}

// Gets file attributes similarly to lsattr(1). Returns flags or -1 on error.
// See linux/fs.h for the definition of the returned flags e.g. FS_NODUMP_FL.
FileAttributes GetFileAttributes(const base::FilePath& path) {
  base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ);
  if (!file.IsValid()) {
    PLOG(ERROR) << "Failed to open file: " << path.value();
    return -1;
  }
  FileAttributes flags = 0;
  if (ioctl(file.GetPlatformFile(), FS_IOC_GETFLAGS, &flags) < 0) {
    PLOG(ERROR) << "ioctl: " << path.value();
    return -1;
  }
  return flags;
}

// Marks the cache file to be removable by cryptohome, or do nothing if
// underlying filesystem doesn't support file attributes, as tmpfs for ephemeral
// mode.
bool SetRemovable(const base::FilePath& path) {
  // For ephemeral mode.
  if (!IsFileAttributesSupported(path)) {
    return true;
  }
  FileAttributes flags = GetFileAttributes(path);
  bool xattr = flags >= 0 && SetFileAttributes(path, flags | FS_NODUMP_FL);
  bool fattr = SetExtendedFileAttributes(
      path, FileCache::kGCacheRemovableAttribute, "1");
  return xattr || fattr;
}

// Marks the cache file to be unremovable by cryptohome, or do nothing if
// underlying filesystem doesn't support file attributes, as tmpfs for ephemeral
// mode.
bool UnsetRemovable(const base::FilePath& path) {
  // For ephemeral mode.
  if (!IsFileAttributesSupported(path)) {
    return true;
  }
  FileAttributes flags = GetFileAttributes(path);
  bool xattr = flags >= 0 && SetFileAttributes(path, flags & ~FS_NODUMP_FL);
  bool fattr =
      UnsetExtendedFileAttributes(path, FileCache::kGCacheRemovableAttribute);
  return xattr || fattr;
}

// Marks |path| as drive cache dir, or do nothing if underlying filesystem
// doesn't support file attributes, as tmpfs for ephemeral mode. Returns if the
// operation succeeded.
bool MarkAsDriveCacheDir(const base::FilePath& path) {
  // For ephemeral mode.
  if (!IsFileAttributesSupported(path)) {
    return true;
  }
  return SetRemovable(path)
      && SetExtendedFileAttributes(path, FileCache::kGCacheFilesAttribute, "");
}

class CacheInfoLatestCompare {
 public:
  bool operator()(const CacheInfo& info_a, const CacheInfo& info_b) {
    return info_a.first.last_accessed < info_b.first.last_accessed;
  }
};

// Returns true if the cache file is present.
bool IsPresent(const ResourceEntry& entry) {
  return entry.has_file_specific_info() &&
         entry.file_specific_info().has_cache_state() &&
         entry.file_specific_info().cache_state().is_present();
}

const size_t kMaxNumOfEvictedCacheFiles = 30000;

}  // namespace

// static
const char FileCache::kGCacheFilesAttribute[] = "user.GCacheFiles";
const char FileCache::kGCacheRemovableAttribute[] = "user.GCacheRemovable";

FileCache::FileCache(ResourceMetadataStorage* storage,
                     const base::FilePath& cache_file_directory,
                     base::SequencedTaskRunner* blocking_task_runner,
                     FreeDiskSpaceGetterInterface* free_disk_space_getter)
    : cache_file_directory_(cache_file_directory),
      blocking_task_runner_(blocking_task_runner),
      storage_(storage),
      free_disk_space_getter_(free_disk_space_getter),
      max_num_of_evicted_cache_files_(kMaxNumOfEvictedCacheFiles) {
  DCHECK(blocking_task_runner_.get());
}

FileCache::~FileCache() {
  // Must be on the sequenced worker pool, as |metadata_| must be deleted on
  // the sequenced worker pool.
  AssertOnSequencedWorkerPool();
}

void FileCache::SetMaxNumOfEvictedCacheFilesForTest(
    size_t max_num_of_evicted_cache_files) {
  max_num_of_evicted_cache_files_ = max_num_of_evicted_cache_files;
}

base::FilePath FileCache::GetCacheFilePath(const std::string& id) const {
  return GetPathForId(cache_file_directory_, id);
}

void FileCache::AssertOnSequencedWorkerPool() {
  DCHECK(blocking_task_runner_->RunsTasksInCurrentSequence());
}

bool FileCache::IsUnderFileCacheDirectory(const base::FilePath& path) const {
  return cache_file_directory_.IsParent(path);
}

bool FileCache::FreeDiskSpaceIfNeededFor(int64_t num_bytes) {
  AssertOnSequencedWorkerPool();

  // Do nothing and return if we have enough space.
  if (GetAvailableSpace() >= num_bytes)
    return true;

  // Otherwise, try to free up the disk space.
  DVLOG(1) << "Freeing up disk space for " << num_bytes;

  // Remove all files which have no corresponding cache entries.
  base::FileEnumerator enumerator(cache_file_directory_,
                                  false,  // not recursive
                                  base::FileEnumerator::FILES);
  ResourceEntry entry;
  for (base::FilePath current = enumerator.Next(); !current.empty();
       current = enumerator.Next()) {
    const std::string id = GetIdFromPath(current);
    const FileError error = storage_->GetEntry(id, &entry);

    if (error == FILE_ERROR_NOT_FOUND)
      base::DeleteFile(current, false /* recursive */);
    else if (error != FILE_ERROR_OK)
      return false;
  }

  // Check available space again. If we have enough space here, do nothing.
  const int64_t available_space = GetAvailableSpace();
  if (available_space >= num_bytes)
    return true;

  const int64_t requested_space = num_bytes - available_space;

  // Put all entries in priority queue where latest entry becomes top.
  std::priority_queue<CacheInfo, std::vector<CacheInfo>, CacheInfoLatestCompare>
      cache_info_queue;
  std::unique_ptr<ResourceMetadataStorage::Iterator> it =
      storage_->GetIterator();
  for (; !it->IsAtEnd(); it->Advance()) {
    if (IsEvictable(it->GetID(), it->GetValue())) {
      const ResourceEntry& entry = it->GetValue();

      const base::FilePath& cache_path = GetCacheFilePath(entry.local_id());
      base::File::Info info;
      // If it fails to get file info of |cache_path|, use default value as its
      // file info. i.e. the file becomes least recently used one.
      base::GetFileInfo(cache_path, &info);

      CacheInfo cache_info = std::make_pair(info, entry);

      if (cache_info_queue.size() < max_num_of_evicted_cache_files_) {
        cache_info_queue.push(cache_info);
      } else if (cache_info_queue.size() >= max_num_of_evicted_cache_files_ &&
                 cache_info.first.last_accessed <
                     cache_info_queue.top().first.last_accessed) {
        // Do not enqueue more than max_num_of_evicted_cache_files_ not to use
        // up memory with this queue.
        cache_info_queue.pop();
        cache_info_queue.push(cache_info);
      }
    }
  }
  if (it->HasError())
    return false;

  // Copy entries to the vector. This becomes last-accessed desc order.
  std::vector<CacheInfo> cache_info_list;
  while (!cache_info_queue.empty()) {
    cache_info_list.push_back(cache_info_queue.top());
    cache_info_queue.pop();
  }

  // Update DB and delete files with accessing to the vector in ascending order.
  int64_t evicted_cache_size = 0;
  auto iter = cache_info_list.rbegin();
  while (evicted_cache_size < requested_space &&
         iter != cache_info_list.rend()) {
    const CacheInfo& cache_info = *iter;

    // Update DB.
    ResourceEntry entry = cache_info.second;
    entry.mutable_file_specific_info()->clear_cache_state();
    storage_->PutEntry(entry);

    // Delete cache file.
    const base::FilePath& path = GetCacheFilePath(entry.local_id());

    if (base::DeleteFile(path, false /* recursive */))
      evicted_cache_size += cache_info.first.size;

    ++iter;
  }

  // Check the disk space again.
  return GetAvailableSpace() >= num_bytes;
}

int64_t FileCache::CalculateCacheSize() {
  AssertOnSequencedWorkerPool();

  int64_t total_cache_size = 0;
  int64_t cache_size = 0;

  std::unique_ptr<ResourceMetadataStorage::Iterator> it =
      storage_->GetIterator();
  for (; !it->IsAtEnd(); it->Advance()) {
    if (IsPresent(it->GetValue()) &&
        base::GetFileSize(GetCacheFilePath(it->GetID()), &cache_size)) {
      DCHECK_GE(cache_size, 0);
      total_cache_size += cache_size;
    }
  }

  if (it->HasError())
    return 0;

  return total_cache_size;
}

int64_t FileCache::CalculateEvictableCacheSize() {
  AssertOnSequencedWorkerPool();

  int64_t evictable_cache_size = 0;
  int64_t cache_size = 0;

  std::unique_ptr<ResourceMetadataStorage::Iterator> it =
      storage_->GetIterator();
  for (; !it->IsAtEnd(); it->Advance()) {
    if (IsEvictable(it->GetID(), it->GetValue()) &&
        base::GetFileSize(GetCacheFilePath(it->GetID()), &cache_size)) {
      DCHECK_GE(cache_size, 0);
      evictable_cache_size += cache_size;
    }
  }

  if (it->HasError())
    return 0;

  return evictable_cache_size;
}

FileError FileCache::GetFile(const std::string& id,
                             base::FilePath* cache_file_path) {
  AssertOnSequencedWorkerPool();
  DCHECK(cache_file_path);

  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().cache_state().is_present())
    return FILE_ERROR_NOT_FOUND;

  *cache_file_path = GetCacheFilePath(id);
  return FILE_ERROR_OK;
}

FileError FileCache::Store(const std::string& id,
                           const std::string& md5,
                           const base::FilePath& source_path,
                           FileOperationType file_operation_type) {
  AssertOnSequencedWorkerPool();

  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;

  int64_t file_size = 0;
  if (file_operation_type == FILE_OPERATION_COPY) {
    if (!base::GetFileSize(source_path, &file_size)) {
      LOG(WARNING) << "Couldn't get file size for: " << source_path.value();
      return FILE_ERROR_FAILED;
    }
  }
  if (!FreeDiskSpaceIfNeededFor(file_size))
    return FILE_ERROR_NO_LOCAL_SPACE;

  // If file is mounted, return error.
  if (mounted_files_.count(id))
    return FILE_ERROR_IN_USE;

  base::FilePath dest_path = GetCacheFilePath(id);
  bool success = false;
  switch (file_operation_type) {
    case FILE_OPERATION_MOVE:
      success = base::Move(source_path, dest_path);
      break;
    case FILE_OPERATION_COPY:
      success = base::CopyFile(source_path, dest_path);
      break;
    default:
      NOTREACHED();
  }

  if (!success) {
    LOG(ERROR) << "Failed to store: "
               << "source_path = " << source_path.value() << ", "
               << "dest_path = " << dest_path.value() << ", "
               << "file_operation_type = " << file_operation_type;
    return FILE_ERROR_FAILED;
  }

  // Now that file operations have completed, update metadata.
  FileCacheEntry* cache_state =
      entry.mutable_file_specific_info()->mutable_cache_state();
  cache_state->set_md5(md5);
  cache_state->set_is_present(true);
  if (md5.empty())
    cache_state->set_is_dirty(true);

  if (!cache_state->is_pinned() && !cache_state->is_dirty()) {
    if (!SetRemovable(dest_path))
      return FILE_ERROR_FAILED;
  } else {
    if (!UnsetRemovable(dest_path))
      return FILE_ERROR_FAILED;
  }

  return storage_->PutEntry(entry);
}

FileError FileCache::Pin(const std::string& id) {
  AssertOnSequencedWorkerPool();

  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;

  entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned(
      true);

  base::FilePath file_path = GetCacheFilePath(entry.local_id());
  // Cache file can be created later.
  if (entry.file_specific_info().cache_state().is_present()) {
    if (!UnsetRemovable(file_path))
      return FILE_ERROR_FAILED;
  }

  return storage_->PutEntry(entry);
}

FileError FileCache::Unpin(const std::string& id) {
  AssertOnSequencedWorkerPool();

  // Unpinning a file means its entry must exist in cache.
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;

  // Now that file operations have completed, update metadata.
  if (entry.file_specific_info().cache_state().is_present()) {
    entry.mutable_file_specific_info()->mutable_cache_state()->set_is_pinned(
        false);
    if (!entry.file_specific_info().cache_state().is_dirty()) {
      if (!SetRemovable(GetCacheFilePath(entry.local_id())))
        return FILE_ERROR_FAILED;
    }
  } else {
    // Remove the existing entry if we are unpinning a non-present file.
    entry.mutable_file_specific_info()->clear_cache_state();
  }
  error = storage_->PutEntry(entry);
  if (error != FILE_ERROR_OK)
    return error;

  // Now it's a chance to free up space if needed.
  FreeDiskSpaceIfNeededFor(0);

  return FILE_ERROR_OK;
}

bool FileCache::IsMarkedAsMounted(const std::string& id) {
  AssertOnSequencedWorkerPool();
  return mounted_files_.count(id);
}

FileError FileCache::MarkAsMounted(const std::string& id,
                                   base::FilePath* cache_file_path) {
  AssertOnSequencedWorkerPool();
  DCHECK(cache_file_path);

  // Get cache entry associated with the id and md5
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().cache_state().is_present())
    return FILE_ERROR_NOT_FOUND;

  if (mounted_files_.count(id))
    return FILE_ERROR_INVALID_OPERATION;

  base::FilePath path = GetCacheFilePath(id);

#if defined(OS_CHROMEOS)
  // Ensure the file is readable to cros_disks. See crbug.com/236994.
  if (!base::SetPosixFilePermissions(
          path,
          base::FILE_PERMISSION_READ_BY_USER |
          base::FILE_PERMISSION_WRITE_BY_USER |
          base::FILE_PERMISSION_READ_BY_GROUP |
          base::FILE_PERMISSION_READ_BY_OTHERS))
    return FILE_ERROR_FAILED;
#endif

  mounted_files_.insert(id);

  *cache_file_path = path;
  return FILE_ERROR_OK;
}

FileError FileCache::OpenForWrite(
    const std::string& id,
    std::unique_ptr<base::ScopedClosureRunner>* file_closer) {
  AssertOnSequencedWorkerPool();

  // Marking a file dirty means its entry and actual file blob must exist in
  // cache.
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().cache_state().is_present()) {
    LOG(WARNING) << "Can't mark dirty a file that wasn't cached: " << id;
    return FILE_ERROR_NOT_FOUND;
  }

  entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty(true);
  if (!UnsetRemovable(GetCacheFilePath(entry.local_id())))
    return FILE_ERROR_FAILED;

  entry.mutable_file_specific_info()->mutable_cache_state()->clear_md5();
  error = storage_->PutEntry(entry);
  if (error != FILE_ERROR_OK)
    return error;

  write_opened_files_[id]++;
  *file_closer = std::make_unique<base::ScopedClosureRunner>(
      base::Bind(&google_apis::RunTaskWithTaskRunner, blocking_task_runner_,
                 base::Bind(&FileCache::CloseForWrite,
                            weak_ptr_factory_.GetWeakPtr(), id)));
  return FILE_ERROR_OK;
}

bool FileCache::IsOpenedForWrite(const std::string& id) {
  AssertOnSequencedWorkerPool();
  return write_opened_files_.count(id) != 0;
}

FileError FileCache::UpdateMd5(const std::string& id) {
  AssertOnSequencedWorkerPool();

  if (IsOpenedForWrite(id))
    return FILE_ERROR_IN_USE;

  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().cache_state().is_present())
    return FILE_ERROR_NOT_FOUND;

  const std::string& md5 =
      util::GetMd5Digest(GetCacheFilePath(id), &in_shutdown_);
  if (in_shutdown_.IsSet())
    return FILE_ERROR_ABORT;
  if (md5.empty())
    return FILE_ERROR_NOT_FOUND;

  entry.mutable_file_specific_info()->mutable_cache_state()->set_md5(md5);
  return storage_->PutEntry(entry);
}

FileError FileCache::ClearDirty(const std::string& id) {
  AssertOnSequencedWorkerPool();

  if (IsOpenedForWrite(id))
    return FILE_ERROR_IN_USE;

  // Clearing a dirty file means its entry and actual file blob must exist in
  // cache.
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().cache_state().is_present()) {
    LOG(WARNING) << "Can't clear dirty state of a file that wasn't cached: "
                 << id;
    return FILE_ERROR_NOT_FOUND;
  }

  // If a file is not dirty (it should have been marked dirty via OpenForWrite),
  // clearing its dirty state is an invalid operation.
  if (!entry.file_specific_info().cache_state().is_dirty()) {
    LOG(WARNING) << "Can't clear dirty state of a non-dirty file: " << id;
    return FILE_ERROR_INVALID_OPERATION;
  }

  entry.mutable_file_specific_info()->mutable_cache_state()->set_is_dirty(
      false);
  if (!entry.file_specific_info().cache_state().is_pinned()) {
    if (!SetRemovable(GetCacheFilePath(entry.local_id())))
      return FILE_ERROR_FAILED;
  }

  return storage_->PutEntry(entry);
}

FileError FileCache::Remove(const std::string& id) {
  AssertOnSequencedWorkerPool();

  ResourceEntry entry;

  // If entry doesn't exist, nothing to do.
  FileError error = storage_->GetEntry(id, &entry);
  if (error == FILE_ERROR_NOT_FOUND)
    return FILE_ERROR_OK;
  if (error != FILE_ERROR_OK)
    return error;
  if (!entry.file_specific_info().has_cache_state())
    return FILE_ERROR_OK;

  // Cannot delete a mounted file.
  if (mounted_files_.count(id))
    return FILE_ERROR_IN_USE;

  // Delete the file.
  base::FilePath path = GetCacheFilePath(id);
  if (!base::DeleteFile(path, false /* recursive */))
    return FILE_ERROR_FAILED;

  // Now that all file operations have completed, remove from metadata.
  entry.mutable_file_specific_info()->clear_cache_state();
  return storage_->PutEntry(entry);
}

bool FileCache::ClearAll() {
  AssertOnSequencedWorkerPool();

  // Remove files.
  base::FileEnumerator enumerator(cache_file_directory_,
                                  false,  // not recursive
                                  base::FileEnumerator::FILES);
  for (base::FilePath file = enumerator.Next(); !file.empty();
       file = enumerator.Next())
    base::DeleteFile(file, false /* recursive */);

  return true;
}

bool FileCache::Initialize() {
  AssertOnSequencedWorkerPool();

  // Older versions do not clear MD5 when marking entries dirty.
  // Clear MD5 of all dirty entries to deal with old data.
  std::unique_ptr<ResourceMetadataStorage::Iterator> it =
      storage_->GetIterator();
  for (; !it->IsAtEnd(); it->Advance()) {
    if (it->GetValue().file_specific_info().cache_state().is_dirty()) {
      ResourceEntry new_entry(it->GetValue());
      new_entry.mutable_file_specific_info()->mutable_cache_state()->
          clear_md5();
      if (storage_->PutEntry(new_entry) != FILE_ERROR_OK)
        return false;
    }
  }
  if (it->HasError())
    return false;

  if (!RenameCacheFilesToNewFormat())
    return false;

  // Run this every time to resolve inconsistency between metadata
  // and file attributes which possibly occurs on abrupt power failure.
  if (!FixMetadataAndFileAttributes()) {
    return false;
  }

  return true;
}

void FileCache::Destroy() {
  DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);

  in_shutdown_.Set();

  // Destroy myself on the blocking pool.
  // Note that base::DeletePointer<> cannot be used as the destructor of this
  // class is private.
  blocking_task_runner_->PostTask(
      FROM_HERE, base::BindOnce(&FileCache::DestroyOnBlockingPool,
                                base::Unretained(this)));
}

void FileCache::DestroyOnBlockingPool() {
  AssertOnSequencedWorkerPool();
  delete this;
}

bool FileCache::RecoverFilesFromCacheDirectory(
    const base::FilePath& dest_directory,
    const ResourceMetadataStorage::RecoveredCacheInfoMap&
        recovered_cache_info) {
  int file_number = 1;

  base::FileEnumerator enumerator(cache_file_directory_,
                                  false,  // not recursive
                                  base::FileEnumerator::FILES);
  for (base::FilePath current = enumerator.Next(); !current.empty();
       current = enumerator.Next()) {
    const std::string& id = GetIdFromPath(current);
    ResourceEntry entry;
    FileError error = storage_->GetEntry(id, &entry);
    if (error != FILE_ERROR_OK && error != FILE_ERROR_NOT_FOUND)
      return false;
    if (error == FILE_ERROR_OK &&
        entry.file_specific_info().cache_state().is_present()) {
      // This file is managed by FileCache, no need to recover it.
      continue;
    }

    // If a cache entry which is non-dirty and has matching MD5 is found in
    // |recovered_cache_entries|, it means the current file is already uploaded
    // to the server. Just delete it instead of recovering it.
    ResourceMetadataStorage::RecoveredCacheInfoMap::const_iterator it =
        recovered_cache_info.find(id);
    if (it != recovered_cache_info.end()) {
      // Due to the DB corruption, cache info might be recovered from old
      // revision. Perform MD5 check even when is_dirty is false just in case.
      if (!it->second.is_dirty &&
          it->second.md5 == util::GetMd5Digest(current, &in_shutdown_)) {
        base::DeleteFile(current, false /* recursive */);
        continue;
      }
    }

    // Read file contents to sniff mime type.
    std::vector<char> content(net::kMaxBytesToSniff);
    const int read_result =
        base::ReadFile(current, &content[0], content.size());
    if (read_result < 0) {
      LOG(WARNING) << "Cannot read: " << current.value();
      return false;
    }
    if (read_result == 0)  // Skip empty files.
      continue;

    // Use recovered file name if available, otherwise decide file name with
    // sniffed mime type.
    base::FilePath dest_base_name(FILE_PATH_LITERAL("file"));
    std::string mime_type;
    if (it != recovered_cache_info.end() && !it->second.title.empty()) {
      // We can use a file name recovered from the trashed DB.
      dest_base_name = base::FilePath::FromUTF8Unsafe(it->second.title);
    } else if (net::SniffMimeType(
                   &content[0], read_result, net::FilePathToFileURL(current),
                   std::string(), net::ForceSniffFileUrlsForHtml::kDisabled,
                   &mime_type) ||
               net::SniffMimeTypeFromLocalData(&content[0], read_result,
                                               &mime_type)) {
      // Change base name for common mime types.
      if (net::MatchesMimeType("image/*", mime_type)) {
        dest_base_name = base::FilePath(FILE_PATH_LITERAL("image"));
      } else if (net::MatchesMimeType("video/*", mime_type)) {
        dest_base_name = base::FilePath(FILE_PATH_LITERAL("video"));
      } else if (net::MatchesMimeType("audio/*", mime_type)) {
        dest_base_name = base::FilePath(FILE_PATH_LITERAL("audio"));
      }

      // Estimate extension from mime type.
      std::vector<base::FilePath::StringType> extensions;
      base::FilePath::StringType extension;
      if (net::GetPreferredExtensionForMimeType(mime_type, &extension))
        extensions.push_back(extension);
      else
        net::GetExtensionsForMimeType(mime_type, &extensions);

      // Add extension if possible.
      if (!extensions.empty())
        dest_base_name = dest_base_name.AddExtension(extensions[0]);
    }

    // Add file number to the file name and move.
    const base::FilePath& dest_path = dest_directory.Append(dest_base_name)
        .InsertBeforeExtensionASCII(base::StringPrintf("%08d", file_number++));
    if (!base::CreateDirectory(dest_directory) ||
        !base::Move(current, dest_path)) {
      LOG(WARNING) << "Failed to move: " << current.value()
                   << " to " << dest_path.value();
      return false;
    }
  }
  UMA_HISTOGRAM_COUNTS_1M("Drive.NumberOfCacheFilesRecoveredAfterDBCorruption",
                          file_number - 1);
  return true;
}

FileError FileCache::MarkAsUnmounted(const base::FilePath& file_path) {
  AssertOnSequencedWorkerPool();
  DCHECK(IsUnderFileCacheDirectory(file_path));

  std::string id = GetIdFromPath(file_path);

  // Get the entry associated with the id.
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK)
    return error;

  std::set<std::string>::iterator it = mounted_files_.find(id);
  if (it == mounted_files_.end())
    return FILE_ERROR_INVALID_OPERATION;

  mounted_files_.erase(it);
  return FILE_ERROR_OK;
}

int64_t FileCache::GetAvailableSpace() {
  int64_t free_space = 0;
  if (free_disk_space_getter_)
    free_space = free_disk_space_getter_->AmountOfFreeDiskSpace();
  else
    free_space = base::SysInfo::AmountOfFreeDiskSpace(cache_file_directory_);

  // Subtract this as if this portion does not exist.
  free_space -= drive::internal::kMinFreeSpaceInBytes;
  return free_space;
}

bool FileCache::RenameCacheFilesToNewFormat() {
  base::FileEnumerator enumerator(cache_file_directory_,
                                  false,  // not recursive
                                  base::FileEnumerator::FILES);
  for (base::FilePath current = enumerator.Next(); !current.empty();
       current = enumerator.Next()) {
    base::FilePath new_path = current.RemoveExtension();
    if (!new_path.Extension().empty()) {
      // Delete files with multiple extensions.
      if (!base::DeleteFile(current, false /* recursive */))
        return false;
      continue;
    }
    const std::string& id = GetIdFromPath(new_path);
    new_path = GetCacheFilePath(util::CanonicalizeResourceId(id));
    if (new_path != current && !base::Move(current, new_path))
      return false;
  }
  return true;
}

bool FileCache::FixMetadataAndFileAttributes() {
  std::unique_ptr<ResourceMetadataStorage::Iterator> it =
      storage_->GetIterator();

  for (; !it->IsAtEnd(); it->Advance()) {
    ResourceEntry entry = it->GetValue();
    FileCacheEntry* file_cache_entry =
        entry.mutable_file_specific_info()->mutable_cache_state();

    const base::FilePath filepath = GetPathForId(cache_file_directory_,
        entry.local_id());

    if (base::PathExists(filepath)) {
      if (file_cache_entry->is_present()) {
        // Update file attribues for cryptohome.
        if (file_cache_entry->is_pinned() || file_cache_entry->is_dirty()) {
          if (!UnsetRemovable(filepath)) return false;
        } else {
          if (!SetRemovable(filepath)) return false;
        }
      } else {
        // Delete file if the file is present but metadata says not.
        // It happens only on abrupt shutdown.
        LOG(WARNING)
            << "File is present but metadata's state was inconsistent.";

        if (!base::DeleteFile(filepath, false /* recursive */))
          return false;
      }
    } else {
      // Update metatadata if there is no file but metadata says there is.
      // It happens when cryptohome removed the file.
      // We don't clear is_pinned here, so that file download is restarted on
      // the following scenario:
      //  1. The file was pinned but not present.
      //  2. Then the file was downloaded and became present.
      //  3. Unclean shutdown happens, metadata update was saved to the disk,
      //     but the file move was not.
      if (file_cache_entry->is_present()) {
        file_cache_entry->set_is_present(false);
        file_cache_entry->set_is_dirty(false);
        file_cache_entry->clear_md5();
        if (storage_->PutEntry(entry) != FILE_ERROR_OK)
          return false;
      }
    }
  }

  return MarkAsDriveCacheDir(cache_file_directory_);
}

void FileCache::CloseForWrite(const std::string& id) {
  AssertOnSequencedWorkerPool();

  std::map<std::string, int>::iterator it = write_opened_files_.find(id);
  if (it == write_opened_files_.end())
    return;

  DCHECK_LT(0, it->second);
  --it->second;
  if (it->second == 0)
    write_opened_files_.erase(it);

  // Update last modified date.
  ResourceEntry entry;
  FileError error = storage_->GetEntry(id, &entry);
  if (error != FILE_ERROR_OK) {
    LOG(ERROR) << "Failed to get entry: " << id << ", "
               << FileErrorToString(error);
    return;
  }
  int64_t now = base::Time::Now().ToInternalValue();
  entry.mutable_file_info()->set_last_modified(now);
  entry.set_last_modified_by_me(now);
  error = storage_->PutEntry(entry);
  if (error != FILE_ERROR_OK) {
    LOG(ERROR) << "Failed to put entry: " << id << ", "
               << FileErrorToString(error);
  }
}

bool FileCache::IsEvictable(const std::string& id, const ResourceEntry& entry) {
  return IsPresent(entry) &&
         !entry.file_specific_info().cache_state().is_pinned() &&
         !entry.file_specific_info().cache_state().is_dirty() &&
         !mounted_files_.count(id);
}

}  // namespace internal
}  // namespace drive
