// Copyright 2018 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.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.devtools.build.lib.shell.Subprocess;
import com.google.devtools.build.lib.shell.SubprocessBuilder;
import com.google.devtools.build.lib.util.OS;
import com.google.devtools.build.lib.versioning.GnuVersionParser;
import com.google.devtools.build.lib.versioning.ParseException;
import com.google.devtools.build.lib.versioning.SemVer;
import com.google.devtools.build.lib.vfs.Path;
import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
import java.util.logging.Logger;
import javax.annotation.Nullable;

/**
 * A sandboxfs implementation that uses an external sandboxfs binary to manage the mount point.
 *
 * <p>This class implements common code to generalize the interactions with sandboxfs, but delegates
 * to its subclassess once the version of sandboxfs in use has been determined. The subclasses
 * implement logic specific to each version to provide compatibility with the different versions of
 * sandboxfs that the user might have installed.
 */
abstract class RealSandboxfsProcess implements SandboxfsProcess {

  private static final Logger log = Logger.getLogger(RealSandboxfsProcess.class.getName());

  /**
   * Contains the {@code --allow} flag to pass to sandboxfs.
   *
   * <p>On macOS, we need to allow users other than self to access the sandboxfs instance. This is
   * necessary because macOS's amfid, which runs as root, has to have access to the binaries within
   * the sandbox in order to validate signatures. See:
   * http://jmmv.dev/2017/10/fighting-execs-sandboxfs-macos.html
   */
  @VisibleForTesting
  static final String ALLOW_FLAG = OS.getCurrent() == OS.DARWIN ? "--allow=other" : "--allow=self";

  /** Directory on which the sandboxfs is serving. */
  private final Path mountPoint;

  /**
   * Process handle to the sandboxfs instance.  Null only after {@link #destroy()} has been invoked.
   */
  private @Nullable Subprocess process;

  /**
   * Shutdown hook to stop the sandboxfs instance on abrupt termination.  Null only after
   * {@link #destroy()} has been invoked.
   */
  private @Nullable Thread shutdownHook;

  /**
   * Initializes a new sandboxfs process instance.
   *
   * @param process process handle for the already-running sandboxfs instance
   */
  RealSandboxfsProcess(Path mountPoint, Subprocess process) {
    this.mountPoint = mountPoint;
    this.process = process;

    this.shutdownHook =
        new Thread(
            () -> {
              try {
                this.destroy();
              } catch (Exception e) {
                log.warning("Failed to destroy running sandboxfs instance; mount point may have "
                    + "been left behind: " + e);
              }
            });
    Runtime.getRuntime().addShutdownHook(shutdownHook);
  }

  /**
   * Mounts a new sandboxfs instance.
   *
   * <p>The root of the file system instance is left unmapped which means that it remains as
   * read-only throughout the lifetime of this instance. Writable subdirectories can later be mapped
   * via {@link #createSandbox}.
   *
   * @param binary path to the sandboxfs binary. This is a {@link PathFragment} and not a {@link
   *     Path} because we want to support "bare" (non-absolute) names for the location of the
   *     sandboxfs binary; such names are automatically looked for in the {@code PATH}.
   * @param mountPoint directory on which to mount the sandboxfs instance
   * @param logFile path to the file that will receive all sandboxfs logging output
   * @return a new handle that represents the running process
   * @throws IOException if there is a problem starting the process
   */
  static SandboxfsProcess mount(PathFragment binary, Path mountPoint, Path logFile)
      throws IOException {
    log.info("Mounting sandboxfs (" + binary + ") onto " + mountPoint);

    GnuVersionParser<SemVer> parser = new GnuVersionParser<>("sandboxfs", SemVer::parse);
    SemVer version;
    try {
      version = parser.fromProgram(binary);
    } catch (IOException | ParseException e) {
      throw new IOException("Failed to get sandboxfs version from " + binary, e);
    }

    ImmutableList.Builder<String> argvBuilder = ImmutableList.builder();
    argvBuilder.add(binary.getPathString());
    argvBuilder.add(ALLOW_FLAG);

    // TODO(jmmv): Pass flags to enable sandboxfs' debugging support (--listen_address and --debug)
    // when requested by the user via --sandbox_debug.  Tricky because we have to figure out how to
    // deal with port numbers (which sandboxfs can autoassign, but doesn't currently promise a way
    // to tell us back what it picked).

    argvBuilder.add(mountPoint.getPathString());

    SubprocessBuilder processBuilder = new SubprocessBuilder();
    processBuilder.setArgv(argvBuilder.build());
    processBuilder.setStderr(logFile.getPathFile());
    processBuilder.setEnv(ImmutableMap.of(
        // sandboxfs may need to locate fusermount depending on the FUSE implementation so pass the
        // PATH to the subprocess (which we assume is sufficient).
        "PATH", System.getenv("PATH")));

    Subprocess process = processBuilder.start();
    RealSandboxfsProcess sandboxfs;
    if (version.compareTo(SemVer.from(0, 2)) >= 0) {
      sandboxfs = new RealSandboxfs02Process(mountPoint, process);
    } else {
      sandboxfs = new RealSandboxfs01Process(mountPoint, process);
    }
    try {
      // Create an empty sandbox to ensure sandboxfs is successfully serving.
      sandboxfs.createSandbox("empty", ImmutableList.of());
    } catch (IOException e) {
      process.destroyAndWait();
      throw new IOException("sandboxfs failed to start", e);
    }
    return sandboxfs;
  }

  @Override
  public Path getMountPoint() {
    return mountPoint;
  }

  @Override
  public boolean isAlive() {
    return process != null && !process.finished();
  }

  @Override
  public synchronized void destroy() {
    if (shutdownHook != null) {
      Runtime.getRuntime().removeShutdownHook(shutdownHook);
      shutdownHook = null;
    }

    if (process != null) {
      try {
        process.getOutputStream().close();
      } catch (IOException e) {
        log.warning("Failed to close sandboxfs's stdin pipe: " + e);
      }

      try {
        process.getInputStream().close();
      } catch (IOException e) {
        log.warning("Failed to close sandboxfs's stdout pipe: " + e);
      }

      process.destroyAndWait();
      process = null;
    }
  }
}
