From c9a4b01f424d5c1b13ddf9eb900c664ea2bf7d98 Mon Sep 17 00:00:00 2001 From: "Bryan C. Mills" Date: Mon, 11 Nov 2019 12:41:01 -0500 Subject: [PATCH] cmd/go: in 'go build -o', allow the destination file to exist if it is empty This allows the target of 'go build' to be a filename constructed using ioutil.TempFile or similar, without racily deleting the file before rebuilding it. Updates #32407 Updates #28387 Change-Id: I4c5072830a02b93f0c4186b50bffa9de00257afe Reviewed-on: https://go-review.googlesource.com/c/go/+/206477 Run-TryBot: Bryan C. Mills Reviewed-by: Jay Conrod --- src/cmd/go/internal/work/exec.go | 4 ++-- src/cmd/go/testdata/script/test_compile_tempfile.txt | 11 +++++++++++ 2 files changed, 13 insertions(+), 2 deletions(-) create mode 100644 src/cmd/go/testdata/script/test_compile_tempfile.txt diff --git a/src/cmd/go/internal/work/exec.go b/src/cmd/go/internal/work/exec.go index a50de513f5..c8849b49fa 100644 --- a/src/cmd/go/internal/work/exec.go +++ b/src/cmd/go/internal/work/exec.go @@ -1610,12 +1610,12 @@ func (b *Builder) copyFile(dst, src string, perm os.FileMode, force bool) error // Be careful about removing/overwriting dst. // Do not remove/overwrite if dst exists and is a directory - // or a non-object file. + // or a non-empty non-object file. if fi, err := os.Stat(dst); err == nil { if fi.IsDir() { return fmt.Errorf("build output %q already exists and is a directory", dst) } - if !force && fi.Mode().IsRegular() && !isObject(dst) { + if !force && fi.Mode().IsRegular() && fi.Size() != 0 && !isObject(dst) { return fmt.Errorf("build output %q already exists and is not an object file", dst) } } diff --git a/src/cmd/go/testdata/script/test_compile_tempfile.txt b/src/cmd/go/testdata/script/test_compile_tempfile.txt new file mode 100644 index 0000000000..912410814f --- /dev/null +++ b/src/cmd/go/testdata/script/test_compile_tempfile.txt @@ -0,0 +1,11 @@ +[short] skip + +# Ensure that the target of 'go build -o' can be an existing, empty file so that +# its name can be reserved using ioutil.TempFile or the 'mktemp` command. + +go build -o empty-file$GOEXE main.go + +-- main.go -- +package main +func main() {} +-- empty-file$GOEXE -- -- 2.50.0