// 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.collect.ImmutableSet;
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> bindMounts;
  private final boolean sandboxDebug;

  LinuxSandboxRunner(
      Path execRoot,
      Path sandboxPath,
      Path sandboxExecRoot,
      Path sandboxTempDir,
      Set<Path> writableDirs,
      Set<Path> inaccessiblePaths,
      ImmutableSet<Path> bindMounts,
      boolean verboseFailures,
      boolean sandboxDebug) {
    super(sandboxExecRoot, verboseFailures);
    this.execRoot = execRoot;
    this.sandboxExecRoot = sandboxExecRoot;
    this.sandboxTempDir = sandboxTempDir;
    this.argumentsFilePath = sandboxPath.getRelative("linux-sandbox.params");
    this.writableDirs = writableDirs;
    this.inaccessiblePaths = inaccessiblePaths;
    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)
      throws IOException {
    writeConfig(timeout, allowNetwork);

    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) 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 bindMount : bindMounts) {
      fileArgs.add("-b");
      fileArgs.add(bindMount.getPathString());
    }

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

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