From 14a2362183d15cc8e618c80f5ea6f013997b8924 Mon Sep 17 00:00:00 2001 From: Cole Faust Date: Fri, 8 Dec 2023 11:09:31 -0800 Subject: [PATCH] Reapply "Handle symlinks in sbox" This reverts commit 69b5a5f0bfbd0b154f5bec18c1782783b7d339a3. Bug: 307824623 Test: Presubmits Change-Id: Id7dd1518ae6b04232c48c0aa138cad2c59b228c3 --- cmd/sbox/sbox.go | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cmd/sbox/sbox.go b/cmd/sbox/sbox.go index 3364f503f..e69a93067 100644 --- a/cmd/sbox/sbox.go +++ b/cmd/sbox/sbox.go @@ -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