blob: 4432dff4ddb4ee9881edfb2fb735b01fc22c7780 [file] [log] [blame]
// Copyright (c) 2012 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.
// Defines cros-disks::MountManager, which is a base class for implementing
// the filesystem mounting service used by CrosDisksServer. It is further
// subclassed to provide the mounting service for particular types of
// filesystem.
#ifndef CROS_DISKS_MOUNT_MANAGER_H_
#define CROS_DISKS_MOUNT_MANAGER_H_
#include <map>
#include <set>
#include <string>
#include <vector>
#include <base/macros.h>
#include <chromeos/dbus/service_constants.h>
#include <gtest/gtest_prod.h>
#include "cros-disks/mount_options.h"
namespace cros_disks {
class Metrics;
class MountEntry;
class Platform;
// A base class for managing mounted filesystems of certain kinds.
// It provides template methods for mounting and unmounting filesystems.
// A derived class implements pure virtual methods CanMount, DoMount,
// DoUnmount and SuggestMountPath to provide specific operations for
// supporting certain kinds of filesystem.
class MountManager {
public:
// Represents status of a mounted volume.
struct MountState {
std::string mount_path;
bool is_read_only;
};
// Constructor that takes a mount root directory, an object for providing
// platform service, and an object for collecting UMA metrics. The mount
// root directory |mount_root| must be a non-empty path string, but it is
// OK if the directory does not exist. Both |platform| and |metrics| must
// be a valid object. An instance of this class does not take ownership
// of the |platform| and |metrics| object, and thus expects these objects
// to exist until its destruction. No actual operation is performed at
// construction. Initialization is performed when Initializes() is called.
MountManager(const std::string& mount_root, Platform* platform,
Metrics* metrics);
// Destructor that performs no specific operations and does not unmount
// any mounted or reserved mount paths. A derived class should override
// the destructor to perform appropriate cleanup, such as unmounting
// mounted filesystems.
virtual ~MountManager();
// Initializes the mount manager. Returns true on success.
// It must be called only once before other methods are called.
// This base class provides a default implementation that creates the
// mount root directory. A derived class can override this method to
// perform any necessary initialization.
virtual bool Initialize();
// Starts a session. Returns true on success.
// This base class provides a default implementation that does nothing.
// A derived class can override this method to perform any necessary
// operations when a session starts. This method is called in response
// to a SessionStateChanged event from the Chromium OS session manager.
virtual bool StartSession();
// Stops a session. Returns true on success.
// This base class provides a default implementation that does nothing.
// A derived class can override this method to perform any necessary
// operations when a session stops. This method is called in response
// to a SessionStateChanged event from the Chromium OS session manager.
virtual bool StopSession();
// Implemented by a derived class to return true if it supports mounting
// |source_path|.
virtual bool CanMount(const std::string& source_path) const = 0;
// Returns true if unmounting |path| is supported by the manager.
// This base class provides a default implementation such that a path
// can be unmounted by the manager if it can be mounted by the manager
// or is an immediate child of the mount root directory where mount
// directories are created. A derived class can override this method to
// support additional paths.
virtual bool CanUnmount(const std::string& path) const;
// Implemented by a derived class to return the type of mount sources
// it supports.
virtual MountSourceType GetMountSourceType() const = 0;
// Mounts |source_path| to |mount_path| as |filesystem_type| with |options|.
// If |mount_path| is an empty string, SuggestMountPath() is called to
// obtain a suggested mount path. |mount_path| is set to actual mount path
// on success. If an error occurs and ShouldReserveMountPathOnError()
// returns true for that type of error, the mount path is reserved and
// |mount_path| is set to the reserved mount path.
MountErrorType Mount(const std::string& source_path,
const std::string& filesystem_type,
const std::vector<std::string>& options,
std::string *mount_path);
// Unmounts |path|, which can be a source path or a mount path,
// with |options|. If the mount path is reserved during Mount(),
// this method releases the reserved mount path.
MountErrorType Unmount(const std::string& path,
const std::vector<std::string>& options);
// Unmounts all mounted paths.
virtual bool UnmountAll();
// Adds a mapping from |source_path| to |mount_path| to the cache.
// Returns false if |source_path| is already in the cache.
bool AddMountPathToCache(const std::string& source_path,
const std::string& mount_path,
bool is_read_only);
// Gets the corresponding |source_path| of |mount_path| from the cache.
// Returns false if |mount_path| is not found in the cache.
bool GetSourcePathFromCache(const std::string& mount_path,
std::string* source_path) const;
// Gets the corresponding |mount_path| of |source_path| from the cache.
// Returns false if |source_path| is not found in the cache.
bool GetMountPathFromCache(const std::string& source_path,
std::string* mount_path) const;
// Gets the corresponding mount state of |source_path| from the cache.
// Returns false if |source_path| is not found in the cache.
bool GetMountStateFromCache(const std::string& source_path,
MountState* mount_state) const;
// Returns true if |mount_path| is found in the cache.
bool IsMountPathInCache(const std::string& mount_path) const;
// Removes |mount_path| from the cache. Returns false if |mount_path|
// is not found in the cache.
bool RemoveMountPathFromCache(const std::string& mount_path);
// Returns true if |mount_path| is reserved.
bool IsMountPathReserved(const std::string& mount_path) const;
// Returns the mount error that caused |mount_path| to be reserved, or
// kMountErrorNone if |mount_path| is not a reserved path.
MountErrorType GetMountErrorOfReservedMountPath(
const std::string& mount_path) const;
// Returns a set of reserved mount paths.
std::set<std::string> GetReservedMountPaths() const;
// Adds |mount_path| to the set of reserved mount paths. Also records
// |error_type| that caused the mount path to be reserved. If a |mount_path|
// has been reserved, subsequent calls to this method with the same
// |mount_path| but different |error_type| are ignored.
void ReserveMountPath(const std::string& mount_path,
MountErrorType error_type);
// Removes |mount_path| from the set of reserved mount paths.
void UnreserveMountPath(const std::string& mount_path);
// Gets the mount entries managed by this mount manager. |mount_entries| is
// overwritten to return the mount entries.
void GetMountEntries(std::vector<MountEntry>* mount_entries);
protected:
// Type definition of a cache mapping a source path to its mount state of
// filesystems mounted by the manager.
using MountStateMap = std::map<std::string, MountState>;
// Type definition of a cache mapping a reserved mount path to the mount
// error that caused the mount path to be reserved.
using ReservedMountPathMap = std::map<std::string, MountErrorType>;
// Implemented by a derived class to mount |source_path| to |mount_path|
// as |filesystem_type| with |options|. An implementation may change the
// options to mount command, and should store all options to
// |applied_options|.
virtual MountErrorType DoMount(const std::string& source_path,
const std::string& filesystem_type,
const std::vector<std::string>& options,
const std::string& mount_path,
MountOptions* applied_options) = 0;
// Implemented by a derived class to unmount |path| with |options|.
virtual MountErrorType DoUnmount(const std::string& path,
const std::vector<std::string>& options) = 0;
// Returns a suggested mount path for |source_path|.
virtual std::string SuggestMountPath(
const std::string& source_path) const = 0;
// Extracts the mount label, if any, from an array of options.
// If a mount label option is found in |options|, returns true, sets
// |mount_label| to the mount label value, and removes the option from
// |options|. If multiple mount label options are given, |mount_label|
// is set to the last mount label value.
bool ExtractMountLabelFromOptions(std::vector<std::string>* options,
std::string* mount_label) const;
// Extracts unmount flags for umount() from an array of options.
virtual bool ExtractUnmountOptions(const std::vector<std::string>& options,
int *unmount_flags) const;
// Returns true if the manager should reserve a mount path if the mount
// operation returns a particular type of error. The default implementation
// returns false on any error. A derived class should override this method
// if it needs to reserve mount paths on certain types of error.
virtual bool ShouldReserveMountPathOnError(MountErrorType error_type) const;
// Returns true if |path| is an immediate child of |parent|, i.e.
// |path| is an immediate file or directory under |parent|.
bool IsPathImmediateChildOfParent(const std::string& path,
const std::string& parent) const;
// Returns true if |mount_path| is a valid mount path, which should be an
// immediate child of the mount root specified by |mount_root_|. The check
// performed by this method takes the simplest approach and does not first try
// to canonicalize |mount_path|, resolve symlinks or determine the absolute
// path of |mount_path|, so a legitimate mount path may be deemed as invalid.
// But we don't consider these cases as part of the use cases of cros-disks.
bool IsValidMountPath(const std::string& mount_path) const;
// Returns the root directory under which mount directories are created.
const std::string& mount_root() const { return mount_root_; }
// Returns an object that provides platform service.
Platform* platform() const { return platform_; }
// Returns an object that collects UMA metrics.
Metrics* metrics() const { return metrics_; }
private:
// The root directory under which mount directories are created.
std::string mount_root_;
// An object that provides platform service.
Platform* platform_;
// An object that collects UMA metrics.
Metrics* metrics_;
// A cache mapping a source path to its mount state of filesystems mounted
// by the manager.
MountStateMap mount_states_;
// A cache mapping a reserved mount path to the error that caused
// the path to reserved.
ReservedMountPathMap reserved_mount_paths_;
FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptions);
FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptionsWithNoMountLabel);
FRIEND_TEST(MountManagerTest, ExtractMountLabelFromOptionsWithTwoMountLabels);
FRIEND_TEST(MountManagerTest, ExtractSupportedUnmountOptions);
FRIEND_TEST(MountManagerTest, ExtractUnsupportedUnmountOptions);
FRIEND_TEST(MountManagerTest, IsPathImmediateChildOfParent);
FRIEND_TEST(MountManagerTest, IsValidMountPath);
DISALLOW_COPY_AND_ASSIGN(MountManager);
};
} // namespace cros_disks
#endif // CROS_DISKS_MOUNT_MANAGER_H_