// 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.

// Contains the implementation of class Platform

#include "cryptohome/fake_platform.h"

#include <memory>
#include <string>
#include <sys/stat.h>
#include <sys/types.h>
#include <vector>

#include <base/check.h>
#include <base/files/file_path.h>
#include <base/logging.h>
#include <brillo/cryptohome.h>
#include <brillo/secure_blob.h>

namespace cryptohome {

namespace {

class ProxyFileEnumerator : public FileEnumerator {
 public:
  ProxyFileEnumerator(const base::FilePath& tmpfs_rootfs,
                      FileEnumerator* real_enumerator)
      : tmpfs_rootfs_(tmpfs_rootfs), real_enumerator_(real_enumerator) {}

  // Removed tmpfs prefix from the returned path.
  base::FilePath Next() override {
    base::FilePath next = real_enumerator_->Next();
    if (!tmpfs_rootfs_.IsParent(next)) {
      return next;
    }
    base::FilePath assumed_path("/");
    CHECK(tmpfs_rootfs_.AppendRelativePath(next, &assumed_path));
    return assumed_path;
  }

  FileEnumerator::FileInfo GetInfo() override {
    return real_enumerator_->GetInfo();
  }

 private:
  base::FilePath tmpfs_rootfs_;
  std::unique_ptr<FileEnumerator> real_enumerator_;
};

}  // namespace

// Constructor/destructor

FakePlatform::FakePlatform() : Platform() {
  base::GetTempDir(&tmpfs_rootfs_);
  tmpfs_rootfs_ = tmpfs_rootfs_.Append(real_platform_.GetRandomSuffix());
  if (!real_platform_.CreateDirectory(tmpfs_rootfs_)) {
    LOG(ERROR) << "Failed to create test dir: " << tmpfs_rootfs_;
  }
}

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

// Helpers

base::FilePath FakePlatform::TestFilePath(const base::FilePath& path) const {
  std::string path_str = path.NormalizePathSeparators().value();
  // Make the path relative.
  CHECK(path.IsAbsolute());
  if (path_str.length() > 0 && path_str[0] == '/') {
    path_str = path_str.substr(1);
  }
  return tmpfs_rootfs_.Append(path_str);
}

// Platform API

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::DeleteFile(const base::FilePath& path) {
  return real_platform_.DeleteFile(TestFilePath(path));
}

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

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

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

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

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::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(
      tmpfs_rootfs_, 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::HasExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name) {
  return real_platform_.HasExtendedFileAttribute(TestFilePath(path), name);
}

bool FakePlatform::ListExtendedFileAttributes(
    const base::FilePath& path, std::vector<std::string>* attr_list) {
  return real_platform_.ListExtendedFileAttributes(TestFilePath(path),
                                                   attr_list);
}

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

bool FakePlatform::GetExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name,
                                            char* value,
                                            ssize_t size) {
  return real_platform_.GetExtendedFileAttribute(TestFilePath(path), name,
                                                 value, size);
}

bool FakePlatform::SetExtendedFileAttribute(const base::FilePath& path,
                                            const std::string& name,
                                            const char* value,
                                            size_t size) {
  return real_platform_.SetExtendedFileAttribute(TestFilePath(path), name,
                                                 value, size);
}

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

bool FakePlatform::GetOwnership(const base::FilePath& path,
                                uid_t* user_id,
                                gid_t* group_id,
                                bool follow_links) const {
  // TODO(chromium:1141301, dlunev): here and further check for file existence.
  // Can not do it at present due to weird test dependencies.
  if (file_owners_.find(path) == file_owners_.end()) {
    *user_id = fake_platform::kChronosUID;
    *group_id = fake_platform::kChronosGID;
    return true;
  }

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

bool FakePlatform::SetOwnership(const base::FilePath& path,
                                uid_t user_id,
                                gid_t group_id,
                                bool follow_links) const {
  file_owners_[path] = {user_id, group_id};
  return true;
}

bool FakePlatform::GetPermissions(const base::FilePath& path,
                                  mode_t* mode) const {
  if (file_mode_.find(path) == file_mode_.end()) {
    *mode = S_IRWXU | S_IRGRP | S_IXGRP;
    return true;
  }
  *mode = file_mode_.at(path);
  return true;
}

bool FakePlatform::SetPermissions(const base::FilePath& path,
                                  mode_t mode) const {
  file_mode_[path] = mode;
  return true;
}

bool FakePlatform::FakePlatform::GetUserId(const std::string& user,
                                           uid_t* user_id,
                                           gid_t* group_id) const {
  CHECK(user_id);
  CHECK(group_id);

  if (uids_.find(user) == uids_.end() || gids_.find(user) == gids_.end()) {
    LOG(ERROR) << "No user: " << user;
    return false;
  }

  *user_id = uids_.at(user);
  *group_id = gids_.at(user);
  return true;
}

bool FakePlatform::GetGroupId(const std::string& group, gid_t* group_id) const {
  CHECK(group_id);

  if (gids_.find(group) == gids_.end()) {
    LOG(ERROR) << "No group: " << group;
    return false;
  }

  *group_id = gids_.at(group);
  return true;
}

// Test API

void FakePlatform::SetUserId(const std::string& user, uid_t user_id) {
  CHECK(uids_.find(user) == uids_.end());

  uids_[user] = user_id;
}

void FakePlatform::SetGroupId(const std::string& group, gid_t group_id) {
  CHECK(gids_.find(group) == gids_.end());

  gids_[group] = group_id;
}

void FakePlatform::SetStandardUsersAndGroups() {
  SetUserId(fake_platform::kRoot, fake_platform::kRootUID);
  SetGroupId(fake_platform::kRoot, fake_platform::kRootGID);
  SetUserId(fake_platform::kChapsUser, fake_platform::kChapsUID);
  SetGroupId(fake_platform::kChapsUser, fake_platform::kChapsGID);
  SetUserId(fake_platform::kChronosUser, fake_platform::kChronosUID);
  SetGroupId(fake_platform::kChronosUser, fake_platform::kChronosGID);
  SetGroupId(fake_platform::kSharedGroup, fake_platform::kSharedGID);
}

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

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

}  // namespace cryptohome
