blob: e4badb71c5a975f8e99a5ca83bec0be8b6324672 [file] [log] [blame]
// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements. See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership. The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License. You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef __FS_HPP__
#define __FS_HPP__
#include <mntent.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <string>
#include <vector>
#include <stout/nothing.hpp>
#include <stout/option.hpp>
#include <stout/try.hpp>
// Define relevant MS_* flags for old includes.
// This is taken from the enum in sys/mount.h.
#ifndef MS_RDONLY
#define MS_RDONLY 1
#endif
#ifndef MS_NOSUID
#define MS_NOSUID 2
#endif
#ifndef MS_NODEV
#define MS_NODEV 4
#endif
#ifndef MS_NOEXEC
#define MS_NOEXEC 8
#endif
#ifndef MS_SYNCHRONOUS
#define MS_SYNCHRONOUS 16
#endif
#ifndef MS_REMOUNT
#define MS_REMOUNT 32
#endif
#ifndef MS_MANDLOCK
#define MS_MANDLOCK 64
#endif
#ifndef MS_DIRSYNC
#define MS_DIRSYNC 128
#endif
#ifndef MS_NOATIME
#define MS_NOATIME 1024
#endif
#ifndef MS_NODIRATIME
#define MS_NODIRATIME 2048
#endif
#ifndef MS_BIND
#define MS_BIND 4096
#endif
#ifndef MS_MOVE
#define MS_MOVE 8192
#endif
#ifndef MS_REC
#define MS_REC 16384
#endif
#ifndef MS_SILENT
#define MS_SILENT 32768
#endif
#ifndef MS_POSIXACL
#define MS_POSIXACL (1 << 16)
#endif
#ifndef MS_UNBINDABLE
#define MS_UNBINDABLE (1 << 17)
#endif
#ifndef MS_PRIVATE
#define MS_PRIVATE (1 << 18)
#endif
#ifndef MS_SLAVE
#define MS_SLAVE (1 << 19)
#endif
#ifndef MS_SHARED
#define MS_SHARED (1 << 20)
#endif
#ifndef MS_RELATIME
#define MS_RELATIME (1 << 21)
#endif
#ifndef MS_KERNMOUNT
#define MS_KERNMOUNT (1 << 22)
#endif
#ifndef MS_I_VERSION
#define MS_I_VERSION (1 << 23)
#endif
#ifndef MS_STRICTATIME
#define MS_STRICTATIME (1 << 24)
#endif
#ifndef MS_ACTIVE
#define MS_ACTIVE (1 << 30)
#endif
#ifndef MS_NOUSER
#define MS_NOUSER (1 << 31)
#endif
#ifndef MNT_FORCE
#define MNT_FORCE 1
#endif
#ifndef MNT_DETACH
#define MNT_DETACH 2
#endif
#ifndef MNT_EXPIRE
#define MNT_EXPIRE 4
#endif
#ifndef UMOUNT_NOFOLLOW
#define UMOUNT_NOFOLLOW 8
#endif
// Define FS_MAGIC_* flags for filesystem types.
// http://man7.org/linux/man-pages/man2/fstatfs64.2.html
#define FS_TYPE_AUFS 0x61756673
#define FS_TYPE_BTRFS 0x9123683E
#define FS_TYPE_CRAMFS 0x28cd3d45
#define FS_TYPE_ECRYPTFS 0xf15f
#define FS_TYPE_EXTFS 0x0000EF53
#define FS_TYPE_F2FS 0xF2F52010
#define FS_TYPE_GPFS 0x47504653
#define FS_TYPE_JFFS2FS 0x000072b6
#define FS_TYPE_JFS 0x3153464a
#define FS_TYPE_NFSFS 0x00006969
#define FS_TYPE_RAMFS 0x858458f6
#define FS_TYPE_REISERFS 0x52654973
#define FS_TYPE_SMBFS 0x0000517B
#define FS_TYPE_SQUASHFS 0x73717368
#define FS_TYPE_TMPFS 0x01021994
#define FS_TYPE_VXFS 0xa501fcf5
#define FS_TYPE_XFS 0x58465342
#define FS_TYPE_ZFS 0x2fc12fc1
#define FS_TYPE_OVERLAY 0x794C7630
namespace mesos {
namespace internal {
namespace fs {
// Detect whether the given file system is supported by the kernel.
Try<bool> supported(const std::string& fsname);
// Detect whether the given file system supports `d_type`
// in `struct dirent`.
// @directory must not be empty for correct `d_type` detection.
// It is the caller's responsibility to ensure this holds.
Try<bool> dtypeSupported(const std::string& directory);
// Returns a filesystem type id, given a directory.
// http://man7.org/linux/man-pages/man2/fstatfs64.2.html
Try<uint32_t> type(const std::string& path);
// Returns the filesystem type name, given a filesystem type id.
Try<std::string> typeName(uint32_t fsType);
// TODO(idownes): These different variations of mount information
// should be consolidated and moved to stout, along with mount and
// umount.
// Structure describing the per-process mounts as found in
// /proc/[pid]/mountinfo. In particular, entries in this table specify
// the propagation properties of mounts, information not present in
// the MountTable or /etc/fstab. Entry order is preserved when
// parsing /proc/[pid]/mountinfo.
struct MountInfoTable {
// Structure describing an individual /proc/[pid]/mountinfo entry.
// See the /proc/[pid]/mountinfo section in 'man proc' for further
// details on each field.
struct Entry {
static Try<Entry> parse(const std::string& s);
Entry() {}
// Returns the ID of the peer group in which this mount resides.
// Returns none if this mount is not a shared mount.
Option<int> shared() const;
// Returns the ID of the peer group in which this mount's master
// resides in. Returns none if this mount is not a slave mount.
Option<int> master() const;
int id; // mountinfo[1]: mount ID.
int parent; // mountinfo[2]: parent ID.
dev_t devno; // mountinfo[3]: st_dev.
std::string root; // mountinfo[4]: root of the mount.
std::string target; // mountinfo[5]: mount point.
// Filesystem independent (VFS) options, e.g., "rw,noatime".
std::string vfsOptions; // mountinfo[6]: per-mount options.
// Filesystem dependent options, e.g., "rw,memory" for a memory
// cgroup filesystem.
std::string fsOptions; // mountinfo[11]: per-block options.
// Current possible optional fields include shared:X, master:X,
// propagate_from:X, unbindable.
std::string optionalFields; // mountinfo[7]: optional fields.
// mountinfo[8] is a separator.
std::string type; // mountinfo[9]: filesystem type.
std::string source; // mountinfo[10]: source dev, other.
};
// Read the mountinfo table for a process.
// @param pid The `pid` of the process for which we should
// read the mountinfo table. If `pid` is None(),
// then "self" is used, i.e., the mountinfo table
// for the calling process.
// @param hierarchicalSort
// A boolean indicating whether the entries in the
// mountinfo table should be sorted according to
// their parent / child relationship (as opposed to
// the temporal ordering of when they were
// mounted). The two orderings may differ (for
// example) if a filesystem is remounted after some
// of its children have been mounted.
// @return An instance of MountInfoTable if success.
static Try<MountInfoTable> read(
const Option<pid_t>& pid = None(),
bool hierarchicalSort = true);
// Read a mountinfo table from a string.
// @param lines The contents of a mountinfo table represented as
// a string. Different entries in the string are
// separated by a newline.
// @param hierarchicalSort
// A boolean indicating whether the entries in the
// mountinfo table should be sorted according to
// their parent / child relationship (as opposed to
// the temporal ordering of when they were
// mounted). The two orderings may differ (for
// example) if a filesystem is remounted after some
// of its children have been mounted.
// @return An instance of MountInfoTable if success.
static Try<MountInfoTable> read(
const std::string& lines,
bool hierarchicalSort = true);
// Find the mount table entry by the given target path. If there is
// no mount table entry that matches the exact target path, return
// the mount table entry that is the immediate parent of the given
// target path (similar to `findmnt --target [TARGET]`).
Try<Entry> findByTarget(const std::string& target);
std::vector<Entry> entries;
};
// Structure describing a mount table (e.g. /etc/mtab or /proc/mounts).
struct MountTable {
// Structure describing a mount table entry. This is a wrapper for struct
// mntent defined in <mntent.h>.
struct Entry {
Entry() : freq(0), passno(0) {}
Entry(const std::string& _fsname,
const std::string& _dir,
const std::string& _type,
const std::string& _opts,
int _freq,
int _passno)
: fsname(_fsname),
dir(_dir),
type(_type),
opts(_opts),
freq(_freq),
passno(_passno)
{}
// Check whether a given mount option exists in a mount table entry.
// @param option The given mount option.
// @return Whether the given mount option exists.
bool hasOption(const std::string& option) const;
std::string fsname; // Device or server for filesystem.
std::string dir; // Directory mounted on.
std::string type; // Type of filesystem: ufs, nfs, etc.
std::string opts; // Comma-separated options for fs.
int freq; // Dump frequency (in days).
int passno; // Pass number for `fsck'.
};
// Read the mount table from a file.
// @param path The path of the file storing the mount table.
// @return An instance of MountTable if success.
static Try<MountTable> read(const std::string& path);
std::vector<Entry> entries;
};
// Mount a file system.
// @param source Specify the file system (often a device name but
// it can also be a directory for a bind mount).
// If None(), nullptr will be passed as a dummy
// argument to mount(), i.e., it is not used for
// the specified mount operation. For example, you
// can mount a filesystem specified in /etc/fstab
// by just specifying the target.
// @param target Directory to be attached to.
// @param type File system type (listed in /proc/filesystems).
// If None(), nullptr will be passed as a dummy
// argument to mount(), i.e., it is not used for
// the specified mount operation. For example, it
// should be None() for a bind mount as it will
// inherit the type of the source.
// @param flags Mount flags.
// @param data Extra data interpreted by different file systems.
// @return Whether the mount operation succeeds.
//
// Note that if this is a read-only bind mount (both the MS_BIND
// and MS_READONLY flags are set), the target will automatically
// be remounted in read-only mode.
Try<Nothing> mount(const Option<std::string>& source,
const std::string& target,
const Option<std::string>& type,
unsigned long flags,
const void* data);
// Alternate version of mount which passes an option string as
// additional data for the filesystem mount.
Try<Nothing> mount(const Option<std::string>& source,
const std::string& target,
const Option<std::string>& type,
unsigned long flags,
const Option<std::string>& options);
// Unmount a file system.
// @param target The (topmost) directory where the file system attaches.
// @param flags Unmount flags.
// @return Whether the unmount operation succeeds.
Try<Nothing> unmount(const std::string& target, int flags = 0);
// Unmount a file system and all mounts under that file system.
// @param target The (topmost) directory where the file system attaches.
// @param flags Unmount flags.
// @return Whether the unmountAll operation succeeds.
Try<Nothing> unmountAll(const std::string& target, int flags = 0);
// Change the root filesystem.
Try<Nothing> pivot_root(const std::string& newRoot, const std::string& putOld);
namespace chroot {
// Clone a device node to a target directory. Intermediate directory paths
// are created in the target.
Try<Nothing> copyDeviceNode(
const std::string& device, const std::string& target);
// Enter a 'chroot' environment. The caller should be in a new mount
// unmounted. The root path must have already been provisioned by
// calling `prepare`()`.
Try<Nothing> enter(const std::string& root);
} // namespace chroot {
} // namespace fs {
} // namespace internal {
} // namespace mesos {
#endif // __FS_HPP__