blob: aea3b74ac0629207f84928d3a0b7e1d8a7008814 [file] [log] [blame]
// Copyright 2021 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.
#ifndef CRYPTOHOME_FAKE_PLATFORM_FAKE_MOUNT_MAPPER_H_
#define CRYPTOHOME_FAKE_PLATFORM_FAKE_MOUNT_MAPPER_H_
#include <map>
#include <memory>
#include <optional>
#include <string>
#include <unordered_map>
#include <base/files/file_path.h>
#include "cryptohome/fake_platform/real_fake_mount_mapping_redirect_factory.h"
namespace cryptohome {
// A wrapper class for a single mount mapping.
class FakeMountMapping final {
public:
FakeMountMapping(const FakeMountMapping& mapping) = default;
~FakeMountMapping() = default;
// Given the path, translate it from the target to the source.
base::FilePath TranslateTargetToSource(const base::FilePath&) const;
// Given the path, translate it from the source to the target.
base::FilePath TranslateSourceToTarget(const base::FilePath&) const;
// Given the path, translate it from the target to the redirect.
base::FilePath TranslateTargetToRedirect(const base::FilePath&) const;
// Given the path, translate it from the redirect to the target.
base::FilePath TranslateRedirectToTarget(const base::FilePath&) const;
const base::FilePath& GetSource() const;
const base::FilePath& GetTarget() const;
const base::FilePath& GetRedirect() const;
private:
FakeMountMapping(const base::FilePath& source,
const base::FilePath& target,
const base::FilePath& redirect);
const base::FilePath source_;
const base::FilePath target_;
const base::FilePath redirect_;
friend class FakeMountMapper;
};
// FakeMountMapper maintains the mapping of mounts and provides a method to
// resolve the actual physical location of a path.
// The main internal concept of the class is a "redirect".
// Redirect is a directory, which is a physical location of the files shown
// under the mount target directory.
// In the case of Bind, redirect is a physical location of the
// source within tmpfs.
// In the case of Mount, redirect is a newly created /tmp/<unique id> directory,
// to simulate a persistent storage within a block device or encrypted fs.
class FakeMountMapper final {
public:
FakeMountMapper(
const base::FilePath& tmpfs_rootfs,
std::unique_ptr<FakeMountMappingRedirectFactory> redirect_factory =
std::make_unique<RealFakeMountMappingRedirectFactory>());
~FakeMountMapper();
bool Mount(const base::FilePath& source, const base::FilePath& target);
bool Bind(const base::FilePath& source, const base::FilePath& target);
bool Unmount(const base::FilePath& target);
// Returns true if the path is a target of a Bind or Mount.
bool IsMounted(const base::FilePath& path) const;
// Returns true if the path is a target or within a target of Bind or Mount.
bool IsOnMount(const base::FilePath& target) const;
void ListMountsBySourcePrefix(
const std::string& source_prefix,
std::multimap<const base::FilePath, const base::FilePath>* mounts) const;
void ListMountsBySourcePrefix(
const base::FilePath& source_prefix,
std::multimap<const base::FilePath, const base::FilePath>* mounts) const;
// Translates a path within the "represented" file system to the actual
// physical location in tmpfs.
base::FilePath ResolvePath(const base::FilePath& path) const;
// Transforms a physical location in tmpfs to a logical location within
// a "represented" filesystem. Since the transformation may yield multiple
// results (a directory mounted to multiple places), `expected_parent` defines
// which result should be used - it needs to be a child of `expected_parent`.
// If matching `expected_parent` also yields multiple results, then the method
// returns any matching path out of all possible (the choice is not guaranteed
// to be deterministic and may wary among invocations and program runs).
base::FilePath ReverseResolvePath(
const base::FilePath& path, const base::FilePath& expected_parent) const;
private:
const base::FilePath tmpfs_rootfs_;
const std::unique_ptr<FakeMountMappingRedirectFactory> redirect_factory_;
std::map<base::FilePath, FakeMountMapping> target_to_mount_;
std::unordered_map<base::FilePath, base::FilePath> source_to_redirect_;
bool MountImpl(const base::FilePath& source,
const base::FilePath& target,
const base::FilePath& redirect);
// Returns mapping if the target is or on the mount, std::nullopt otherwise.
std::optional<FakeMountMapping> FindMapping(
const base::FilePath& target) const;
};
} // namespace cryptohome
#endif // CRYPTOHOME_FAKE_PLATFORM_FAKE_MOUNT_MAPPER_H_