aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java')
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java97
1 files changed, 23 insertions, 74 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java b/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java
index f4d41e38a3..d2806db1a1 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/SymlinkedSandboxedSpawn.java
@@ -15,14 +15,13 @@
package com.google.devtools.build.lib.sandbox;
import com.google.common.base.Preconditions;
-import com.google.devtools.build.lib.vfs.FileStatus;
+import com.google.common.collect.Iterables;
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.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
@@ -75,36 +74,8 @@ public class SymlinkedSandboxedSpawn implements SandboxedSpawn {
@Override
public void createFileSystem() throws IOException {
- Set<Path> createdDirs = new HashSet<>();
- cleanFileSystem(inputs.keySet());
- createDirectoryAndParentsWithCache(createdDirs, sandboxExecRoot);
- createParentDirectoriesForInputs(createdDirs, inputs.keySet());
+ createDirectories();
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();
- }
- }
- }
}
/**
@@ -119,29 +90,32 @@ public class SymlinkedSandboxedSpawn implements SandboxedSpawn {
* 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);
- createDirectoryAndParentsWithCache(createdDirs, dir);
+ private void createDirectories() throws IOException {
+ LinkedHashSet<Path> dirsToCreate = new LinkedHashSet<>();
+
+ for (PathFragment path : Iterables.concat(inputs.keySet(), outputs)) {
+ Preconditions.checkArgument(!path.isAbsolute());
+ Preconditions.checkArgument(!path.containsUplevelReferences());
+ for (int i = 0; i < path.segmentCount(); i++) {
+ dirsToCreate.add(sandboxExecRoot.getRelative(path.subFragment(0, i)));
+ }
+ }
+
+ for (Path path : dirsToCreate) {
+ path.createDirectory();
+ }
+
+ for (Path dir : writableDirs) {
+ if (dir.startsWith(sandboxExecRoot)) {
+ dir.createDirectoryAndParents();
+ }
}
}
- private void createInputs(Map<PathFragment, Path> inputs) throws IOException {
+ protected 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());
@@ -151,24 +125,6 @@ public class SymlinkedSandboxedSpawn implements SandboxedSpawn {
}
}
- private void createWritableDirectories(Set<Path> createdDirs, Set<Path> writableDirs)
- throws IOException {
- for (Path writablePath : writableDirs) {
- if (writablePath.startsWith(sandboxExecRoot)) {
- 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) {
- createDirectoryAndParentsWithCache(
- createdDirs, sandboxExecRoot.getRelative(output.getParentDirectory()));
- }
- }
-
@Override
public void copyOutputs(Path execRoot) throws IOException {
SandboxedSpawn.moveOutputs(outputs, sandboxExecRoot, execRoot);
@@ -188,11 +144,4 @@ public class SymlinkedSandboxedSpawn implements SandboxedSpawn {
// on here.
}
}
-
- private static void createDirectoryAndParentsWithCache(Set<Path> cache, Path dir)
- throws IOException {
- if (cache.add(dir)) {
- dir.createDirectoryAndParents();
- }
- }
}