aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Philipp Wollermann <philwo@google.com>2017-05-09 05:56:24 -0400
committerGravatar Kristina Chodorow <kchodorow@google.com>2017-05-09 10:54:33 -0400
commit92bad2984eb8e301f9504a053d73213942fa3de3 (patch)
treeac424ff1764e3429ed05d15eb5d4004c64e09211
parent6f041661ca159903691fcb443d86dc7b6454253d (diff)
sandbox: Precache writable directories in DarwinSandboxedStrategy.
Change-Id: I1522c364a157ee0a144ab83eca54e419142c03b1 PiperOrigin-RevId: 155484109
-rw-r--r--src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedStrategy.java105
1 files changed, 54 insertions, 51 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedStrategy.java b/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedStrategy.java
index 62a5c52af1..25c8dd33e4 100644
--- a/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/sandbox/DarwinSandboxedStrategy.java
@@ -17,7 +17,6 @@ package com.google.devtools.build.lib.sandbox;
import static java.nio.charset.StandardCharsets.UTF_8;
import com.google.common.base.Predicates;
-import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
@@ -47,7 +46,7 @@ import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.util.HashMap;
-import java.util.List;
+import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
@@ -64,17 +63,23 @@ public class DarwinSandboxedStrategy extends SandboxStrategy {
private final boolean sandboxDebug;
private final boolean verboseFailures;
private final String productName;
- private final ImmutableList<Path> confPaths;
private final SpawnHelpers spawnHelpers;
+ /**
+ * The set of directories that always should be writable, independent of the Spawn itself.
+ *
+ * <p>We cache this, because creating it involves executing {@code getconf}, which is expensive.
+ */
+ private final ImmutableSet<Path> alwaysWritableDirs;
+
private DarwinSandboxedStrategy(
CommandEnvironment cmdEnv,
BuildRequest buildRequest,
Path sandboxBase,
boolean verboseFailures,
String productName,
- ImmutableList<Path> confPaths,
- SpawnHelpers spawnHelpers) {
+ SpawnHelpers spawnHelpers,
+ ImmutableSet<Path> alwaysWritableDirs) {
super(
cmdEnv,
buildRequest,
@@ -86,8 +91,8 @@ public class DarwinSandboxedStrategy extends SandboxStrategy {
this.sandboxDebug = buildRequest.getOptions(SandboxOptions.class).sandboxDebug;
this.verboseFailures = verboseFailures;
this.productName = productName;
- this.confPaths = confPaths;
this.spawnHelpers = spawnHelpers;
+ this.alwaysWritableDirs = alwaysWritableDirs;
}
public static DarwinSandboxedStrategy create(
@@ -97,25 +102,52 @@ public class DarwinSandboxedStrategy extends SandboxStrategy {
boolean verboseFailures,
String productName)
throws IOException {
- // On OS X, in addition to what is specified in $TMPDIR, two other temporary directories may be
- // written to by processes. We have to get their location by calling "getconf".
- List<String> confVars = ImmutableList.of("DARWIN_USER_TEMP_DIR", "DARWIN_USER_CACHE_DIR");
- ImmutableList.Builder<Path> writablePaths = ImmutableList.builder();
- for (String confVar : confVars) {
- Path path = cmdEnv.getDirectories().getFileSystem().getPath(getConfStr(confVar));
- if (path.exists()) {
- writablePaths.add(path);
- }
- }
-
return new DarwinSandboxedStrategy(
cmdEnv,
buildRequest,
sandboxBase,
verboseFailures,
productName,
- writablePaths.build(),
- new SpawnHelpers(cmdEnv.getExecRoot()));
+ new SpawnHelpers(cmdEnv.getExecRoot()),
+ getAlwaysWritableDirs(cmdEnv.getDirectories().getFileSystem()));
+ }
+
+ private static void addPathToSetIfExists(FileSystem fs, Set<Path> paths, String path)
+ throws IOException {
+ if (path != null) {
+ addPathToSetIfExists(paths, fs.getPath(path));
+ }
+ }
+
+ private static void addPathToSetIfExists(Set<Path> paths, Path path) throws IOException {
+ if (path.exists()) {
+ paths.add(path.resolveSymbolicLinks());
+ }
+ }
+
+ private static ImmutableSet<Path> getAlwaysWritableDirs(FileSystem fs) throws IOException {
+ HashSet<Path> writableDirs = new HashSet<>();
+
+ addPathToSetIfExists(fs, writableDirs, "/dev");
+ addPathToSetIfExists(fs, writableDirs, System.getenv("TMPDIR"));
+ addPathToSetIfExists(fs, writableDirs, "/tmp");
+ addPathToSetIfExists(fs, writableDirs, "/private/tmp");
+ addPathToSetIfExists(fs, writableDirs, "/private/var/tmp");
+
+ // On macOS, in addition to what is specified in $TMPDIR, two other temporary directories may be
+ // written to by processes. We have to get their location by calling "getconf".
+ addPathToSetIfExists(fs, writableDirs, getConfStr("DARWIN_USER_TEMP_DIR"));
+ addPathToSetIfExists(fs, writableDirs, getConfStr("DARWIN_USER_CACHE_DIR"));
+
+ // ~/Library/Cache and ~/Library/Logs need to be writable (cf. issue #2231).
+ Path homeDir = fs.getPath(System.getProperty("user.home"));
+ addPathToSetIfExists(writableDirs, homeDir.getRelative("Library/Cache"));
+ addPathToSetIfExists(writableDirs, homeDir.getRelative("Library/Logs"));
+
+ // Certain Xcode tools expect to be able to write to this path.
+ addPathToSetIfExists(writableDirs, homeDir.getRelative("Library/Developer"));
+
+ return ImmutableSet.copyOf(writableDirs);
}
/**
@@ -168,7 +200,9 @@ public class DarwinSandboxedStrategy extends SandboxStrategy {
ImmutableMap<String, String> spawnEnvironment =
StandaloneSpawnStrategy.locallyDeterminedEnv(execRoot, productName, spawn.getEnvironment());
- Set<Path> writableDirs = getWritableDirs(sandboxExecRoot, spawn.getEnvironment());
+ HashSet<Path> writableDirs = new HashSet<>(alwaysWritableDirs);
+ writableDirs.addAll(getWritableDirs(sandboxExecRoot, spawnEnvironment));
+
HardlinkedExecRoot hardlinkedExecRoot =
new HardlinkedExecRoot(execRoot, sandboxPath, sandboxExecRoot, errWriter);
ImmutableSet<PathFragment> outputs = SandboxHelpers.getOutputFiles(spawn);
@@ -209,37 +243,6 @@ public class DarwinSandboxedStrategy extends SandboxStrategy {
}
@Override
- protected ImmutableSet<Path> getWritableDirs(Path sandboxExecRoot, Map<String, String> env)
- throws IOException {
- ImmutableSet.Builder<Path> writableDirs = ImmutableSet.builder();
- writableDirs.addAll(super.getWritableDirs(sandboxExecRoot, env));
-
- FileSystem fs = sandboxExecRoot.getFileSystem();
- writableDirs.add(fs.getPath("/dev"));
-
- String sysTmpDir = System.getenv("TMPDIR");
- if (sysTmpDir != null) {
- writableDirs.add(fs.getPath(sysTmpDir));
- }
-
- writableDirs.add(fs.getPath("/tmp"));
-
- // ~/Library/Cache and ~/Library/Logs need to be writable (cf. issue #2231).
- Path homeDir = fs.getPath(System.getProperty("user.home"));
- writableDirs.add(homeDir.getRelative("Library/Cache"));
- writableDirs.add(homeDir.getRelative("Library/Logs"));
-
- // Other temporary directories from getconf.
- for (Path path : confPaths) {
- if (path.exists()) {
- writableDirs.add(path);
- }
- }
-
- return writableDirs.build();
- }
-
- @Override
public Map<PathFragment, Path> getMounts(Spawn spawn, ActionExecutionContext executionContext)
throws ExecException {
try {