Fix sbox in chdir mode

When running commands in chdir mode sbox needs to translate the
directory placeholders to paths relative to the sandbox directory
instead of relative to the top of the source tree.

Also translate relative PATH entries into absolute paths so they
are still valid when the current directory is changed.

Bug: 182612695
Test: manual
Change-Id: Idcbe20466888909d423d62788bc9c35f4e03b398
diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go
index f8919a4..f47c601 100644
--- a/cmd/sbox/sbox.go
+++ b/cmd/sbox/sbox.go
@@ -229,13 +229,18 @@
 		return "", err
 	}
 
+	pathToTempDirInSbox := tempDir
+	if command.GetChdir() {
+		pathToTempDirInSbox = "."
+	}
+
 	if strings.Contains(rawCommand, depFilePlaceholder) {
-		depFile = filepath.Join(tempDir, "deps.d")
+		depFile = filepath.Join(pathToTempDirInSbox, "deps.d")
 		rawCommand = strings.Replace(rawCommand, depFilePlaceholder, depFile, -1)
 	}
 
 	if strings.Contains(rawCommand, sandboxDirPlaceholder) {
-		rawCommand = strings.Replace(rawCommand, sandboxDirPlaceholder, tempDir, -1)
+		rawCommand = strings.Replace(rawCommand, sandboxDirPlaceholder, pathToTempDirInSbox, -1)
 	}
 
 	// Emulate ninja's behavior of creating the directories for any output files before
@@ -254,6 +259,15 @@
 
 	if command.GetChdir() {
 		cmd.Dir = tempDir
+		path := os.Getenv("PATH")
+		absPath, err := makeAbsPathEnv(path)
+		if err != nil {
+			return "", err
+		}
+		err = os.Setenv("PATH", absPath)
+		if err != nil {
+			return "", fmt.Errorf("Failed to update PATH: %w", err)
+		}
 	}
 	err = cmd.Run()
 
@@ -466,3 +480,17 @@
 	}
 	return filepath.Join(dir, file)
 }
+
+func makeAbsPathEnv(pathEnv string) (string, error) {
+	pathEnvElements := filepath.SplitList(pathEnv)
+	for i, p := range pathEnvElements {
+		if !filepath.IsAbs(p) {
+			absPath, err := filepath.Abs(p)
+			if err != nil {
+				return "", fmt.Errorf("failed to make PATH entry %q absolute: %w", p, err)
+			}
+			pathEnvElements[i] = absPath
+		}
+	}
+	return strings.Join(pathEnvElements, string(filepath.ListSeparator)), nil
+}