// Copyright 2020 The Chromium OS 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 "cryptohome/fake_platform.h"

#include <map>
#include <memory>
#include <optional>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <linux/fs.h>
#include <vector>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <brillo/blkdev_utils/loop_device_fake.h>
#include <brillo/blkdev_utils/mock_lvm.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>

#include "cryptohome/util/get_random_suffix.h"

#include "cryptohome/fake_platform/test_file_path.h"
#include "cryptohome/filesystem_layout.h"

namespace cryptohome {

using fake_platform::NormalizePath;

namespace {

class ProxyFileEnumerator : public FileEnumerator {
 public:
  ProxyFileEnumerator(const base::FilePath& original_path,
                      FakePlatform* fake_platform,
                      FakeMountMapper* fake_mount_mapper,
                      FileEnumerator* real_enumerator)
      : original_path_(NormalizePath(original_path)),
        fake_platform_(fake_platform),
        fake_mount_mapper_(fake_mount_mapper),
        real_enumerator_(real_enumerator) {}

  // Removed tmpfs prefix from the returned path.
  base::FilePath Next() override {
    base::FilePath next = real_enumerator_->Next();
    last_path_ = fake_mount_mapper_->ReverseResolvePath(next, original_path_);
    return last_path_;
  }

  FileEnumerator::FileInfo GetInfo() override {
    FileEnumerator::FileInfo real_info = real_enumerator_->GetInfo();
    base::stat_wrapper_t stat;
    CHECK(fake_platform_->Stat(last_path_, &stat));
    return FileEnumerator::FileInfo(real_info.GetName(), stat);
  }

 private:
  base::FilePath original_path_;
  FakePlatform* fake_platform_;
  FakeMountMapper* fake_mount_mapper_;
  std::unique_ptr<FileEnumerator> real_enumerator_;
  base::FilePath last_path_;
};

template <typename KeyType>
void RemoveFakeEntriesRecursiveImpl(
    const base::FilePath& path,
    std::unordered_map<base::FilePath, KeyType>* m) {
  for (auto it = m->begin(); it != m->end();) {
    auto tmp_it = it;
    ++it;
    if (tmp_it->first == path || path.IsParent(tmp_it->first)) {
      m->erase(tmp_it);
    }
  }
}

}  // namespace

// FakeExtendedAttributes

bool FakePlatform::FakeExtendedAttributes::Exists(
    const std::string& name) const {
  return xattrs_.find(name) != xattrs_.end();
}

void FakePlatform::FakeExtendedAttributes::List(
    std::vector<std::string>* attr_list) const {
  DCHECK(attr_list);
  attr_list->clear();
  for (const auto& xattr : xattrs_) {
    attr_list->push_back(xattr.first);
  }
}

bool FakePlatform::FakeExtendedAttributes::GetAsString(
    const std::string& name, std::string* value) const {
  const auto it = xattrs_.find(name);
  if (it == xattrs_.end()) {
    return false;
  }

  value->assign(it->second.data(), it->second.size());
  return true;
}

bool FakePlatform::FakeExtendedAttributes::Get(const std::string& name,
                                               char* value,
                                               ssize_t size) const {
  const auto it = xattrs_.find(name);
  if (it == xattrs_.end()) {
    return false;
  }

  if (it->second.size() > size) {
    return false;
  }

  memcpy(value, it->second.data(), it->second.size());

  return true;
}

void FakePlatform::FakeExtendedAttributes::Set(const std::string& name,
                                               const char* value,
                                               ssize_t size) {
  xattrs_[name].assign(value, value + size);
}

void FakePlatform::FakeExtendedAttributes::Remove(const std::string& name) {
  xattrs_.erase(name);
}

// Constructor/destructor

FakePlatform::FakePlatform()
    : Platform(),
      fake_loop_device_manager_(
          std::make_unique<brillo::fake::FakeLoopDeviceManager>()),
      mock_lvm_(std::make_unique<brillo::MockLogicalVolumeManager>()) {
  base::GetTempDir(&tmpfs_rootfs_);
  tmpfs_rootfs_ = tmpfs_rootfs_.Append(GetRandomSuffix());
  if (!real_platform_.CreateDirectory(tmpfs_rootfs_)) {
    LOG(ERROR) << "Failed to create test dir: " << tmpfs_rootfs_;
  }
  fake_mount_mapper_.reset(new FakeMountMapper(tmpfs_rootfs_));
  brillo::SecureBlob system_salt;
  InitializeFilesystemLayout(this, &system_salt);
  SetSystemSaltForLibbrillo(system_salt);
}

FakePlatform::~FakePlatform() {
  RemoveSystemSaltForLibbrillo();
  real_platform_.DeletePathRecursively(tmpfs_rootfs_);
}

// Helpers

base::FilePath FakePlatform::TestFilePath(const base::FilePath& path) const {
  CHECK(path.IsAbsolute());
  const base::FilePath normalized_path = NormalizePath(path);
  return fake_mount_mapper_->ResolvePath(normalized_path);
}

base::FilePath FakePlatform::StripTestFilePath(
    const base::FilePath& path) const {
  return fake_platform::StripTestFilePath(tmpfs_rootfs_, path);
}

bool FakePlatform::IsLink(const base::FilePath& path) const {
  return base::IsLink(TestFilePath(path));
}

void FakePlatform::RemoveFakeEntries(const base::FilePath& path) {
  base::AutoLock lock(mappings_lock_);
  xattrs_.erase(path);
  file_owners_.erase(path);
  file_mode_.erase(path);
  file_flags_.erase(path);
}

void FakePlatform::RemoveFakeEntriesRecursive(const base::FilePath& path) {
  base::AutoLock lock(mappings_lock_);
  RemoveFakeEntriesRecursiveImpl(path, &xattrs_);
  RemoveFakeEntriesRecursiveImpl(path, &file_owners_);
  RemoveFakeEntriesRecursiveImpl(path, &file_mode_);
  RemoveFakeEntriesRecursiveImpl(path, &file_flags_);
}

// Platform API

brillo::LoopDeviceManager* FakePlatform::GetLoopDeviceManager() {
  return fake_loop_device_manager_.get();
}

brillo::LogicalVolumeManager* FakePlatform::GetLogicalVolumeManager() {
  return mock_lvm_.get();
}

brillo::MockLogicalVolumeManager* FakePlatform::GetMockLogicalVolumeManager() {
  return mock_lvm_.get();
}

bool FakePlatform::Rename(const base::FilePath& from,
                          const base::FilePath& to) {
  return real_platform_.Rename(TestFilePath(from), TestFilePath(to));
}

bool FakePlatform::Move(const base::FilePath& from, const base::FilePath& to) {
  return real_platform_.Move(TestFilePath(from), TestFilePath(to));
}

bool FakePlatform::Copy(const base::FilePath& from, const base::FilePath& to) {
  return real_platform_.Copy(TestFilePath(from), TestFilePath(to));
}

bool FakePlatform::EnumerateDirectoryEntries(
    const base::FilePath& path,
    bool recursive,
    std::vector<base::FilePath>* ent_list) {
  return real_platform_.EnumerateDirectoryEntries(TestFilePath(path), recursive,
                                                  ent_list);
}

bool FakePlatform::IsDirectoryEmpty(const base::FilePath& path) {
  return real_platform_.IsDirectoryEmpty(TestFilePath(path));
}

bool FakePlatform::TouchFileDurable(const base::FilePath& path) {
  return real_platform_.TouchFileDurable(TestFilePath(path));
}

bool FakePlatform::DeleteFile(const base::FilePath& path) {
  RemoveFakeEntries(path);
  return real_platform_.DeleteFile(TestFilePath(path));
}

bool FakePlatform::DeletePathRecursively(const base::FilePath& path) {
  RemoveFakeEntriesRecursive(path);
  return real_platform_.DeletePathRecursively(TestFilePath(path));
}

bool FakePlatform::DeleteFileDurable(const base::FilePath& path) {
  RemoveFakeEntries(path);
  return real_platform_.DeleteFileDurable(TestFilePath(path));
}

bool FakePlatform::FileExists(const base::FilePath& path) const {
  return real_platform_.FileExists(TestFilePath(path));
}

bool FakePlatform::DirectoryExists(const base::FilePath& path) {
  return real_platform_.DirectoryExists(TestFilePath(path));
}

int FakePlatform::Access(const base::FilePath& path, uint32_t flag) {
  if (!FileExists(path)) {
    return -1;
  }

  mode_t mode;
  if (!GetPermissions(path, &mode)) {
    return -1;
  }
  bool failed_read = (flag & R_OK) && !(mode & S_IRUSR);
  bool failed_write = (flag & W_OK) && !(mode & S_IWUSR);
  bool failed_exec = (flag & X_OK) && !(mode & S_IXUSR);
  if (failed_read || failed_write || failed_exec) {
    return -1;
  }

  return 0;
}

bool FakePlatform::CreateDirectory(const base::FilePath& path) {
  return real_platform_.CreateDirectory(TestFilePath(path));
}

bool FakePlatform::CreateSparseFile(const base::FilePath& path, int64_t size) {
  return real_platform_.CreateSparseFile(TestFilePath(path), size);
}

bool FakePlatform::DataSyncFile(const base::FilePath& path) {
  return real_platform_.DataSyncFile(TestFilePath(path));
}

bool FakePlatform::SyncFile(const base::FilePath& path) {
  return real_platform_.SyncFile(TestFilePath(path));
}

bool FakePlatform::SyncDirectory(const base::FilePath& path) {
  return real_platform_.SyncDirectory(TestFilePath(path));
}

void FakePlatform::Sync() {
  real_platform_.Sync();
}

bool FakePlatform::CreateSymbolicLink(const base::FilePath& path,
                                      const base::FilePath& target) {
  if (target.IsAbsolute()) {
    return real_platform_.CreateSymbolicLink(TestFilePath(path),
                                             TestFilePath(target));
  } else {
    return real_platform_.CreateSymbolicLink(TestFilePath(path), target);
  }
}

bool FakePlatform::ReadLink(const base::FilePath& path,
                            base::FilePath* target) {
  base::FilePath tmp_path;
  if (!real_platform_.ReadLink(TestFilePath(path), &tmp_path)) {
    return false;
  }

  *target = StripTestFilePath(tmp_path);
  return true;
}

bool FakePlatform::SetFileTimes(const base::FilePath& path,
                                const struct timespec& atime,
                                const struct timespec& mtime,
                                bool follow_links) {
  return real_platform_.SetFileTimes(TestFilePath(path), atime, mtime,
                                     follow_links);
}

bool FakePlatform::SendFile(int fd_to,
                            int fd_from,
                            off_t offset,
                            size_t count) {
  return real_platform_.SendFile(fd_to, fd_from, offset, count);
}

void FakePlatform::InitializeFile(base::File* file,
                                  const base::FilePath& path,
                                  uint32_t flags) {
  // This part here is to make one of the access verification tests happy.
  // TODO(dlunev): generalize access control abiding fake permissions.
  if (FileExists(path)) {
    mode_t mode;
    CHECK(GetPermissions(path, &mode));
    bool init_for_read = flags & base::File::FLAG_READ;
    bool can_read = mode & S_IRUSR;
    if (init_for_read && !can_read) {
      return;
    }
  }

  real_platform_.InitializeFile(file, TestFilePath(path), flags);
}

bool FakePlatform::LockFile(int fd) {
  return real_platform_.LockFile(fd);
}

bool FakePlatform::ReadFile(const base::FilePath& path, brillo::Blob* blob) {
  return real_platform_.ReadFile(TestFilePath(path), blob);
}

bool FakePlatform::ReadFileToString(const base::FilePath& path,
                                    std::string* str) {
  return real_platform_.ReadFileToString(TestFilePath(path), str);
}

bool FakePlatform::ReadFileToSecureBlob(const base::FilePath& path,
                                        brillo::SecureBlob* sblob) {
  return real_platform_.ReadFileToSecureBlob(TestFilePath(path), sblob);
}

bool FakePlatform::WriteFile(const base::FilePath& path,
                             const brillo::Blob& blob) {
  return real_platform_.WriteFile(TestFilePath(path), blob);
}

bool FakePlatform::WriteSecureBlobToFile(const base::FilePath& path,
                                         const brillo::SecureBlob& sblob) {
  return real_platform_.WriteSecureBlobToFile(TestFilePath(path), sblob);
}

bool FakePlatform::WriteFileAtomic(const base::FilePath& path,
                                   const brillo::Blob& blob,
                                   mode_t mode) {
  return real_platform_.WriteFileAtomic(TestFilePath(path), blob, mode);
}

bool FakePlatform::WriteSecureBlobToFileAtomic(const base::FilePath& path,
                                               const brillo::SecureBlob& sblob,
                                               mode_t mode) {
  return real_platform_.WriteSecureBlobToFileAtomic(TestFilePath(path), sblob,
                                                    mode);
}

bool FakePlatform::WriteFileAtomicDurable(const base::FilePath& path,
                                          const brillo::Blob& blob,
                                          mode_t mode) {
  return real_platform_.WriteFileAtomicDurable(TestFilePath(path), blob, mode);
}

bool FakePlatform::WriteSecureBlobToFileAtomicDurable(
    const base::FilePath& path, const brillo::SecureBlob& sblob, mode_t mode) {
  return real_platform_.WriteSecureBlobToFileAtomicDurable(TestFilePath(path),
                                                           sblob, mode);
}

bool FakePlatform::WriteStringToFile(const base::FilePath& path,
                                     const std::string& str) {
  return real_platform_.WriteStringToFile(TestFilePath(path), str);
}

bool FakePlatform::WriteStringToFileAtomicDurable(const base::FilePath& path,
                                                  const std::string& str,
                                                  mode_t mode) {
  return real_platform_.WriteStringToFileAtomicDurable(TestFilePath(path), str,
                                                       mode);
}

bool FakePlatform::WriteArrayToFile(const base::FilePath& path,
                                    const char* data,
                                    size_t size) {
  return real_platform_.WriteArrayToFile(TestFilePath(path), data, size);
}

FILE* FakePlatform::OpenFile(const base::FilePath& path, const char* mode) {
  return real_platform_.OpenFile(TestFilePath(path), mode);
}

bool FakePlatform::CloseFile(FILE* file) {
  return real_platform_.CloseFile(file);
}

FileEnumerator* FakePlatform::GetFileEnumerator(const base::FilePath& path,
                                                bool recursive,
                                                int file_type) {
  return new ProxyFileEnumerator(path, this, fake_mount_mapper_.get(),
                                 real_platform_.GetFileEnumerator(
                                     TestFilePath(path), recursive, file_type));
}

bool FakePlatform::GetFileSize(const base::FilePath& path, int64_t* size) {
  return real_platform_.GetFileSize(TestFilePath(path), size);
}

bool FakePlatform::Stat(const base::FilePath& path, base::stat_wrapper_t* buf) {
  if (!real_platform_.Stat(TestFilePath(path), buf)) {
    return false;
  }
  // Override mode and ownership from internal fake mappings.
  mode_t mode;
  if (!GetPermissions(path, &mode)) {
    return false;
  }
  buf->st_mode &= ~01777;
  buf->st_mode |= mode;
  if (!GetOwnership(path, &buf->st_uid, &buf->st_gid, false)) {
    return false;
  }
  return true;
}

bool FakePlatform::StatVFS(const base::FilePath& path, struct statvfs* vfs) {
  return real_platform_.StatVFS(TestFilePath(path), vfs);
}

bool FakePlatform::HasExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  const auto it = xattrs_.find(real_path);
  if (it == xattrs_.end() || !it->second.Exists(name)) {
    // Client code checks the error code, so set it.
    errno = ENODATA;
    return false;
  }

  return true;
}

bool FakePlatform::ListExtendedFileAttributes(
    const base::FilePath& path, std::vector<std::string>* attr_list) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  const auto it = xattrs_.find(real_path);
  if (it == xattrs_.end()) {
    attr_list->clear();
    return true;
  }

  it->second.List(attr_list);
  return true;
}

bool FakePlatform::GetExtendedFileAttributeAsString(const base::FilePath& path,
                                                    const std::string& name,
                                                    std::string* value) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  const auto it = xattrs_.find(real_path);
  if (it == xattrs_.end() || !it->second.Exists(name)) {
    // Client code checks the error code, so set it.
    errno = ENODATA;
    return false;
  }

  return it->second.GetAsString(name, value);
}

bool FakePlatform::GetExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name,
                                            char* value,
                                            ssize_t size) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  const auto it = xattrs_.find(real_path);
  if (it == xattrs_.end() || !it->second.Exists(name)) {
    // Client code checks the error code, so set it.
    errno = ENODATA;
    return false;
  }

  return it->second.Get(name, value, size);
}

bool FakePlatform::SetExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name,
                                            const char* value,
                                            size_t size) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }

  auto [it, unused] =
      xattrs_.emplace(real_path, FakePlatform::FakeExtendedAttributes());

  it->second.Set(name, value, size);
  return true;
}

bool FakePlatform::RemoveExtendedFileAttribute(const base::FilePath& path,
                                               const std::string& name) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  auto it = xattrs_.find(real_path);
  if (it == xattrs_.end()) {
    return true;
  }

  it->second.Remove(name);
  return true;
}

bool FakePlatform::GetExtFileAttributes(const base::FilePath& path,
                                        int* flags) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  auto it = file_flags_.find(real_path);
  if (it == file_flags_.end()) {
    *flags = 0;
    return true;
  }
  *flags = it->second;
  return true;
}

bool FakePlatform::SetExtFileAttributes(const base::FilePath& path, int flags) {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  file_flags_[real_path] = flags;
  return true;
}

bool FakePlatform::HasNoDumpFileAttribute(const base::FilePath& path) {
  int flags;
  return GetExtFileAttributes(path, &flags) &&
         (flags & FS_NODUMP_FL) == FS_NODUMP_FL;
}

bool FakePlatform::GetOwnership(const base::FilePath& path,
                                uid_t* user_id,
                                gid_t* group_id,
                                bool follow_links) const {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  // Can not do it at present due to weird test dependencies.
  if (file_owners_.find(real_path) == file_owners_.end()) {
    *user_id = kChronosUid;
    *group_id = kChronosGid;
    return true;
  }

  *user_id = file_owners_.at(real_path).first;
  *group_id = file_owners_.at(real_path).second;
  return true;
}

bool FakePlatform::SetOwnership(const base::FilePath& path,
                                uid_t user_id,
                                gid_t group_id,
                                bool follow_links) const {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  file_owners_[real_path] = {user_id, group_id};
  return true;
}

bool FakePlatform::SafeDirChown(const base::FilePath& path,
                                uid_t user_id,
                                gid_t group_id) {
  if (!DirectoryExists(path)) {
    return false;
  }
  return SetOwnership(path, user_id, group_id, false);
}

bool FakePlatform::GetPermissions(const base::FilePath& path,
                                  mode_t* mode) const {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  if (file_mode_.find(real_path) == file_mode_.end()) {
    (*mode) = S_IRWXU | S_IRGRP | S_IXGRP;
    return true;
  }
  (*mode) = (file_mode_.at(real_path) & 01777);
  return true;
}

bool FakePlatform::SetPermissions(const base::FilePath& path,
                                  mode_t mode) const {
  base::AutoLock lock(mappings_lock_);
  const base::FilePath real_path = TestFilePath(path);
  if (!IsLink(path) && !FileExists(path)) {
    return false;
  }
  file_mode_[real_path] = mode & 01777;
  return true;
}

bool FakePlatform::SafeDirChmod(const base::FilePath& path, mode_t mode) {
  if (!DirectoryExists(path)) {
    return false;
  }
  return SetPermissions(path, mode);
}

bool FakePlatform::SafeCreateDirAndSetOwnershipAndPermissions(
    const base::FilePath& path, mode_t mode, uid_t user_id, gid_t gid) {
  if (!CreateDirectory(path) || !SafeDirChown(path, user_id, gid) ||
      !SafeDirChmod(path, mode)) {
    return false;
  }
  return true;
}

bool FakePlatform::SafeCreateDirAndSetOwnership(const base::FilePath& path,
                                                uid_t user_id,
                                                gid_t gid) {
  if (!CreateDirectory(path) || !SafeDirChown(path, user_id, gid)) {
    return false;
  }
  return true;
}

int64_t FakePlatform::AmountOfFreeDiskSpace(const base::FilePath& path) const {
  return real_platform_.AmountOfFreeDiskSpace(TestFilePath(path));
}

bool FakePlatform::Mount(const base::FilePath& from,
                         const base::FilePath& to,
                         const std::string& type,
                         uint32_t mount_flags,
                         const std::string& mount_options) {
  base::FilePath nfrom = NormalizePath(from);
  base::FilePath nto = NormalizePath(to);
  if (type == "ecryptfs") {
    // In the case of ecryptfs we more or less transparently overlay
    // directories, so it looks more like a bind rather than a mount.
    return fake_mount_mapper_->Bind(nfrom, nto);
  }
  return fake_mount_mapper_->Mount(nfrom, nto);
}

bool FakePlatform::Bind(const base::FilePath& from,
                        const base::FilePath& to,
                        RemountOption remount,
                        bool nosymfollow) {
  base::FilePath nfrom = NormalizePath(from);
  base::FilePath nto = NormalizePath(to);
  return fake_mount_mapper_->Bind(nfrom, nto);
}

bool FakePlatform::Unmount(const base::FilePath& path,
                           bool lazy,
                           bool* was_busy) {
  base::FilePath normalized_path = NormalizePath(path);
  bool ok = fake_mount_mapper_->Unmount(normalized_path);
  if (was_busy != nullptr) {
    *was_busy = !ok;
  }
  return true;
}

void FakePlatform::LazyUnmount(const base::FilePath& path) {
  base::FilePath normalized_path = NormalizePath(path);
  // TODO(dlunev): actually implement lazy unmount in fake mapper, for now busy
  // target will just fail silently.
  (void)fake_mount_mapper_->Unmount(normalized_path);
}

bool FakePlatform::GetLoopDeviceMounts(
    std::multimap<const base::FilePath, const base::FilePath>* mounts) {
  constexpr char kLoopPrefix[] = "/dev/loop";
  fake_mount_mapper_->ListMountsBySourcePrefix(kLoopPrefix, mounts);
  return true;
}

bool FakePlatform::GetMountsBySourcePrefix(
    const base::FilePath& from_prefix,
    std::multimap<const base::FilePath, const base::FilePath>* mounts) {
  fake_mount_mapper_->ListMountsBySourcePrefix(from_prefix, mounts);
  return true;
}

bool FakePlatform::IsDirectoryMounted(const base::FilePath& directory) {
  const base::FilePath ndirectory = NormalizePath(directory);
  return fake_mount_mapper_->IsMounted(ndirectory);
}

std::optional<std::vector<bool>> FakePlatform::AreDirectoriesMounted(
    const std::vector<base::FilePath>& directories) {
  std::vector<bool> result;
  result.reserve(directories.size());
  for (const auto& d : directories) {
    result.push_back(IsDirectoryMounted(d));
  }
  return result;
}

// Test API

void FakePlatform::SetSystemSaltForLibbrillo(const brillo::SecureBlob& salt) {
  DCHECK(!old_salt_);
  std::string* brillo_salt = new std::string();
  brillo_salt->resize(salt.size());
  brillo_salt->assign(reinterpret_cast<const char*>(salt.data()), salt.size());
  old_salt_ = brillo::cryptohome::home::GetSystemSalt();
  brillo::cryptohome::home::SetSystemSalt(brillo_salt);
}

void FakePlatform::RemoveSystemSaltForLibbrillo() {
  std::string* salt = brillo::cryptohome::home::GetSystemSalt();
  brillo::cryptohome::home::SetSystemSalt(old_salt_);
  delete salt;
  old_salt_ = nullptr;
}

}  // namespace cryptohome
