// Copyright 2014 The Bazel Authors. All rights reserved.
//
// 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.

package com.google.devtools.build.lib.sandbox;

import com.google.common.collect.ImmutableMap;
import com.google.common.io.ByteStreams;
import com.google.devtools.build.lib.runtime.CommandEnvironment;
import com.google.devtools.build.lib.shell.Command;
import com.google.devtools.build.lib.shell.CommandException;
import com.google.devtools.build.lib.util.OsUtils;
import com.google.devtools.build.lib.vfs.FileSystemUtils;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Helper class for running the Linux sandbox. This runner prepares environment inside the sandbox,
 * handles sandbox output, performs cleanup and changes invocation if necessary.
 */
final class LinuxSandboxRunner extends SandboxRunner {
  protected static final String LINUX_SANDBOX = "linux-sandbox" + OsUtils.executableExtension();

  private final Path execRoot;
  private final Path sandboxExecRoot;
  private final Path sandboxTempDir;
  private final Path argumentsFilePath;
  private final Set<Path> writableDirs;
  private final Set<Path> inaccessiblePaths;
  private final Set<Path> tmpfsPaths;
  // a <target, source> mapping of paths to bind mount
  private final Map<Path, Path> bindMounts;
  private final boolean sandboxDebug;

  LinuxSandboxRunner(
      Path execRoot,
      Path sandboxPath,
      Path sandboxExecRoot,
      Path sandboxTempDir,
      Set<Path> writableDirs,
      Set<Path> inaccessiblePaths,
      Set<Path> tmpfsPaths,
      Map<Path, Path> bindMounts,
      boolean verboseFailures,
      boolean sandboxDebug) {
    super(verboseFailures);
    this.execRoot = execRoot;
    this.sandboxExecRoot = sandboxExecRoot;
    this.sandboxTempDir = sandboxTempDir;
    this.argumentsFilePath = sandboxPath.getRelative("linux-sandbox.params");
    this.writableDirs = writableDirs;
    this.inaccessiblePaths = inaccessiblePaths;
    this.tmpfsPaths = tmpfsPaths;
    this.bindMounts = bindMounts;
    this.sandboxDebug = sandboxDebug;
  }

  static boolean isSupported(CommandEnvironment commandEnv) {
    Path execRoot = commandEnv.getExecRoot();

    PathFragment embeddedTool =
        commandEnv.getBlazeWorkspace().getBinTools().getExecPath(LINUX_SANDBOX);
    if (embeddedTool == null) {
      // The embedded tool does not exist, meaning that we don't support sandboxing (e.g., while
      // bootstrapping).
      return false;
    }

    List<String> args = new ArrayList<>();
    args.add(execRoot.getRelative(embeddedTool).getPathString());
    args.add("-C");

    ImmutableMap<String, String> env = ImmutableMap.of();
    File cwd = execRoot.getPathFile();

    Command cmd = new Command(args.toArray(new String[0]), env, cwd);
    try {
      cmd.execute(
          /* stdin */ new byte[] {},
          Command.NO_OBSERVER,
          ByteStreams.nullOutputStream(),
          ByteStreams.nullOutputStream(),
          /* killSubprocessOnInterrupt */ true);
    } catch (CommandException e) {
      return false;
    }

    return true;
  }

  @Override
  protected Command getCommand(
      List<String> spawnArguments,
      Map<String, String> env,
      int timeout,
      boolean allowNetwork,
      boolean useFakeHostname)
      throws IOException {
    writeConfig(timeout, allowNetwork, useFakeHostname);

    List<String> commandLineArgs = new ArrayList<>(3 + spawnArguments.size());
    commandLineArgs.add(execRoot.getRelative("_bin/linux-sandbox").getPathString());
    commandLineArgs.add("@" + argumentsFilePath.getPathString());
    commandLineArgs.add("--");
    commandLineArgs.addAll(spawnArguments);
    return new Command(commandLineArgs.toArray(new String[0]), env, sandboxExecRoot.getPathFile());
  }

  private void writeConfig(int timeout, boolean allowNetwork, boolean useFakeHostname)
      throws IOException {
    List<String> fileArgs = new ArrayList<>();

    if (sandboxDebug) {
      fileArgs.add("-D");
    }

    // Temporary directory of the sandbox.
    fileArgs.add("-S");
    fileArgs.add(sandboxTempDir.toString());

    // Working directory of the spawn.
    fileArgs.add("-W");
    fileArgs.add(sandboxExecRoot.toString());

    // Kill the process after a timeout.
    if (timeout != -1) {
      fileArgs.add("-T");
      fileArgs.add(Integer.toString(timeout));
    }

    // Create all needed directories.
    for (Path writablePath : writableDirs) {
      fileArgs.add("-w");
      fileArgs.add(writablePath.getPathString());
    }

    for (Path inaccessiblePath : inaccessiblePaths) {
      fileArgs.add("-i");
      fileArgs.add(inaccessiblePath.getPathString());
    }

    for (Path tmpfsPath : tmpfsPaths) {
      fileArgs.add("-e");
      fileArgs.add(tmpfsPath.getPathString());
    }

    for (ImmutableMap.Entry<Path, Path> bindMount : bindMounts.entrySet()) {
      fileArgs.add("-M");
      fileArgs.add(bindMount.getValue().getPathString());

      // The file is mounted in a custom location inside the sandbox.
      if (!bindMount.getKey().equals(bindMount.getValue())) {
        fileArgs.add("-m");
        fileArgs.add(bindMount.getKey().getPathString());
      }
    }

    if (!allowNetwork) {
      // Block network access out of the namespace.
      fileArgs.add("-N");
    }

    if (useFakeHostname) {
      // Use a fake hostname ("localhost") inside the sandbox when blocking network access.
      fileArgs.add("-H");
    }

    FileSystemUtils.writeLinesAs(argumentsFilePath, StandardCharsets.ISO_8859_1, fileArgs);
  }
}
