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

#include "linux/fs.hpp"

#include <errno.h>
#include <stdio.h>
#include <string.h>

#include <linux/limits.h>
#include <linux/unistd.h>

// This header include must be enclosed in an `extern "C"` block to
// workaround a bug in glibc <= 2.12 (see MESOS-7378).
//
// TODO(neilc): Remove this when we no longer support glibc <= 2.12.
extern "C" {
#include <sys/sysmacros.h>
}

#include <list>
#include <set>
#include <utility>

#include <stout/adaptor.hpp>
#include <stout/check.hpp>
#include <stout/error.hpp>
#include <stout/hashmap.hpp>
#include <stout/hashset.hpp>
#include <stout/numify.hpp>
#include <stout/option.hpp>
#include <stout/os.hpp>
#include <stout/path.hpp>
#include <stout/strings.hpp>
#include <stout/synchronized.hpp>

#include <stout/os/exec.hpp>
#include <stout/os/read.hpp>
#include <stout/os/realpath.hpp>
#include <stout/os/stat.hpp>

#include "common/status_utils.hpp"

using std::list;
using std::set;
using std::string;
using std::vector;

namespace mesos {
namespace internal {
namespace fs {


Try<bool> supported(const string& fsname)
{
  hashset<string> overlayfs{"overlay", "overlayfs"};

  Try<string> lines = os::read("/proc/filesystems");
  if (lines.isError()) {
    return Error("Failed to read /proc/filesystems: " + lines.error());
  }

  // Each line of /proc/filesystems is "nodev" + "\t" + "fsname", and the
  // field "nodev" is optional. For the details, check the kernel src code:
  // https://github.com/torvalds/linux/blob/2101ae42899a14fe7caa73114e2161e778328661/fs/filesystems.c#L222-L237 NOLINT(whitespace/line_length)
  foreach (const string& line, strings::tokenize(lines.get(), "\n")) {
    vector<string> tokens = strings::tokenize(line, "\t");
    if (tokens.size() != 1 && tokens.size() != 2) {
      return Error("Failed to parse /proc/filesystems: '" + line + "'");
    }

    // The "overlayfs" was renamed to "overlay" in kernel 4.2, for overlay
    // support check function, it should check both "overlay" and "overlayfs"
    // in "/proc/filesystems".
    if (overlayfs.contains(fsname) && overlayfs.contains(tokens.back())) {
      return true;
    }

    if (fsname == tokens.back()) {
      return true;
    }
  }

  return false;
}


Try<bool> dtypeSupported(const string& directory)
{
  DIR* dir = ::opendir(directory.c_str());

  if (dir == nullptr) {
    return ErrnoError("Failed to open '" + directory + "'");
  }

  bool result = true;
  struct dirent* entry;

  errno = 0;
  while ((entry = ::readdir(dir)) != nullptr) {
    if (entry->d_type == DT_UNKNOWN) {
      result = false;
    }
  }

  if (errno != 0) {
    Error error = ErrnoError("Failed to read '" + directory + "'");
    ::closedir(dir);
    return error;
  }

  if (::closedir(dir) == -1) {
    return ErrnoError("Failed to close '" + directory + "'");
  }

  return result;
}


Try<uint32_t> type(const string& path)
{
  struct statfs buf;
  if (statfs(path.c_str(), &buf) < 0) {
    return ErrnoError();
  }
  return (uint32_t) buf.f_type;
}


Try<string> typeName(uint32_t fsType)
{
  // `typeNames` maps a filesystem id to its filesystem type name.
  hashmap<uint32_t, string> typeNames = {
    {FS_TYPE_AUFS      , "aufs"},
    {FS_TYPE_BTRFS     , "btrfs"},
    {FS_TYPE_CRAMFS    , "cramfs"},
    {FS_TYPE_ECRYPTFS  , "ecryptfs"},
    {FS_TYPE_EXTFS     , "extfs"},
    {FS_TYPE_F2FS      , "f2fs"},
    {FS_TYPE_GPFS      , "gpfs"},
    {FS_TYPE_JFFS2FS   , "jffs2fs"},
    {FS_TYPE_JFS       , "jfs"},
    {FS_TYPE_NFSFS     , "nfsfs"},
    {FS_TYPE_RAMFS     , "ramfs"},
    {FS_TYPE_REISERFS  , "reiserfs"},
    {FS_TYPE_SMBFS     , "smbfs"},
    {FS_TYPE_SQUASHFS  , "squashfs"},
    {FS_TYPE_TMPFS     , "tmpfs"},
    {FS_TYPE_VXFS      , "vxfs"},
    {FS_TYPE_XFS       , "xfs"},
    {FS_TYPE_ZFS       , "zfs"},
    {FS_TYPE_OVERLAY   , "overlay"}
  };

  if (!typeNames.contains(fsType)) {
    return Error("Unexpected filesystem type '" + stringify(fsType) + "'");
  }

  return typeNames[fsType];
}


Try<MountInfoTable> MountInfoTable::read(
    const string& lines,
    bool hierarchicalSort)
{
  MountInfoTable table;

  foreach (const string& line, strings::tokenize(lines, "\n")) {
    Try<Entry> parse = MountInfoTable::Entry::parse(line);
    if (parse.isError()) {
      return Error("Failed to parse entry '" + line + "': " + parse.error());
    }

    table.entries.push_back(parse.get());
  }

  // If `hierarchicalSort == true`, then sort the entries in
  // the newly constructed table hierarchically. That is, sort
  // them according to the invariant that all parent entries
  // appear before their child entries.
  if (hierarchicalSort) {
    // Build an ID to entry and a parent to children IDs map for quick
    // lookup.
    hashmap<int, MountInfoTable::Entry> entries;
    hashmap<int, vector<int>> children;
    for (const MountInfoTable::Entry& ent : table.entries) {
      entries.emplace(ent.id, ent);

      // It is legal to have a mount info table entry whose ID is the
      // same as its parent ID. This can happen if, for example, the
      // system boots from network and then keeps the original / in RAM.
      // To avoid cycles when walking the mount hierarchy, we skip such
      // entries in the children map.
      if (ent.parent != ent.id) {
        children[ent.parent].push_back(ent.id);
      }
    }

    // Entries without a visible parent (e.g. in a chroot) or referring
    // to themselves are roots of visible mount trees. Sort them in BFS
    // order.
    vector<MountInfoTable::Entry> sorted;
    sorted.reserve(table.entries.size());
    for (const MountInfoTable::Entry& ent : table.entries) {
      if (ent.parent == ent.id || !entries.contains(ent.parent)) {
        sorted.push_back(ent);
      }
    }
    for (auto it = sorted.begin(); it != sorted.end(); ++it) {
      if (children.contains(it->id)) {
        for (const int id : children.at(it->id)) {
          sorted.push_back(entries.at(id));
        }
      }
    }

    CHECK_EQ(sorted.size(), table.entries.size())
      << "Possible cycle in mount info table: " << std::endl << lines;
    table.entries = std::move(sorted); 
  }

  return table;
}


Try<MountInfoTable> MountInfoTable::read(
    const Option<pid_t>& pid,
    bool hierarchicalSort)
{
  const string path = path::join(
      "/proc",
      (pid.isSome() ? stringify(pid.get()) : "self"),
      "mountinfo");

  Try<string> lines = os::read(path);
  if (lines.isError()) {
    return Error("Failed to read mountinfo file: " + lines.error());
  }

  return MountInfoTable::read(lines.get(), hierarchicalSort);
}


Try<MountInfoTable::Entry> MountInfoTable::findByTarget(
    const std::string& target)
{
  Result<string> realTarget = os::realpath(target);
  if (!realTarget.isSome()) {
    return Error(
        "Failed to get the realpath of '" + target + "'"
        ": " + (realTarget.isError() ? realTarget.error() : "Not found"));
  }

  // Trying to find the mount entry that contains the 'realTarget'. We
  // achieve that by doing a reverse traverse of the mount table to
  // find the first entry whose target is a prefix of the specified
  // 'realTarget'.
  foreach (const Entry& entry, adaptor::reverse(entries)) {
    if (entry.target == realTarget.get()) {
      return entry;
    }

    // NOTE: We have to use `path::join(entry.target, "")` here
    // to make sure the parent is a directory.
    if (strings::startsWith(realTarget.get(), path::join(entry.target, ""))) {
      return entry;
    }
  }

  // It's unlikely that we cannot find the immediate parent because
  // '/' is always mounted and will be the immediate parent if no
  // other mounts found in between.
  return Error("Not found");
}


Try<MountInfoTable::Entry> MountInfoTable::Entry::parse(const string& s)
{
  MountInfoTable::Entry entry;

  const string separator = " - ";
  size_t pos = s.find(separator);
  if (pos == string::npos) {
    return Error("Could not find separator ' - '");
  }

  // First group of fields (before the separator): 6 required fields
  // then zero or more optional fields
  vector<string> tokens = strings::tokenize(s.substr(0, pos), " ");
  if (tokens.size() < 6) {
    return Error("Failed to parse entry");
  }

  Try<int> id = numify<int>(tokens[0]);
  if (id.isError()) {
    return Error("Mount ID is not a number");
  }
  entry.id = id.get();

  Try<int> parent = numify<int>(tokens[1]);
  if (parent.isError()) {
    return Error("Parent ID is not a number");
  }
  entry.parent = parent.get();

  // Parse out the major:minor device number.
  vector<string> device = strings::split(tokens[2], ":");
  if (device.size() != 2) {
    return Error("Invalid major:minor device number");
  }

  Try<int> major = numify<int>(device[0]);
  if (major.isError()) {
    return Error("Device major is not a number");
  }

  Try<int> minor = numify<int>(device[1]);
  if (minor.isError()) {
    return Error("Device minor is not a number");
  }

  entry.devno = makedev(major.get(), minor.get());

  entry.root = tokens[3];
  entry.target = tokens[4];

  entry.vfsOptions = tokens[5];

  // The "proc" manpage states there can be zero or more optional
  // fields. The kernel source (fs/proc_namespace.c) has the optional
  // fields ("tagged fields") separated by " " when printing the table
  // (see show_mountinfo()).
  if (tokens.size() > 6) {
    tokens.erase(tokens.begin(), tokens.begin() + 6);
    entry.optionalFields = strings::join(" ", tokens);
  }

  // Second set of fields: 3 required fields.
  tokens = strings::tokenize(s.substr(pos + separator.size() - 1), " ");
  if (tokens.size() != 3) {
    return Error("Failed to parse type, source or options");
  }

  entry.type = tokens[0];
  entry.source = tokens[1];
  entry.fsOptions = tokens[2];

  return entry;
}


Option<int> MountInfoTable::Entry::shared() const
{
  foreach (const string& token, strings::tokenize(optionalFields, " ")) {
    if (strings::startsWith(token, "shared:")) {
      Try<int> id = numify<int>(
          strings::remove(token, "shared:", strings::PREFIX));

      CHECK_SOME(id);
      return id.get();
    }
  }

  return None();
}


Option<int> MountInfoTable::Entry::master() const
{
  foreach (const string& token, strings::tokenize(optionalFields, " ")) {
    if (strings::startsWith(token, "master:")) {
      Try<int> id = numify<int>(
          strings::remove(token, "master:", strings::PREFIX));

      CHECK_SOME(id);
      return id.get();
    }
  }

  return None();
}


bool MountTable::Entry::hasOption(const string& option) const
{
  struct mntent mntent;
  mntent.mnt_fsname = const_cast<char*>(fsname.c_str());
  mntent.mnt_dir = const_cast<char*>(dir.c_str());
  mntent.mnt_type = const_cast<char*>(type.c_str());
  mntent.mnt_opts = const_cast<char*>(opts.c_str());
  mntent.mnt_freq = freq;
  mntent.mnt_passno = passno;
  return ::hasmntopt(&mntent, option.c_str()) != nullptr;
}


Try<MountTable> MountTable::read(const string& path)
{
  MountTable table;

  FILE* file = ::setmntent(path.c_str(), "r");
  if (file == nullptr) {
    return ErrnoError("Failed to open '" + path + "'");
  }

  while (true) {
#if defined(_BSD_SOURCE) || defined(_SVID_SOURCE)
    // Reentrant version exists.
    struct mntent mntentBuffer;
    char strBuffer[PATH_MAX];
    struct mntent* mntent =
      ::getmntent_r(file, &mntentBuffer, strBuffer, sizeof(strBuffer));
    if (mntent == nullptr) {
      // nullptr means the end of enties.
      break;
    }

    MountTable::Entry entry(mntent->mnt_fsname,
                            mntent->mnt_dir,
                            mntent->mnt_type,
                            mntent->mnt_opts,
                            mntent->mnt_freq,
                            mntent->mnt_passno);
    table.entries.push_back(entry);
#else
    // Mutex for guarding calls into non-reentrant mount table
    // functions. We use a static local variable to avoid unused
    // variable warnings.
    static std::mutex mutex;

    synchronized (mutex) {
      struct mntent* mntent = ::getmntent(file);
      if (mntent == nullptr) {
        // nullptr means the end of enties.
        break;
      }

      MountTable::Entry entry(mntent->mnt_fsname,
                              mntent->mnt_dir,
                              mntent->mnt_type,
                              mntent->mnt_opts,
                              mntent->mnt_freq,
                              mntent->mnt_passno);
      table.entries.push_back(entry);
    }
#endif
  }

  ::endmntent(file);

  return table;
}


Try<Nothing> mount(const Option<string>& _source,
                   const string& target,
                   const Option<string>& _type,
                   unsigned long flags,
                   const void* data)
{
  const char * source = _source.isSome() ? _source->c_str() : nullptr;
  const char * type = _type.isSome() ? _type->c_str() : nullptr;

  // The prototype of function 'mount' on Linux is as follows:
  // int mount(const char *source,
  //           const char *target,
  //           const char *filesystemtype,
  //           unsigned long mountflags,
  //           const void *data);
  if (::mount(source, target.c_str(), type, flags, data) < 0) {
    return ErrnoError();
  }

  const unsigned READ_ONLY_FLAG = MS_BIND | MS_RDONLY;
  const unsigned READ_ONLY_MASK = MS_BIND | MS_RDONLY | MS_REC;

  // Bind mounts need to be remounted for the read-only flag to take
  // effect. If this was a read-only bind mount, automatically remount
  // so that every caller doesn't have to deal with this. We don't do
  // anything if this was already a remount.
  if ((flags & (READ_ONLY_FLAG | MS_REMOUNT)) == READ_ONLY_FLAG) {
    if (::mount(
            nullptr,
            target.c_str(),
            nullptr,
            MS_REMOUNT | (flags & READ_ONLY_MASK),
            nullptr) < 0) {
      return ErrnoError("Read-only remount failed");
    }
  }

  return Nothing();
}


Try<Nothing> mount(const Option<string>& source,
                   const string& target,
                   const Option<string>& type,
                   unsigned long flags,
                   const Option<string>& options)
{
  return mount(
      source,
      target,
      type,
      flags,
      options.isSome() ? options->c_str() : nullptr);
}


Try<Nothing> unmount(const string& target, int flags)
{
  // The prototype of function 'umount2' on Linux is as follows:
  // int umount2(const char *target, int flags);
  if (::umount2(target.c_str(), flags) < 0) {
    return ErrnoError("Failed to unmount '" + target + "'");
  }

  return Nothing();
}


Try<Nothing> unmountAll(const string& target, int flags)
{
  Try<fs::MountTable> mountTable = fs::MountTable::read("/proc/mounts");
  if (mountTable.isError()) {
    return Error("Failed to read mount table: " + mountTable.error());
  }

  foreach (const MountTable::Entry& entry,
           adaptor::reverse(mountTable->entries)) {
    if (strings::startsWith(entry.dir, target)) {
      Try<Nothing> unmount = fs::unmount(entry.dir, flags);
      if (unmount.isError()) {
        return unmount;
      }

      // This normally should not fail even if the entry is not in
      // mtab or mtab doesn't exist or is not writable. However we
      // still catch the error here in case there's an error somewhere
      // else while running this command.
      // TODO(xujyan): Consider using `setmntent(3)` to implement this.
      const Option<int> status =
        os::spawn("umount", {"umount", "--fake", entry.dir});

      const string message =
        "Failed to clean up '" + entry.dir + "' in /etc/mtab";

      if (status.isNone()) {
        return ErrnoError(message);
      }

      if (!WSUCCEEDED(status.get())) {
        return Error(message + ": " + WSTRINGIFY(status.get()));
      }
    }
  }

  return Nothing();
}


Try<Nothing> pivot_root(
    const string& newRoot,
    const string& putOld)
{
  // These checks are done in the syscall but we'll do them here to
  // provide less cryptic error messages. See 'man 2 pivot_root'.
  if (!os::stat::isdir(newRoot)) {
    return Error("newRoot '" + newRoot + "' is not a directory");
  }

  if (!os::stat::isdir(putOld)) {
    return Error("putOld '" + putOld + "' is not a directory");
  }

  // TODO(idownes): Verify that newRoot (and putOld) is on a different
  // filesystem to the current root. st_dev distinguishes the device
  // an inode is on, but bind mounts (which are acceptable to
  // pivot_root) share the same st_dev as the source of the mount so
  // st_dev is not generally sufficient.

  if (!strings::startsWith(putOld, newRoot)) {
    return Error("putOld '" + putOld +
                 "' must be beneath newRoot '" + newRoot);
  }

#ifdef __NR_pivot_root
  int ret = ::syscall(__NR_pivot_root, newRoot.c_str(), putOld.c_str());
#else
#error "pivot_root is not available"
#endif
  if (ret == -1) {
    return ErrnoError();
  }

  return Nothing();
}


namespace chroot {

Try<Nothing> copyDeviceNode(
    const std::string& source,
    const std::string& target)
{
  Try<mode_t> mode = os::stat::mode(source);
  if (mode.isError()) {
    return Error("Failed to get source mode: " + mode.error());
  }

  Try<dev_t> dev = os::stat::rdev(source);
  if (dev.isError()) {
    return Error("Failed to get source dev: " + dev.error());
  }

  Try<Nothing> mkdir = os::mkdir(Path(target).dirname());
  if (mkdir.isError()) {
    return Error(
        "Failed to create parent directory for device '" +
        target + "': " + mkdir.error());
  }

  Try<Nothing> mknod = os::mknod(target, mode.get(), dev.get());
  if (mknod.isError()) {
    return Error("Failed to mknod device '" + target + "': " + mknod.error());
  }

  Try<Nothing> chmod = os::chmod(target, mode.get());
  if (chmod.isError()) {
    return Error("Failed to chmod device '" + target + "': " + chmod.error());
  }

  return Nothing();
}


// TODO(idownes): Add unit test.
Try<Nothing> enter(const string& root)
{
  // Prepare /tmp in the new root. Note that we cannot assume that the
  // new root is writable (i.e., it could be a read only filesystem).
  // Therefore, we always mount a tmpfs on /tmp in the new root so
  // that we can create the mount point for the old root.
  //
  // NOTE: If the new root is a read-only filesystem (e.g., using bind
  // backend), the 'tmpfs' mount point '/tmp' must already exist in the
  // new root. Otherwise, mkdir would return an error because of unable
  // to create it in read-only filesystem.
  Try<Nothing> mkdir = os::mkdir(path::join(root, "tmp"));
  if (mkdir.isError()) {
    return Error("Failed to create 'tmpfs' mount point at '" +
                 path::join(root, "tmp") + "': " + mkdir.error());
  }

  // TODO(jieyu): Consider limiting the size of the tmpfs.
  Try<Nothing> mount = fs::mount(
      "tmpfs",
      path::join(root, "tmp"),
      "tmpfs",
      MS_NOSUID | MS_NOEXEC | MS_NODEV,
      "mode=1777");

  if (mount.isError()) {
    return Error("Failed to mount the temporary tmpfs at /tmp in new root: " +
                 mount.error());
  }

  // Create a mount point for the old root.
  Try<string> old = os::mkdtemp(path::join(root, "tmp", "._old_root_.XXXXXX"));
  if (old.isError()) {
    return Error("Failed to create mount point for old root: " + old.error());
  }

  // Chroot to the new root. This is done by a particular sequence of
  // operations, each of which is necessary: chdir, pivot_root,
  // chroot, chdir. After these operations, the process will be
  // chrooted to the new root.

  // Chdir to the new root.
  Try<Nothing> chdir = os::chdir(root);
  if (chdir.isError()) {
    return Error("Failed to chdir to new root: " + chdir.error());
  }

  // Pivot the root to the cwd.
  Try<Nothing> pivot = fs::pivot_root(root, old.get());
  if (pivot.isError()) {
    return Error("Failed to pivot to new root: " + pivot.error());
  }

  // Chroot to the new "/". This is necessary to correctly set the
  // base for all paths.
  Try<Nothing> chroot = os::chroot(".");
  if (chroot.isError()) {
    return Error("Failed to chroot to new root: " + chroot.error());
  }

  // Ensure all references are within the new root.
  chdir = os::chdir("/");
  if (chdir.isError()) {
    return Error("Failed to chdir to new root: " + chdir.error());
  }

  // Unmount filesystems on the old root. Note, any filesystems that
  // were mounted to the chroot directory will be correctly pivoted.
  Try<fs::MountTable> mountTable = fs::MountTable::read("/proc/mounts");
  if (mountTable.isError()) {
    return Error("Failed to read mount table: " + mountTable.error());
  }

  // The old root is now relative to chroot so remove the chroot path.
  const string relativeOld = strings::remove(old.get(), root, strings::PREFIX);

  foreach (const fs::MountTable::Entry& entry, mountTable->entries) {
    // TODO(idownes): sort the entries and remove depth first so we
    // don't rely on the lazy umount and can check the status.
    if (strings::startsWith(entry.dir, relativeOld)) {
      fs::unmount(entry.dir, MNT_DETACH);
    }
  }

  // TODO(idownes): If any of the lazy umounts above is still pending
  // this will fail, leaving behind an empty directory which we'll
  // ignore.
  // Check status when we stop using lazy umounts.
  os::rmdir(relativeOld);

  Try<Nothing> unmount = fs::unmount("/tmp");
  if (unmount.isError()) {
    return Error("Failed to umount /tmp in the chroot: " + unmount.error());
  }

  return Nothing();
}

} // namespace chroot {
} // namespace fs {
} // namespace internal {
} // namespace mesos {
