]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/go/internal/renameio: allow write file with the specified permissions
authorBaokun Lee <nototon@gmail.com>
Thu, 9 May 2019 03:24:30 +0000 (11:24 +0800)
committerBryan C. Mills <bcmills@google.com>
Wed, 15 May 2019 14:32:33 +0000 (14:32 +0000)
Now renameio package creates file use ioutil.TempFile, which calls
OpenFile with mode 0600, we should support creates a file with given
permission bits.

Fixes #31871

Change-Id: I0436e9f7081f2fce18bf9f3b14d55b02d4d995fb
Reviewed-on: https://go-review.googlesource.com/c/go/+/175958
Run-TryBot: Baokun Lee <nototon@gmail.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Bryan C. Mills <bcmills@google.com>
src/cmd/go/internal/cache/cache.go
src/cmd/go/internal/modfetch/cache.go
src/cmd/go/internal/modfetch/fetch.go
src/cmd/go/internal/modload/init.go
src/cmd/go/internal/renameio/renameio.go
src/cmd/go/internal/renameio/renameio_test.go [new file with mode: 0644]

index 3e386a08815d832d9a0698db65bac3c4ed9e84b3..c1d073806e31fb58b0290a7ca2f32f5efba5f149 100644 (file)
@@ -278,7 +278,7 @@ func (c *Cache) Trim() {
 
        // Ignore errors from here: if we don't write the complete timestamp, the
        // cache will appear older than it is, and we'll trim it again next time.
-       renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())))
+       renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666)
 }
 
 // trimSubdir trims a single cache subdirectory.
index 1ccd43dc2ae845d859f2c2d9447c00ed8003ca1a..f269c47f59892523d98b713424eef0fbda9ad318 100644 (file)
@@ -488,7 +488,7 @@ func writeDiskCache(file string, data []byte) error {
                return err
        }
 
-       if err := renameio.WriteFile(file, data); err != nil {
+       if err := renameio.WriteFile(file, data, 0666); err != nil {
                return err
        }
 
@@ -550,7 +550,7 @@ func rewriteVersionList(dir string) {
                return
        }
 
-       if err := renameio.WriteFile(listFile, buf.Bytes()); err != nil {
+       if err := renameio.WriteFile(listFile, buf.Bytes(), 0666); err != nil {
                base.Fatalf("go: failed to write version list: %v", err)
        }
 }
index 8f9e50da75a143c1bc52d96262a74c2e79695285..817f7657e2e84afd4815f69e5770afb90c4c53d1 100644 (file)
@@ -248,7 +248,7 @@ func downloadZip(mod module.Version, zipfile string) (err error) {
        }
        checkModSum(mod, hash)
 
-       if err := renameio.WriteFile(zipfile+"hash", []byte(hash)); err != nil {
+       if err := renameio.WriteFile(zipfile+"hash", []byte(hash), 0666); err != nil {
                return err
        }
        if err := os.Rename(f.Name(), zipfile); err != nil {
@@ -565,7 +565,7 @@ func WriteGoSum() {
                }
        }
 
-       if err := renameio.WriteFile(GoSumFile, buf.Bytes()); err != nil {
+       if err := renameio.WriteFile(GoSumFile, buf.Bytes(), 0666); err != nil {
                base.Fatalf("go: writing go.sum: %v", err)
        }
 
index c55f8e3760a84d82b2bba6231af3c93eff0acbcd..b51e411421c328973b9ec6e7b3cefa3fb2f575b7 100644 (file)
@@ -715,7 +715,7 @@ func WriteGoMod() {
 
        }
 
-       if err := renameio.WriteFile(file, new); err != nil {
+       if err := renameio.WriteFile(file, new, 0666); err != nil {
                base.Fatalf("error writing go.mod: %v", err)
        }
        modFileData = new
index 0bd40a544ad64a6f465a4da75b7ad5cee4297f6e..5fe5bb7dd42470e70c813311901422b8e6b580dc 100644 (file)
@@ -8,13 +8,14 @@ package renameio
 import (
        "bytes"
        "io"
-       "io/ioutil"
+       "math/rand"
        "os"
        "path/filepath"
+       "strconv"
        "time"
 )
 
-const patternSuffix = "*.tmp"
+const patternSuffix = ".tmp"
 
 // Pattern returns a glob pattern that matches the unrenamed temporary files
 // created when writing to filename.
@@ -27,14 +28,14 @@ func Pattern(filename string) string {
 // final name.
 //
 // That ensures that the final location, if it exists, is always a complete file.
-func WriteFile(filename string, data []byte) (err error) {
-       return WriteToFile(filename, bytes.NewReader(data))
+func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
+       return WriteToFile(filename, bytes.NewReader(data), perm)
 }
 
 // WriteToFile is a variant of WriteFile that accepts the data as an io.Reader
 // instead of a slice.
-func WriteToFile(filename string, data io.Reader) (err error) {
-       f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+patternSuffix)
+func WriteToFile(filename string, data io.Reader, perm os.FileMode) (err error) {
+       f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm)
        if err != nil {
                return err
        }
@@ -79,3 +80,16 @@ func WriteToFile(filename string, data io.Reader) (err error) {
                time.Sleep(5 * time.Millisecond)
        }
 }
+
+// tempFile creates a new temporary file with given permission bits.
+func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) {
+       for i := 0; i < 10000; i++ {
+               name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix)
+               f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
+               if os.IsExist(err) {
+                       continue
+               }
+               break
+       }
+       return
+}
diff --git a/src/cmd/go/internal/renameio/renameio_test.go b/src/cmd/go/internal/renameio/renameio_test.go
new file mode 100644 (file)
index 0000000..53f8798
--- /dev/null
@@ -0,0 +1,44 @@
+// Copyright 2019 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+// Package renameio writes files atomically by renaming temporary files.
+
+//+build !nacl,!plan9,!windows,!js
+
+package renameio
+
+import (
+       "io/ioutil"
+       "os"
+       "path/filepath"
+       "syscall"
+       "testing"
+)
+
+func TestWriteFileModeAppliesUmask(t *testing.T) {
+       dir, err := ioutil.TempDir("", "renameio")
+       if err != nil {
+               t.Fatalf("Failed to create temporary directory: %v", err)
+       }
+
+       const mode = 0644
+       const umask = 0007
+       defer syscall.Umask(syscall.Umask(umask))
+
+       file := filepath.Join(dir, "testWrite")
+       err = WriteFile(file, []byte("go-build"), mode)
+       if err != nil {
+               t.Fatalf("Failed to write file: %v", err)
+       }
+       defer os.RemoveAll(dir)
+
+       fi, err := os.Stat(file)
+       if err != nil {
+               t.Fatalf("Stat %q (looking for mode %#o): %s", file, mode, err)
+       }
+
+       if fi.Mode()&os.ModePerm != 0640 {
+               t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&os.ModePerm, 0640)
+       }
+}