// Copyright (c) 2013 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/fuse_mounter.h"

#include <linux/capability.h>

#include <string>

#include <base/file_util.h>
#include <base/logging.h>

#include "cros-disks/platform.h"
#include "cros-disks/sandboxed_process.h"

using base::FilePath;
using std::string;

namespace {

// Process capabilities required by the FUSE mount process:
//   CAP_SYS_ADMIN for mounting/unmounting filesystem
//   CAP_SETUID/CAP_SETGID for setting uid/gid in non-privileged mounts
const uint64_t kMountProgramCapabilities =
    (1 << CAP_SYS_ADMIN) | (1 << CAP_SETUID) | (1 << CAP_SETGID);

const mode_t kSourcePathPermissions = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
const mode_t kTargetPathPermissions = S_IRWXU | S_IRWXG;

}  // namespace

namespace cros_disks {

FUSEMounter::FUSEMounter(const string& source_path,
                         const string& target_path,
                         const string& filesystem_type,
                         const MountOptions& mount_options,
                         const Platform* platform,
                         const string& mount_program_path,
                         const string& mount_user)
    : Mounter(source_path, target_path, filesystem_type, mount_options),
      platform_(platform),
      mount_program_path_(mount_program_path),
      mount_user_(mount_user) {
}

MountErrorType FUSEMounter::MountImpl() {
  if (!file_util::PathExists(FilePath(mount_program_path_))) {
    LOG(ERROR) << "Failed to find the FUSE mount program";
    return MOUNT_ERROR_MOUNT_PROGRAM_NOT_FOUND;
  }

  SandboxedProcess mount_process;
  mount_process.SetCapabilities(kMountProgramCapabilities);

  uid_t mount_user_id;
  gid_t mount_group_id;
  // To perform a non-privileged mount via the FUSE mount program, change the
  // group of the source and target path to the group of the non-privileged
  // user, but keep the user of the source and target path unchanged. Also set
  // appropriate group permissions on the source and target path.
  if (!platform_->GetUserAndGroupId(mount_user_,
                                    &mount_user_id, &mount_group_id) ||
      !platform_->SetOwnership(source_path(), getuid(), mount_group_id) ||
      !platform_->SetPermissions(source_path(), kSourcePathPermissions) ||
      !platform_->SetOwnership(target_path(), getuid(), mount_group_id) ||
      !platform_->SetPermissions(target_path(), kTargetPathPermissions)) {
    return MOUNT_ERROR_INTERNAL;
  }
  mount_process.SetUserId(mount_user_id);
  mount_process.SetGroupId(mount_group_id);

  mount_process.AddArgument(mount_program_path_);
  string options_string = mount_options().ToString();
  if (!options_string.empty()) {
    mount_process.AddArgument("-o");
    mount_process.AddArgument(options_string);
  }
  mount_process.AddArgument(source_path());
  mount_process.AddArgument(target_path());

  int return_code = mount_process.Run();
  if (return_code != 0) {
    LOG(WARNING) << "FUSE mount program failed with a return code "
                 << return_code;
    return MOUNT_ERROR_MOUNT_PROGRAM_FAILED;
  }
  return MOUNT_ERROR_NONE;
}

}  // namespace cros_disks
