Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit dd952905 authored by Cole Faust's avatar Cole Faust
Browse files

Handle symlinks in sbox

Previously, sbox would follow the symlink and copy the symlink's target
into the sbox, instead of the symlink itself.

camera-its is a genrule that zips up a folder that includes a symlink,
so we want the symlink to still be there instead of a copy of the file
it points to.

Bug: 307824623
Test: ./build/soong/tests/genrule_sandbox_test.py camera-its
Change-Id: Ib81f6fd6745ec2c58580082c73e33760d5051f5e
parent 74656ccf
Loading
Loading
Loading
Loading
+23 −2
Original line number Diff line number Diff line
@@ -22,6 +22,7 @@ import (
	"flag"
	"fmt"
	"io"
	"io/fs"
	"io/ioutil"
	"os"
	"os/exec"
@@ -478,7 +479,8 @@ func copyFiles(copies []*sbox_proto.Copy, fromDir, toDir string, exists existsTy
// copyOneFile copies a file and its permissions.  If forceExecutable is true it adds u+x to the
// permissions.  If exists is allowFromNotExists it returns nil if the from path doesn't exist.
// If write is onlyWriteIfChanged then the output file is compared to the input file and not written to
// if it is the same, avoiding updating the timestamp.
// if it is the same, avoiding updating the timestamp. If from is a symlink, the symlink itself
// will be copied, instead of what it points to.
func copyOneFile(from string, to string, forceExecutable bool, exists existsType,
	write writeType) error {
	err := os.MkdirAll(filepath.Dir(to), 0777)
@@ -486,7 +488,7 @@ func copyOneFile(from string, to string, forceExecutable bool, exists existsType
		return err
	}

	stat, err := os.Stat(from)
	stat, err := os.Lstat(from)
	if err != nil {
		if os.IsNotExist(err) && exists == allowFromNotExists {
			return nil
@@ -494,6 +496,25 @@ func copyOneFile(from string, to string, forceExecutable bool, exists existsType
		return err
	}

	if stat.Mode()&fs.ModeSymlink != 0 {
		linkTarget, err := os.Readlink(from)
		if err != nil {
			return err
		}
		if write == onlyWriteIfChanged {
			toLinkTarget, err := os.Readlink(to)
			if err == nil && toLinkTarget == linkTarget {
				return nil
			}
		}
		err = os.Remove(to)
		if err != nil && !os.IsNotExist(err) {
			return err
		}

		return os.Symlink(linkTarget, to)
	}

	perm := stat.Mode()
	if forceExecutable {
		perm = perm | 0100 // u+x