/*
 * Copyright (C) 2018 The Android Open Source Project
 *
 * Licensed 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.
 */

#define LOG_TAG "apexd"

#include "apexd_prepostinstall.h"

#include <algorithm>
#include <vector>

#include <fcntl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>

#include <android-base/logging.h>
#include <android-base/macros.h>
#include <android-base/scopeguard.h>
#include <android-base/strings.h>

#include "apex_file.h"
#include "apexd.h"
#include "apexd_private.h"
#include "apexd_utils.h"
#include "string_log.h"

namespace android {
namespace apex {

namespace {

void PseudoCloseDescriptors() {
  int write_fd = open("/dev/null", O_WRONLY);
  int read_fd = open("/dev/zero", O_RDONLY);
  if (write_fd == -1 || read_fd == -1) {
    PLOG(FATAL) << "Error opening fds " << write_fd << " " << read_fd;
  }
  auto dup_or_close = [](int new_fd, int old_fd) {
    int rc = TEMP_FAILURE_RETRY(dup2(new_fd, old_fd));
    if (rc != 0) {
      if (errno != EBADF) {
        rc = close(old_fd);
      }
    }
  };
  dup_or_close(read_fd, STDIN_FILENO);
  dup_or_close(write_fd, STDOUT_FILENO);
  dup_or_close(write_fd, STDERR_FILENO);
}

template <typename Fn>
Status StageFnInstall(std::vector<ApexFile>& apexes, Fn fn, const char* arg,
                      const char* name) {
  // TODO: Support a session with more than one pre-install hook.
  const ApexFile* hook_file = nullptr;
  for (const ApexFile& f : apexes) {
    if (!(f.GetManifest().*fn)().empty()) {
      if (hook_file != nullptr) {
        return Status::Fail(StringLog() << "Missing support for multiple "
                                        << name << " hooks");
      }
      hook_file = &f;
    }
  }
  CHECK(hook_file != nullptr);
  LOG(VERBOSE) << name << " for " << hook_file->GetPath();

  std::vector<const ApexFile*> mounted_apexes;
  std::vector<std::string> activation_dirs;
  auto preinstall_guard = android::base::make_scope_guard([&]() {
    for (const ApexFile* f : mounted_apexes) {
      Status st = apexd_private::UnmountPackage(*f);
      if (!st.Ok()) {
        LOG(ERROR) << "Failed to unmount " << f->GetPath() << " after " << name
                   << ": " << st.ErrorMessage();
      }
    }
    for (const std::string& active_point : activation_dirs) {
      if (0 != rmdir(active_point.c_str())) {
        PLOG(ERROR) << "Could not delete temporary active point "
                    << active_point;
      }
    }
  });

  for (const ApexFile& apex : apexes) {
    // 1) Mount the package, if necessary.
    std::string mount_point =
        apexd_private::GetPackageMountPoint(apex.GetManifest());

    if (!apexd_private::IsMounted(apex.GetManifest().name(), apex.GetPath())) {
      Status mountStatus = apexd_private::MountPackage(apex, mount_point);
      if (!mountStatus.Ok()) {
        return mountStatus;
      }
      mounted_apexes.push_back(&apex);
    }

    // 2) Ensure there is an activation point, and we will clean it up.
    std::string active_point =
        apexd_private::GetActiveMountPoint(apex.GetManifest());
    if (0 == mkdir(active_point.c_str(), kMkdirMode)) {
      activation_dirs.emplace_back(std::move(active_point));
    } else {
      int saved_errno = errno;
      if (saved_errno != EEXIST) {
        return Status::Fail(StringLog()
                            << "Unable to create mount point" << active_point
                            << ": " << strerror(saved_errno));
      }
    }
  }

  // 3) Create invocation args.
  std::vector<std::string> args{
      "/system/bin/apexd", arg,
      hook_file->GetPath(),  // Make the APEX with hook first.
  };
  for (const ApexFile& apex : apexes) {
    if (&apex != hook_file) {
      args.push_back(apex.GetPath());
    }
  }

  std::string error_msg;
  int res = ForkAndRun(args, &error_msg);
  return res == 0 ? Status::Success() : Status::Fail(error_msg);
}

template <typename Fn>
int RunFnInstall(char** in_argv, Fn fn, const char* name) {
  // 1) Close all file descriptors. They are coming from the caller, we do not
  // want to pass them on across our fork/exec into a different domain.
  PseudoCloseDescriptors();

  // 2) Unshare.
  if (unshare(CLONE_NEWNS) != 0) {
    PLOG(ERROR) << "Failed to unshare() for apex " << name;
    _exit(200);
  }

  // 3) Make /apex private, so that our changes don't propagate.
  if (mount("", kApexRoot, nullptr, MS_PRIVATE, nullptr) != 0) {
    PLOG(ERROR) << "Failed to mount private.";
    _exit(201);
  }

  std::string hook_path;
  {
    auto bind_fn = [&fn, name](const std::string& apex) {
      std::string hook;
      std::string mount_point;
      std::string active_point;
      {
        StatusOr<ApexFile> apex_file = ApexFile::Open(apex);
        if (!apex_file.Ok()) {
          LOG(ERROR) << "Could not open apex " << apex << " for " << name
                     << ": " << apex_file.ErrorMessage();
          _exit(202);
        }
        const ApexManifest& manifest = apex_file->GetManifest();
        hook = (manifest.*fn)();
        mount_point = apexd_private::GetPackageMountPoint(manifest);
        active_point = apexd_private::GetActiveMountPoint(manifest);
      }

      // 4) Activate the new apex.
      Status bind_status = apexd_private::BindMount(active_point, mount_point);
      if (!bind_status.Ok()) {
        LOG(ERROR) << "Failed to bind-mount " << mount_point << " to "
                   << active_point << ": " << bind_status.ErrorMessage();
        _exit(203);
      }

      return std::make_pair(active_point, hook);
    };

    // First/main APEX.
    auto [active_point, hook] = bind_fn(in_argv[2]);
    hook_path = active_point + "/" + hook;

    for (size_t i = 3;; ++i) {
      if (in_argv[i] == nullptr) {
        break;
      }
      bind_fn(in_argv[i]);  // Ignore result, hook will be empty.
    }
  }

  // 5) Run the hook.

  // For now, just run sh. But this probably needs to run the new linker.
  std::vector<std::string> args{
      "/system/bin/sh",
      "-c",
      hook_path,
  };
  std::vector<const char*> argv;
  argv.resize(args.size() + 1, nullptr);
  std::transform(args.begin(), args.end(), argv.begin(),
                 [](const std::string& in) { return in.c_str(); });

  LOG(ERROR) << "execv of " << android::base::Join(args, " ");

  execv(argv[0], const_cast<char**>(argv.data()));
  PLOG(ERROR) << "execv of " << android::base::Join(args, " ") << " failed";
  _exit(204);
}

}  // namespace

Status StagePreInstall(std::vector<ApexFile>& apexes) {
  return StageFnInstall(apexes, &ApexManifest::preinstallhook, "--pre-install",
                        "pre-install");
}

int RunPreInstall(char** in_argv) {
  return RunFnInstall(in_argv, &ApexManifest::preinstallhook, "pre-install");
}

Status StagePostInstall(std::vector<ApexFile>& apexes) {
  return StageFnInstall(apexes, &ApexManifest::postinstallhook,
                        "--post-install", "post-install");
}

int RunPostInstall(char** in_argv) {
  return RunFnInstall(in_argv, &ApexManifest::postinstallhook, "post-install");
}

}  // namespace apex
}  // namespace android
