// Copyright 2020 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 "cros-disks/archive_mounter.h"

#include <utility>

#include <base/containers/contains.h>
#include <base/logging.h>
#include <base/strings/stringprintf.h>
#include <base/strings/string_util.h>
#include <brillo/scoped_mount_namespace.h>

#include "cros-disks/quote.h"

namespace cros_disks {

namespace {
constexpr char kOptionPassword[] = "password";

bool IsFormatRaw(const std::string& archive_type) {
  return (archive_type == "bz2") || (archive_type == "gz") ||
         (archive_type == "xz");
}

void RecordArchiveTypeMetrics(Metrics* const metrics,
                              const std::string& archive_type,
                              bool format_raw,
                              const std::string& source) {
  if (format_raw) {
    // Discriminate between kArchiveOtherGzip and kArchiveTarGzip, and ditto
    // for the Bzip2 and Xz flavors.
    std::string ext = base::FilePath(source).Extension();
    if (base::LowerCaseEqualsASCII(ext, ".tar.bz2")) {
      metrics->RecordArchiveType("tar.bz2");
      return;
    } else if (base::LowerCaseEqualsASCII(ext, ".tar.gz")) {
      metrics->RecordArchiveType("tar.gz");
      return;
    } else if (base::LowerCaseEqualsASCII(ext, ".tar.xz")) {
      metrics->RecordArchiveType("tar.xz");
      return;
    }
  }
  metrics->RecordArchiveType(archive_type);
}
}  // namespace

ArchiveMounter::ArchiveMounter(
    const Platform* platform,
    brillo::ProcessReaper* process_reaper,
    std::string archive_type,
    Metrics* metrics,
    std::string metrics_name,
    std::vector<int> password_needed_exit_codes,
    std::unique_ptr<SandboxedProcessFactory> sandbox_factory,
    std::vector<std::string> extra_command_line_options)
    : FUSEMounter(
          platform, process_reaper, archive_type + "fs", {.read_only = true}),
      archive_type_(archive_type),
      extension_("." + archive_type),
      metrics_(metrics),
      metrics_name_(std::move(metrics_name)),
      password_needed_exit_codes_(std::move(password_needed_exit_codes)),
      sandbox_factory_(std::move(sandbox_factory)),
      extra_command_line_options_(std::move(extra_command_line_options)),
      format_raw_(IsFormatRaw(archive_type)) {}

ArchiveMounter::~ArchiveMounter() = default;

bool ArchiveMounter::CanMount(const std::string& source,
                              const std::vector<std::string>& /*params*/,
                              base::FilePath* suggested_dir_name) const {
  base::FilePath path(source);
  if (path.IsAbsolute() && base::CompareCaseInsensitiveASCII(
                               path.FinalExtension(), extension_) == 0) {
    *suggested_dir_name = path.BaseName();
    return true;
  }
  return false;
}

MountErrorType ArchiveMounter::InterpretReturnCode(int return_code) const {
  if (metrics_ && !metrics_name_.empty())
    metrics_->RecordFuseMounterErrorCode(metrics_name_, return_code);

  if (base::Contains(password_needed_exit_codes_, return_code))
    return MOUNT_ERROR_NEED_PASSWORD;
  return FUSEMounter::InterpretReturnCode(return_code);
}

std::unique_ptr<SandboxedProcess> ArchiveMounter::PrepareSandbox(
    const std::string& source,
    const base::FilePath& /*target_path*/,
    std::vector<std::string> params,
    MountErrorType* error) const {
  RecordArchiveTypeMetrics(metrics_, archive_type_, format_raw_, source);

  base::FilePath path(source);
  if (!path.IsAbsolute() || path.ReferencesParent()) {
    LOG(ERROR) << "Invalid archive path " << redact(path);
    *error = MOUNT_ERROR_INVALID_ARGUMENT;
    return nullptr;
  }

  auto sandbox = sandbox_factory_->CreateSandboxedProcess();

  std::unique_ptr<brillo::ScopedMountNamespace> mount_ns;
  if (!platform()->PathExists(path.value())) {
    // Try to locate the file in Chrome's mount namespace.
    mount_ns = brillo::ScopedMountNamespace::CreateFromPath(
        base::FilePath(kChromeNamespace));
    if (!mount_ns) {
      PLOG(ERROR) << "Cannot find archive " << redact(path)
                  << " in mount namespace " << quote(kChromeNamespace);

      // TODO(dats): These probably should be MOUNT_ERROR_INVALID_DEVICE_PATH or
      //             something like that, but tast tests expect
      //             MOUNT_ERROR_MOUNT_PROGRAM_FAILED.
      *error = MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
      return nullptr;
    }
    if (!platform()->PathExists(path.value())) {
      PLOG(ERROR) << "Cannot find archive " << redact(path);
      *error = MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
      return nullptr;
    }
  }

  // Archives are typically under /home, /media or /run. To bind-mount the
  // source those directories must be writable, but by default only /run is.
  for (const char* const dir : {"/home", "/media"}) {
    if (!sandbox->Mount("tmpfs", dir, "tmpfs", "mode=0755,size=1M")) {
      LOG(ERROR) << "Cannot mount " << quote(dir);
      *error = MOUNT_ERROR_INTERNAL;
      return nullptr;
    }
  }

  // Is the process "password-aware"?
  if (!password_needed_exit_codes_.empty()) {
    std::string password;
    if (GetParamValue(params, kOptionPassword, &password)) {
      sandbox->SetStdIn(password);
    }
  }

  // Bind-mount parts of a multipart archive if any.
  for (const std::string& part : GetBindPaths(path.value())) {
    if (!sandbox->BindMount(part, part, /* writeable= */ false,
                            /* recursive= */ false)) {
      PLOG(ERROR) << "Cannot bind-mount archive " << redact(part);
      *error = MOUNT_ERROR_INTERNAL;
      return nullptr;
    }
  }

  // Prepare command line arguments.
  sandbox->AddArgument("-o");
  sandbox->AddArgument(base::StringPrintf("ro,umask=0222,uid=%d,gid=%d",
                                          kChronosUID, kChronosAccessGID));

  for (const auto& opt : extra_command_line_options_)
    sandbox->AddArgument(opt);

  sandbox->AddArgument(path.value());

  if (mount_ns) {
    // Sandbox will need to enter Chrome's namespace too to access files.
    mount_ns.reset();
    sandbox->EnterExistingMountNamespace(kChromeNamespace);
  }

  *error = MOUNT_ERROR_NONE;
  return sandbox;
}

}  // namespace cros_disks
