aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2017-07-12 12:10:11 +0200
committerGravatar László Csomor <laszlocsomor@google.com>2017-07-12 16:02:39 +0200
commit264f40fb42ce1390f9ee420f923b77ef3a82327f (patch)
tree11e16746189e6ee28b57c9294f8570715e4edb87 /src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java
parent423a46a11acd109467573c3344a4dd49f211aea6 (diff)
Rewrite all the sandbox strategy implementations
- Make use of existing abstractions like SpawnRunner and SpawnExecutionPolicy. - Instead of having the *Strategy create a *Runner, and then call back into SandboxStrategy, create a single SandboxContainer which contains the full command line, environment, and everything needed to create and delete the sandbox directory. - Do all the work in SandboxStrategy, including creation and deletion of the sandbox directory. - Use SpawnResult instead of throwing, catching, and rethrowing. - Simplify the control flow a bit. PiperOrigin-RevId: 161644979
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java160
1 files changed, 0 insertions, 160 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java b/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java
deleted file mode 100644
index a158f02961..0000000000
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedExecRoot.java
+++ /dev/null
@@ -1,160 +0,0 @@
-// Copyright 2016 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.io.Files;
-import com.google.devtools.build.lib.util.Preconditions;
-import com.google.devtools.build.lib.vfs.FileStatus;
-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 com.google.devtools.build.lib.vfs.Symlinks;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-/**
- * Creates an execRoot for a Spawn that contains input files as symlinks to their original
- * destination.
- */
-public final class SymlinkedExecRoot implements SandboxExecRoot {
-
- private final Path sandboxExecRoot;
-
- public SymlinkedExecRoot(Path sandboxExecRoot) {
- this.sandboxExecRoot = sandboxExecRoot;
- }
-
- @Override
- public void createFileSystem(
- Map<PathFragment, Path> inputs, Collection<PathFragment> outputs, Set<Path> writableDirs)
- throws IOException {
- Set<Path> createdDirs = new HashSet<>();
- cleanFileSystem(inputs.keySet());
- FileSystemUtils.createDirectoryAndParentsWithCache(createdDirs, sandboxExecRoot);
- createParentDirectoriesForInputs(createdDirs, inputs.keySet());
- createInputs(inputs);
- createWritableDirectories(createdDirs, writableDirs);
- createDirectoriesForOutputs(createdDirs, outputs);
- }
-
- private void cleanFileSystem(Set<PathFragment> allowedFiles) throws IOException {
- if (sandboxExecRoot.exists(Symlinks.NOFOLLOW)) {
- deleteExceptAllowedFiles(sandboxExecRoot, allowedFiles);
- }
- }
-
- private void deleteExceptAllowedFiles(Path root, Set<PathFragment> allowedFiles)
- throws IOException {
- for (Path p : root.getDirectoryEntries()) {
- FileStatus stat = p.stat(Symlinks.NOFOLLOW);
- if (!stat.isDirectory()) {
- if (!allowedFiles.contains(p.relativeTo(sandboxExecRoot))) {
- p.delete();
- }
- } else {
- deleteExceptAllowedFiles(p, allowedFiles);
- if (p.readdir(Symlinks.NOFOLLOW).isEmpty()) {
- p.delete();
- }
- }
- }
- }
-
- /**
- * No input can be a child of another input, because otherwise we might try to create a symlink
- * below another symlink we created earlier - which means we'd actually end up writing somewhere
- * in the workspace.
- *
- * <p>If all inputs were regular files, this situation could naturally not happen - but
- * unfortunately, we might get the occasional action that has directories in its inputs.
- *
- * <p>Creating all parent directories first ensures that we can safely create symlinks to
- * directories, too, because we'll get an IOException with EEXIST if inputs happen to be nested
- * once we start creating the symlinks for all inputs.
- */
- private void createParentDirectoriesForInputs(Set<Path> createdDirs, Set<PathFragment> inputs)
- throws IOException {
- for (PathFragment inputPath : inputs) {
- Path dir = sandboxExecRoot.getRelative(inputPath).getParentDirectory();
- Preconditions.checkArgument(
- dir.startsWith(sandboxExecRoot), "Bad relative path: '%s'", inputPath);
- FileSystemUtils.createDirectoryAndParentsWithCache(createdDirs, dir);
- }
- }
-
- private void createInputs(Map<PathFragment, Path> inputs) throws IOException {
- // All input files are relative to the execroot.
- for (Entry<PathFragment, Path> entry : inputs.entrySet()) {
- Path key = sandboxExecRoot.getRelative(entry.getKey());
- FileStatus keyStat = key.statNullable(Symlinks.NOFOLLOW);
- if (keyStat != null) {
- if (keyStat.isSymbolicLink()
- && entry.getValue() != null
- && key.readSymbolicLink().equals(entry.getValue().asFragment())) {
- continue;
- }
- key.delete();
- }
- // A null value means that we're supposed to create an empty file as the input.
- if (entry.getValue() != null) {
- key.createSymbolicLink(entry.getValue());
- } else {
- FileSystemUtils.createEmptyFile(key);
- }
- }
- }
-
- private void createWritableDirectories(Set<Path> createdDirs, Set<Path> writableDirs)
- throws IOException {
- for (Path writablePath : writableDirs) {
- if (writablePath.startsWith(sandboxExecRoot)) {
- FileSystemUtils.createDirectoryAndParentsWithCache(createdDirs, writablePath);
- }
- }
- }
-
- /** Prepare the output directories in the sandbox. */
- private void createDirectoriesForOutputs(Set<Path> createdDirs, Collection<PathFragment> outputs)
- throws IOException {
- for (PathFragment output : outputs) {
- FileSystemUtils.createDirectoryAndParentsWithCache(
- createdDirs, sandboxExecRoot.getRelative(output.getParentDirectory()));
- }
- }
-
- /** Moves all {@code outputs} to {@code execRoot}. */
- @Override
- public void copyOutputs(Path execRoot, Collection<PathFragment> outputs) throws IOException {
- for (PathFragment output : outputs) {
- Path source = sandboxExecRoot.getRelative(output);
- Path target = execRoot.getRelative(output);
- if (source.isFile() || source.isSymbolicLink()) {
- Files.move(source.getPathFile(), target.getPathFile());
- } else if (source.isDirectory()) {
- try {
- source.renameTo(target);
- } catch (IOException e) {
- // Failed to move directory directly, thus move it recursively.
- target.createDirectory();
- FileSystemUtils.moveTreesBelow(source, target);
- }
- }
- }
- }
-}