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

#include "arc/setup/arc_setup_util.h"

#include <fcntl.h>
#include <limits.h>
#include <linux/loop.h>
#include <linux/magic.h>
#include <linux/major.h>
#include <mntent.h>
#include <net/if.h>
#include <net/if_arp.h>
#include <openssl/sha.h>
#include <pwd.h>
#include <selinux/restorecon.h>
#include <selinux/selinux.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/statfs.h>
#include <sys/sysmacros.h>
#include <sys/types.h>
#include <sys/xattr.h>
#include <unistd.h>

#include <algorithm>
#include <fstream>
#include <list>
#include <set>
#include <utility>

#include <base/bind.h>
#include <base/callback_helpers.h>
#include <base/environment.h>
#include <base/files/file_enumerator.h>
#include <base/files/file_util.h>
#include <base/files/scoped_file.h>
#include <base/json/json_reader.h>
#include <base/logging.h>
#include <base/process/launch.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_util.h>
#include <base/strings/stringprintf.h>
#include <base/time/time.h>
#include <base/timer/elapsed_timer.h>
#include <base/values.h>
#include <brillo/file_utils.h>
#include <brillo/files/safe_fd.h>
#include <crypto/sha2.h>

using base::StringPiece;

namespace arc {

namespace {

// Version element prefix in packages.xml and packages_cache.xml files.
// Note: This constant has to be in sync with Android's arc-boot-type-detector.
constexpr char kElementVersion[] = "<version ";

// Fingerprint attribute prefix in packages.xml and packages_cache.xml files.
// Note: This constant has to be in sync with Android's arc-boot-type-detector.
constexpr char kAttributeFingerprint[] = " fingerprint=\"";

// Gets the loop device path for a loop device number.
base::FilePath GetLoopDevicePath(int32_t device) {
  return base::FilePath(base::StringPrintf("/dev/loop%d", device));
}

// Immediately removes the loop device from the system.
void RemoveLoopDevice(int control_fd, int32_t device) {
  if (ioctl(control_fd, LOOP_CTL_REMOVE, device) < 0)
    PLOG(ERROR) << "Failed to free /dev/loop" << device;
}

// Disassociates the loop device from any file descriptor.
void DisassociateLoopDevice(int loop_fd,
                            const std::string& source,
                            const base::FilePath& device_path) {
  if (ioctl(loop_fd, LOOP_CLR_FD) < 0) {
    PLOG(ERROR) << "Failed to remove " << source << " from "
                << device_path.value();
  }
}

// A callback function for SELinux restorecon.
PRINTF_FORMAT(2, 3)
int RestoreConLogCallback(int type, const char* fmt, ...) {
  va_list ap;

  std::string message = "restorecon: ";
  va_start(ap, fmt);
  message += base::StringPrintV(fmt, ap);
  va_end(ap);

  // This already has a line feed at the end, so trim it off to avoid
  // empty lines in the log.
  base::TrimString(message, "\r\n", &message);

  if (type == SELINUX_INFO)
    LOG(INFO) << message;
  else
    LOG(ERROR) << message;

  return 0;
}

bool RestoreconInternal(const std::vector<base::FilePath>& paths,
                        bool is_recursive) {
  union selinux_callback cb;
  cb.func_log = RestoreConLogCallback;
  selinux_set_callback(SELINUX_CB_LOG, cb);

  const unsigned int base_flags =
      (is_recursive ? SELINUX_RESTORECON_RECURSE : 0) |
      SELINUX_RESTORECON_REALPATH;

  bool success = true;
  for (const auto& path : paths) {
    unsigned int restorecon_flags = base_flags;
    struct statfs fsinfo;
    if (statfs(path.value().c_str(), &fsinfo) != 0) {
      PLOG(WARNING) << "Failed to statfs for " << path.value();
      // Continue anyway because restorecon should work even if it can't
      // update digests.
    } else if (fsinfo.f_type == TRACEFS_MAGIC ||
               fsinfo.f_type == DEBUGFS_MAGIC) {
      // tracefs and debugfs don't support xattrs, so restorecon can't store
      // digests.
      restorecon_flags |= SELINUX_RESTORECON_SKIP_DIGEST;
    }

    if (selinux_restorecon(path.value().c_str(), restorecon_flags) != 0) {
      LOG(ERROR) << "Error in restorecon of " << path.value();
      success = false;
    }
  }
  return success;
}

// A callback function for GetPropertyFromFile.
bool FindProperty(const std::string& line_prefix_to_find,
                  std::string* out_prop,
                  const std::string& line) {
  if (base::StartsWith(line, line_prefix_to_find,
                       base::CompareCase::SENSITIVE)) {
    *out_prop = line.substr(line_prefix_to_find.length());
    return true;
  }
  return false;
}

// Helper function for extracting an attribute value from an XML line.
// Expects |key| to be suffixed with '=\"' (e.g. ' sdkVersion=\"').
// Note: This function has to be in sync with Android's arc-boot-type-detector.
StringPiece GetAttributeValue(const StringPiece& line, const StringPiece& key) {
  StringPiece::size_type key_begin_pos = line.find(key);
  if (key_begin_pos == StringPiece::npos)
    return StringPiece();
  StringPiece::size_type value_begin_pos = key_begin_pos + key.length();
  StringPiece::size_type value_end_pos = line.find('"', value_begin_pos);
  if (value_end_pos == StringPiece::npos)
    return StringPiece();
  return line.substr(value_begin_pos, value_end_pos - value_begin_pos);
}

// Sets the permission of the given |fd|.
bool SetPermissions(base::PlatformFile fd, mode_t mode) {
  struct stat st;
  if (fstat(fd, &st) < 0) {
    PLOG(ERROR) << "Failed to stat";
    return false;
  }
  if ((st.st_mode & 07000) && ((st.st_mode & 07000) != (mode & 07000))) {
    LOG(INFO) << "Changing permissions from " << (st.st_mode & ~S_IFMT)
              << " to " << (mode & ~S_IFMT);
  }

  if (fchmod(fd, mode) != 0) {
    PLOG(ERROR) << "Failed to fchmod " << mode;
    return false;
  }
  return true;
}

class ArcMounterImpl : public ArcMounter {
 public:
  ArcMounterImpl() = default;
  ~ArcMounterImpl() override = default;

  bool Mount(const std::string& source,
             const base::FilePath& target,
             const char* filesystem_type,
             unsigned long mount_flags,  // NOLINT(runtime/int)
             const char* data) override {
    std::string source_resolved;
    if (!source.empty() && source[0] == '/')
      source_resolved = Realpath(base::FilePath(source)).value();
    else
      source_resolved = source;  // not a path (e.g. "tmpfs")

    if (mount(source_resolved.c_str(), Realpath(target).value().c_str(),
              filesystem_type, mount_flags, data) != 0) {
      PLOG(ERROR) << "Failed to mount " << source << " to " << target.value();
      return false;
    }
    return true;
  }

  bool Remount(const base::FilePath& target_directory,
               unsigned long mount_flags,  // NOLINT(runtime/int)
               const char* data) override {
    return Mount(std::string(),  // ignored
                 target_directory,
                 nullptr,  // ignored
                 mount_flags | MS_REMOUNT, data);
  }

  bool LoopMount(const std::string& source,
                 const base::FilePath& target,
                 unsigned long mount_flags) override {  // NOLINT(runtime/int)
    constexpr size_t kRetryMax = 10;
    for (size_t i = 0; i < kRetryMax; ++i) {
      bool retry = false;
      if (LoopMountInternal(source, target, mount_flags, &retry))
        return true;
      if (!retry)
        break;
      LOG(INFO) << "LoopMountInternal failed with EBUSY. Retrying...";
    }
    return false;
  }

  bool BindMount(const base::FilePath& old_path,
                 const base::FilePath& new_path) override {
    return Mount(old_path.value(), new_path, nullptr, MS_BIND, nullptr);
  }

  bool SharedMount(const base::FilePath& path) override {
    return Mount("none", path, nullptr, MS_SHARED, nullptr);
  }

  bool Umount(const base::FilePath& path) override {
    if (umount(Realpath(path).value().c_str()) != 0) {
      PLOG(ERROR) << "Failed to umount " << path.value();
      return false;
    }
    return true;
  }

  bool UmountIfExists(const base::FilePath& path) override {
    if (umount(Realpath(path).value().c_str()) != 0) {
      // We tolerate nothing mounted on the path (EINVAL) and we tolerate the
      // path not existing (ENOENT)
      if (errno != EINVAL && errno != ENOENT) {
        PLOG(ERROR) << "Mount exists but failed to umount " << path.value();
        return false;
      }
    }
    return true;
  }

  bool LoopUmount(const base::FilePath& path) override {
    if (!LoopUmountInternal(path, /*ignore_missing=*/false)) {
      LOG(ERROR) << "Failed to unmount loop " << path.value();
      return false;
    }
    return true;
  }

  bool LoopUmountIfExists(const base::FilePath& path) override {
    if (!LoopUmountInternal(path, /*ignore_missing=*/true)) {
      LOG(ERROR) << "Mount exists but failed to unmount loop " << path.value();
      return false;
    }
    return true;
  }

 private:
  bool LoopUmountInternal(const base::FilePath& path,
                          const bool ignore_missing) {
    struct stat st;
    if (stat(path.value().c_str(), &st) < 0) {
      if (!ignore_missing || errno != ENOENT) {
        PLOG(ERROR) << "Failed to stat " << path.value();
        return false;
      }
      return true;
    }

    if (major(st.st_dev) != LOOP_MAJOR) {
      if (!ignore_missing) {
        LOG(ERROR) << path.value()
                   << " is not loop-mounted. st_dev=" << st.st_dev;
        return false;
      }
      return true;
    }

    bool autoclear = false;
    const base::FilePath device_path = GetLoopDevicePath(minor(st.st_dev));
    {
      base::ScopedFD scoped_loop_fd(
          open(device_path.value().c_str(), O_RDONLY | O_CLOEXEC));
      if (!scoped_loop_fd.is_valid()) {
        PLOG(ERROR) << "Failed to open " << device_path.value();
        return false;
      }

      struct loop_info64 loop_info;
      if (ioctl(scoped_loop_fd.get(), LOOP_GET_STATUS64, &loop_info) < 0) {
        PLOG(ERROR) << "Failed to get info " << device_path.value();
        return false;
      }
      autoclear = loop_info.lo_flags & LO_FLAGS_AUTOCLEAR;
    }

    if (!Umount(path))
      return false;

    if (!autoclear) {
      base::ScopedFD scoped_loop_fd(
          open(device_path.value().c_str(), O_RDWR | O_CLOEXEC));
      if (!scoped_loop_fd.is_valid()) {
        PLOG(ERROR) << "Failed to open " << device_path.value();
        return false;
      }

      if (ioctl(scoped_loop_fd.get(), LOOP_CLR_FD) < 0) {
        PLOG(ERROR) << "Failed to free " << device_path.value();
        return false;
      }
    }

    return true;
  }

  bool LoopMountInternal(const std::string& source,
                         const base::FilePath& target,
                         unsigned long mount_flags,  // NOLINT(runtime/int)
                         bool* out_retry) {
    constexpr char kLoopControl[] = "/dev/loop-control";

    *out_retry = false;
    base::ScopedFD scoped_control_fd(open(kLoopControl, O_RDONLY));
    if (!scoped_control_fd.is_valid()) {
      PLOG(ERROR) << "Failed to open " << kLoopControl;
      return false;
    }

    const int32_t device_num =
        ioctl(scoped_control_fd.get(), LOOP_CTL_GET_FREE);
    if (device_num < 0) {
      PLOG(ERROR) << "Failed to allocate a loop device";
      return false;
    }

    // Cleanup in case mount fails. This frees |device_num| altogether.
    base::ScopedClosureRunner loop_device_cleanup(
        base::Bind(&RemoveLoopDevice, scoped_control_fd.get(), device_num));

    const base::FilePath device_path = GetLoopDevicePath(device_num);
    base::ScopedFD scoped_loop_fd(open(device_path.value().c_str(), O_RDWR));
    if (!scoped_loop_fd.is_valid()) {
      PLOG(ERROR) << "Failed to open " << device_path.value();
      return false;
    }

    const bool is_readonly_mount = mount_flags & MS_RDONLY;
    base::ScopedFD scoped_source_fd(
        open(source.c_str(), is_readonly_mount ? O_RDONLY : O_RDWR));
    if (!scoped_source_fd.is_valid()) {
      // If the open failed because we tried to open a read only file as RW
      // we fallback to opening it with O_RDONLY
      if (!is_readonly_mount && (errno == EROFS || errno == EACCES)) {
        LOG(WARNING) << source << " is write-protected, using read-only";
        scoped_source_fd.reset(open(source.c_str(), O_RDONLY));
      }
      if (!scoped_source_fd.is_valid()) {
        PLOG(ERROR) << "Failed to open " << source;
        return false;
      }
    }

    if (ioctl(scoped_loop_fd.get(), LOOP_SET_FD, scoped_source_fd.get()) < 0) {
      PLOG(ERROR) << "Failed to associate " << source << " with "
                  << device_path.value();
      // Set |out_retry| to true if LOOP_SET_FD returns EBUSY. The errno
      // indicates that another process has grabbed the same |device_num|
      // before arc-setup does that.
      *out_retry = (errno == EBUSY);
      return false;
    }

    // Set the autoclear flag on the loop device, which will release it when
    // there are no more references to it.
    struct loop_info64 loop_info = {};
    if (ioctl(scoped_loop_fd.get(), LOOP_GET_STATUS64, &loop_info) < 0) {
      PLOG(ERROR) << "Failed to get loop status for " << device_path.value();
      return false;
    }
    loop_info.lo_flags |= LO_FLAGS_AUTOCLEAR;
    if (ioctl(scoped_loop_fd.get(), LOOP_SET_STATUS64, &loop_info) < 0) {
      PLOG(ERROR) << "Failed to set autoclear loop status for "
                  << device_path.value();
      return false;
    }
    // Substitute the removal of the device number by disassociating |source|
    // from the loop device, such that the autoclear flag on |device_num| can
    // automatically remove the loop device.
    loop_device_cleanup.ReplaceClosure(base::Bind(
        &DisassociateLoopDevice, scoped_loop_fd.get(), source, device_path));

    if (Mount(device_path.value(), target, "squashfs", mount_flags, nullptr)) {
      ignore_result(loop_device_cleanup.Release());
      return true;
    }

    // For debugging, ext4 might be used.
    if (Mount(device_path.value(), target, "ext4", mount_flags, nullptr)) {
      LOG(INFO) << "Mounted " << source << " as ext4";
      ignore_result(loop_device_cleanup.Release());
      return true;
    }

    return false;
  }
};

}  // namespace

ScopedMount::ScopedMount(const base::FilePath& path,
                         ArcMounter* mounter,
                         bool is_loop)
    : mounter_(mounter), path_(path), is_loop_(is_loop) {}

ScopedMount::~ScopedMount() {
  if (is_loop_) {
    PLOG_IF(INFO, !mounter_->LoopUmount(path_))
        << "Ignoring failure to umount " << path_.value();
  } else {
    PLOG_IF(INFO, !mounter_->Umount(path_))
        << "Ignoring failure to umount " << path_.value();
  }
}

// static
std::unique_ptr<ScopedMount> ScopedMount::CreateScopedMount(
    ArcMounter* mounter,
    const std::string& source,
    const base::FilePath& target,
    const char* filesystem_type,
    unsigned long mount_flags,  // NOLINT(runtime/int)
    const char* data) {
  if (!mounter->Mount(source, target, filesystem_type, mount_flags, data))
    return nullptr;
  return std::make_unique<ScopedMount>(target, mounter, false /*is_loop*/);
}

// static
std::unique_ptr<ScopedMount> ScopedMount::CreateScopedLoopMount(
    ArcMounter* mounter,
    const std::string& source,
    const base::FilePath& target,
    unsigned long flags) {  // NOLINT(runtime/int)
  if (!mounter->LoopMount(source, target, flags))
    return nullptr;
  return std::make_unique<ScopedMount>(target, mounter, true /*is_loop*/);
}

// static
std::unique_ptr<ScopedMount> ScopedMount::CreateScopedBindMount(
    ArcMounter* mounter,
    const base::FilePath& old_path,
    const base::FilePath& new_path) {
  if (!mounter->BindMount(old_path, new_path))
    return nullptr;
  return std::make_unique<ScopedMount>(new_path, mounter, false /*is_loop*/);
}

base::FilePath Realpath(const base::FilePath& path) {
  // We cannot use base::NormalizeFilePath because the function fails
  // if |path| points to a directory (for Windows compatibility.)
  char buf[PATH_MAX] = {};
  if (!realpath(path.value().c_str(), buf)) {
    if (errno != ENOENT)
      PLOG(WARNING) << "Failed to resolve " << path.value();
    return path;
  }
  return base::FilePath(buf);
}

bool Chown(uid_t uid, gid_t gid, const base::FilePath& path) {
  base::ScopedFD fd(brillo::OpenSafely(path, O_RDONLY, 0));
  if (!fd.is_valid())
    return false;
  return fchown(fd.get(), uid, gid) == 0;
}

bool Chcon(const std::string& context, const base::FilePath& path) {
  if (lsetfilecon(path.value().c_str(), context.c_str()) < 0) {
    PLOG(ERROR) << "Could not label " << path.value() << " with " << context;
    return false;
  }

  return true;
}

bool InstallDirectory(mode_t mode,
                      uid_t uid,
                      gid_t gid,
                      const base::FilePath& path) {
  if (!brillo::MkdirRecursively(path, 0755).is_valid())
    return false;

  base::ScopedFD fd(brillo::OpenSafely(path, O_DIRECTORY | O_RDONLY, 0));
  if (!fd.is_valid())
    return false;

  // Unlike 'mkdir -m mode -p' which does not change modes when the path already
  // exists, 'install -d' always sets modes and owner regardless of whether the
  // path exists or not.
  const bool chown_result = (fchown(fd.get(), uid, gid) == 0);
  const bool chmod_result = SetPermissions(fd.get(), mode);
  return chown_result && chmod_result;
}

bool WriteToFile(const base::FilePath& file_path,
                 mode_t mode,
                 const std::string& content) {
  // Use the same mode as base/files/file_posix.cc's.
  constexpr mode_t kMode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;

  base::ScopedFD fd(
      brillo::OpenSafely(file_path, O_WRONLY | O_CREAT | O_TRUNC, kMode));
  if (!fd.is_valid())
    return false;
  if (!SetPermissions(fd.get(), mode))
    return false;
  if (content.empty())
    return true;

  // Note: WriteFileDescriptor() makes a best effort to write all data.
  // While-loop for handling partial-write is not needed here.
  return base::WriteFileDescriptor(fd.get(), content.c_str(), content.size());
}

bool GetPropertyFromFile(const base::FilePath& prop_file_path,
                         const std::string& prop_name,
                         std::string* out_prop) {
  const std::string line_prefix_to_find = prop_name + '=';
  if (FindLine(prop_file_path,
               base::Bind(&FindProperty, line_prefix_to_find, out_prop))) {
    return true;  // found the line.
  }
  LOG(WARNING) << prop_name << " is not in " << prop_file_path.value();
  return false;
}

bool GetPropertiesFromFile(const base::FilePath& prop_file_path,
                           std::map<std::string, std::string>* out_properties) {
  if (FindLine(prop_file_path,
               base::Bind(&FindAllProperties, out_properties))) {
    // Failed to parse the file.
    out_properties->clear();
    return false;
  }

  return true;
}

// Note: This function has to be in sync with Android's arc-boot-type-detector.
bool GetFingerprintAndSdkVersionFromPackagesXml(
    const base::FilePath& packages_xml_path,
    std::string* out_fingerprint,
    std::string* out_sdk_version) {
  if (FindLine(packages_xml_path,
               base::Bind(&FindFingerprintAndSdkVersion, out_fingerprint,
                          out_sdk_version))) {
    return true;  // found it.
  }
  LOG(WARNING) << "No fingerprint found in " << packages_xml_path.value();
  return false;
}

bool CreateOrTruncate(const base::FilePath& file_path, mode_t mode) {
  return WriteToFile(file_path, mode, std::string());
}

bool WaitForPaths(std::initializer_list<base::FilePath> paths,
                  const base::TimeDelta& timeout,
                  base::TimeDelta* out_elapsed) {
  const base::TimeDelta sleep_interval = timeout / 20;
  std::list<base::FilePath> left(paths);

  base::ElapsedTimer timer;
  do {
    left.erase(std::remove_if(left.begin(), left.end(), base::PathExists),
               left.end());
    if (left.empty())
      break;  // all paths are found.
    base::PlatformThread::Sleep(sleep_interval);
  } while (timeout >= timer.Elapsed());

  if (out_elapsed)
    *out_elapsed = timer.Elapsed();

  for (const auto& path : left)
    LOG(ERROR) << path.value() << " not found";
  return left.empty();
}

bool LaunchAndWait(const std::vector<std::string>& argv) {
  base::Process process(base::LaunchProcess(argv, base::LaunchOptions()));
  if (!process.IsValid())
    return false;
  int exit_code = -1;
  return process.WaitForExit(&exit_code) && (exit_code == 0);
}

bool RestoreconRecursively(const std::vector<base::FilePath>& directories) {
  return RestoreconInternal(directories, true /* is_recursive */);
}

bool Restorecon(const std::vector<base::FilePath>& paths) {
  return RestoreconInternal(paths, false /* is_recursive */);
}

std::string GenerateFakeSerialNumber(const std::string& chromeos_user,
                                     const std::string& salt) {
  constexpr size_t kMaxHardwareIdLen = 20;
  const std::string hash(crypto::SHA256HashString(chromeos_user + salt));
  return base::HexEncode(hash.data(), hash.length())
      .substr(0, kMaxHardwareIdLen);
}

uint64_t GetArtCompilationOffsetSeed(const std::string& image_build_id,
                                     const std::string& salt) {
  uint64_t result = 0;
  std::string input;
  do {
    input += image_build_id + salt;
    crypto::SHA256HashString(input, &result, sizeof(result));
  } while (!result);
  return result;
}

// Note: This function has to be in sync with Android's arc-boot-type-detector.
bool MoveDirIntoDataOldDir(const base::FilePath& dir,
                           const base::FilePath& android_data_old_dir) {
  if (!base::DirectoryExists(dir)) {
    // Nothing to do.
    return true;
  }

  brillo::SafeFD root = brillo::SafeFD::Root().first;

  brillo::SafeFD source_parent = root.OpenExistingDir(dir.DirName()).first;
  if (!source_parent.is_valid()) {
    LOG(ERROR) << "Cannot open " << dir.DirName().value();
    return false;
  }

  brillo::SafeFD dest_dir_parent =
      root.OpenExistingDir(android_data_old_dir.DirName()).first;
  if (!dest_dir_parent.is_valid()) {
    LOG(ERROR) << "Cannot open " << android_data_old_dir.DirName().value();
    return false;
  }

  brillo::SafeFD dest_dir;
  brillo::SafeFD::Error err;
  std::tie(dest_dir, err) = dest_dir_parent.MakeDir(
      android_data_old_dir.BaseName(), 0700 /*permissions*/);
  if (err == brillo::SafeFD::Error::kWrongType) {
    LOG(INFO) << "Deleting something that is not a directory at "
              << android_data_old_dir.value();
    if (dest_dir_parent.Unlink(android_data_old_dir.BaseName().value()) !=
        brillo::SafeFD::Error::kNoError) {
      LOG(ERROR) << "Failed to delete " << android_data_old_dir.value();
      return false;
    }
    std::tie(dest_dir, err) = dest_dir_parent.MakeDir(
        android_data_old_dir.BaseName(), 0700 /*permissions*/);
  }
  if (!dest_dir.is_valid()) {
    LOG(ERROR) << "Cannot open or create " << android_data_old_dir.value();
    return false;
  }

  // Create a unique directory under android_data_old_dir.
  // TODO(crbug.com/1076654): Add temporary directory create and rename
  // APIs to SafeFD and replace the inline implementation here.
  int seed =
      std::chrono::high_resolution_clock::now().time_since_epoch().count() &
      0xFFFFFF;
  const std::string dest_base = dir.BaseName().value();
  bool moved = false;
  // How many different unique names shall we try? FreeBSD insists on
  // exhaustively trying all 56**5 (2.4e10) combinations to find that last
  // possible free filename. In contrast, glibc "only" tries 300000 times.
  // Conservativelty, we do not expect more than something on the order of
  // 100 names to be taken, but failing to opt-out is pretty bad for the
  // user so we use a safety factor of 1000 to be very sure. At 100000
  // syscalls, will still only block for a second before erroring out.
  constexpr int kMaxTries = 100000;
  for (int i = 0; i < kMaxTries; i++) {
    std::string new_name =
        base::StringPrintf("%s_%06x", dest_base.c_str(), seed);
    if (renameat(source_parent.get(), dir.BaseName().value().c_str(),
                 dest_dir.get(), new_name.c_str()) == 0) {
      moved = true;
      break;
    }
    if (errno != EEXIST && errno != ENOTEMPTY && errno != ENOTDIR) {
      PLOG(ERROR) << "Cannot move" << dir.value() << " to "
                  << android_data_old_dir.Append(new_name).value();
      return false;
    }
    seed = (seed + 1) & 0xFFFFFF;
  }
  if (!moved) {
    LOG(ERROR) << "Giving up, cannot move " << dir.value()
               << " to a directory of the form "
               << android_data_old_dir.Append(dest_base + "_XXXXXX").value();
    return false;
  }

  return true;
}

bool DeleteFilesInDir(const base::FilePath& directory) {
  base::FileEnumerator files(
      directory, true /* recursive */,
      base::FileEnumerator::FILES | base::FileEnumerator::SHOW_SYM_LINKS);
  bool retval = true;
  for (base::FilePath file = files.Next(); !file.empty(); file = files.Next()) {
    if (!DeleteFile(file, false /*recursive*/)) {
      LOG(ERROR) << "Failed to delete file " << file.value();
      retval = false;
    }
  }
  return retval;
}

std::unique_ptr<ArcMounter> GetDefaultMounter() {
  return std::make_unique<ArcMounterImpl>();
}

// Note: This function has to be in sync with Android's arc-boot-type-detector.
bool FindLine(const base::FilePath& file_path,
              const base::Callback<bool(const std::string&)>& callback) {
  // Do exactly the same stream handling as TextContentsEqual() in
  // base/files/file_util.cc which is known to work.
  std::ifstream file(file_path.value().c_str(), std::ios::in);
  if (!file.is_open()) {
    PLOG(WARNING) << "Cannot open " << file_path.value();
    return false;
  }

  do {
    std::string line;
    std::getline(file, line);

    // Check for any error state.
    if (file.bad()) {
      PLOG(WARNING) << "Failed to read " << file_path.value();
      return false;
    }

    // Trim all '\r' and '\n' characters from the end of the line.
    std::string::size_type end = line.find_last_not_of("\r\n");
    if (end == std::string::npos)
      line.clear();
    else if (end + 1 < line.length())
      line.erase(end + 1);

    // Stop reading the file if |callback| returns true.
    if (callback.Run(line))
      return true;
  } while (!file.eof());

  // |callback| didn't find anything in the file.
  return false;
}

std::string GetChromeOsChannelFromFile(
    const base::FilePath& lsb_release_file_path) {
  constexpr char kChromeOsReleaseTrackProp[] = "CHROMEOS_RELEASE_TRACK";
  const std::set<std::string> kChannels = {
      "beta-channel",    "canary-channel", "dev-channel",
      "dogfood-channel", "stable-channel", "testimage-channel"};
  const std::string kUnknown = "unknown";
  const std::string kChannelSuffix = "-channel";

  // Read the channel property from /etc/lsb-release
  std::string chromeos_channel;
  if (!GetPropertyFromFile(lsb_release_file_path, kChromeOsReleaseTrackProp,
                           &chromeos_channel)) {
    LOG(ERROR) << "Failed to get the ChromeOS channel from "
               << lsb_release_file_path.value();
    return kUnknown;
  }

  if (kChannels.find(chromeos_channel) == kChannels.end()) {
    LOG(WARNING) << "Unknown ChromeOS channel: \"" << chromeos_channel << "\"";
    return kUnknown;
  }
  return chromeos_channel.erase(chromeos_channel.find(kChannelSuffix),
                                kChannelSuffix.size());
}

bool GetOciContainerState(const base::FilePath& path,
                          pid_t* out_container_pid,
                          base::FilePath* out_rootfs) {
  // Read the OCI container state from |path|. Its format is documented in
  // https://github.com/opencontainers/runtime-spec/blob/master/runtime.md#state
  std::string json_str;
  if (!base::ReadFileToString(path, &json_str)) {
    PLOG(ERROR) << "Failed to read json string from " << path.value();
    return false;
  }
  auto container_state = base::JSONReader::ReadAndReturnValueWithError(
      json_str, base::JSON_PARSE_RFC);
  if (!container_state.value) {
    LOG(ERROR) << "Failed to parse json: " << container_state.error_message;
    return false;
  }
  if (!container_state.value->is_dict()) {
    LOG(ERROR) << "Failed to read container state as dictionary";
    return false;
  }

  // Get the container PID and the rootfs path.
  base::Optional<int> pid = container_state.value->FindIntKey("pid");
  if (!pid) {
    LOG(ERROR) << "Failed to get PID from container state";
    return false;
  }
  *out_container_pid = pid.value();

  const base::Value* annotations =
      container_state.value->FindDictKey("annotations");
  if (!annotations) {
    LOG(ERROR) << "Failed to get annotations from container state";
    return false;
  }
  const std::string* container_root_path =
      annotations->FindStringKey("org.chromium.run_oci.container_root");
  if (!container_root_path) {
    LOG(ERROR)
        << "Failed to get org.chromium.run_oci.container_root annotation";
    return false;
  }
  base::FilePath container_root(*container_root_path);
  if (!base::ReadSymbolicLink(
          container_root.Append("mountpoints/container-root"), out_rootfs)) {
    PLOG(ERROR) << "Failed to read container root symlink";
    return false;
  }

  return true;
}

bool IsProcessAlive(pid_t pid) {
  return kill(pid, 0 /* sig */) == 0;
}

bool GetSha1HashOfFiles(const std::vector<base::FilePath>& files,
                        std::string* out_hash) {
  SHA_CTX sha_context;
  SHA1_Init(&sha_context);
  for (const auto& file : files) {
    std::string file_str;
    if (!base::ReadFileToString(file, &file_str))
      return false;
    SHA1_Update(&sha_context, file_str.data(), file_str.size());
  }
  unsigned char hash[SHA_DIGEST_LENGTH];
  SHA1_Final(hash, &sha_context);
  out_hash->assign(reinterpret_cast<const char*>(hash), sizeof(hash));
  return true;
}

bool SetXattr(const base::FilePath& path,
              const char* name,
              const std::string& value) {
  base::ScopedFD fd(brillo::OpenSafely(path, O_RDONLY, 0));
  if (!fd.is_valid())
    return false;

  if (fsetxattr(fd.get(), name, value.data(), value.size(), 0 /* flags */) !=
      0) {
    PLOG(ERROR) << "Failed to change xattr " << name << " of " << path.value();
    return false;
  }
  return true;
}

bool ShouldDeleteAndroidData(AndroidSdkVersion system_sdk_version,
                             AndroidSdkVersion data_sdk_version) {
  // Downgraded. (b/80113276)
  if (data_sdk_version > system_sdk_version) {
    LOG(INFO) << "Clearing /data dir because ARC was downgraded from "
              << static_cast<int>(data_sdk_version) << " to "
              << static_cast<int>(system_sdk_version) << ".";
    return true;
  }
  // Upgraded from pre-M to post-P. (b/77591360)
  if (data_sdk_version > AndroidSdkVersion::UNKNOWN &&
      data_sdk_version <= AndroidSdkVersion::ANDROID_M &&
      system_sdk_version >= AndroidSdkVersion::ANDROID_P) {
    LOG(INFO) << "Clearing /data dir because ARC was upgraded from pre-M("
              << static_cast<int>(data_sdk_version) << ") to post-P("
              << static_cast<int>(system_sdk_version) << ").";
    return true;
  }
  return false;
}

bool FindAllProperties(std::map<std::string, std::string>* out_properties,
                       const std::string& line) {
  // Ignore empty lines and comments.
  if (line.empty() || line.at(0) == '#') {
    // Continue reading next lines.
    return false;
  }

  std::string::size_type separator = line.find('=');
  if (separator == std::string::npos) {
    LOG(WARNING) << "Failed to parse: " << line;
    // Stop reading next lines on error.
    return true;
  }

  (*out_properties)[line.substr(0, separator)] = line.substr(separator + 1);
  // Continue reading next lines.
  return false;
}

// Note: This function has to be in sync with Android's arc-boot-type-detector.
bool FindFingerprintAndSdkVersion(std::string* out_fingerprint,
                                  std::string* out_sdk_version,
                                  const std::string& line) {
  constexpr char kAttributeVolumeUuid[] = " volumeUuid=\"";
  constexpr char kAttributeSdkVersion[] = " sdkVersion=\"";
  constexpr char kAttributeDatabaseVersion[] = " databaseVersion=\"";

  // Parsing an XML this way is not very clean but in this case, it works (and
  // fast.) Android's packages.xml is written in com.android.server.pm.Settings'
  // writeLPr(), and the write function always uses Android's FastXmlSerializer.
  // The serializer does not try to pretty-print the XML, and inserts '\n' only
  // to certain places like endTag.
  StringPiece trimmed = base::TrimWhitespaceASCII(line, base::TRIM_ALL);
  if (!base::StartsWith(trimmed, kElementVersion, base::CompareCase::SENSITIVE))
    return false;  // Not a <version> element. Ignoring.

  if (trimmed.find(kAttributeVolumeUuid) != std::string::npos)
    return false;  // This is for an external storage. Ignoring.

  StringPiece fingerprint = GetAttributeValue(trimmed, kAttributeFingerprint);
  if (fingerprint.empty()) {
    LOG(WARNING) << "<version> doesn't have a valid fingerprint: " << trimmed;
    return false;
  }
  StringPiece sdk_version = GetAttributeValue(trimmed, kAttributeSdkVersion);
  if (sdk_version.empty()) {
    LOG(WARNING) << "<version> doesn't have a valid sdkVersion: " << trimmed;
    return false;
  }
  // Also checks existence of databaseVersion.
  if (GetAttributeValue(trimmed, kAttributeDatabaseVersion).empty()) {
    LOG(WARNING) << "<version> doesn't have a databaseVersion: " << trimmed;
    return false;
  }

  out_fingerprint->assign(fingerprint.data(), fingerprint.size());
  out_sdk_version->assign(sdk_version.data(), sdk_version.size());
  return true;
}

bool GetUserId(const std::string& user, uid_t* user_id, gid_t* group_id) {
  constexpr int kDefaultPwnameLength = 1024;
  // Load the passwd entry
  long user_name_length = sysconf(_SC_GETPW_R_SIZE_MAX);  // NOLINT long
  if (user_name_length == -1)
    user_name_length = kDefaultPwnameLength;
  passwd user_info;
  passwd* user_infop = nullptr;
  std::vector<char> user_name_buf(user_name_length);
  if (getpwnam_r(user.c_str(), &user_info, user_name_buf.data(),
                 user_name_length, &user_infop)) {
    return false;
  }
  if (!user_infop)
    return false;  // no such user
  *user_id = user_info.pw_uid;
  *group_id = user_info.pw_gid;
  return true;
}

}  // namespace arc
