Skip to content

Commit cefc0bb

Browse files
oioojBryan C. Mills
authored and
Bryan C. Mills
committed
cmd/go/internal/renameio: allow write file with the specified permissions
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 <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Bryan C. Mills <[email protected]>
1 parent 1e3ffb0 commit cefc0bb

File tree

6 files changed

+70
-12
lines changed

6 files changed

+70
-12
lines changed

src/cmd/go/internal/cache/cache.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ func (c *Cache) Trim() {
278278

279279
// Ignore errors from here: if we don't write the complete timestamp, the
280280
// cache will appear older than it is, and we'll trim it again next time.
281-
renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())))
281+
renameio.WriteFile(filepath.Join(c.dir, "trim.txt"), []byte(fmt.Sprintf("%d", now.Unix())), 0666)
282282
}
283283

284284
// trimSubdir trims a single cache subdirectory.

src/cmd/go/internal/modfetch/cache.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -488,7 +488,7 @@ func writeDiskCache(file string, data []byte) error {
488488
return err
489489
}
490490

491-
if err := renameio.WriteFile(file, data); err != nil {
491+
if err := renameio.WriteFile(file, data, 0666); err != nil {
492492
return err
493493
}
494494

@@ -550,7 +550,7 @@ func rewriteVersionList(dir string) {
550550
return
551551
}
552552

553-
if err := renameio.WriteFile(listFile, buf.Bytes()); err != nil {
553+
if err := renameio.WriteFile(listFile, buf.Bytes(), 0666); err != nil {
554554
base.Fatalf("go: failed to write version list: %v", err)
555555
}
556556
}

src/cmd/go/internal/modfetch/fetch.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ func downloadZip(mod module.Version, zipfile string) (err error) {
248248
}
249249
checkModSum(mod, hash)
250250

251-
if err := renameio.WriteFile(zipfile+"hash", []byte(hash)); err != nil {
251+
if err := renameio.WriteFile(zipfile+"hash", []byte(hash), 0666); err != nil {
252252
return err
253253
}
254254
if err := os.Rename(f.Name(), zipfile); err != nil {
@@ -565,7 +565,7 @@ func WriteGoSum() {
565565
}
566566
}
567567

568-
if err := renameio.WriteFile(GoSumFile, buf.Bytes()); err != nil {
568+
if err := renameio.WriteFile(GoSumFile, buf.Bytes(), 0666); err != nil {
569569
base.Fatalf("go: writing go.sum: %v", err)
570570
}
571571

src/cmd/go/internal/modload/init.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -715,7 +715,7 @@ func WriteGoMod() {
715715

716716
}
717717

718-
if err := renameio.WriteFile(file, new); err != nil {
718+
if err := renameio.WriteFile(file, new, 0666); err != nil {
719719
base.Fatalf("error writing go.mod: %v", err)
720720
}
721721
modFileData = new

src/cmd/go/internal/renameio/renameio.go

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ package renameio
88
import (
99
"bytes"
1010
"io"
11-
"io/ioutil"
11+
"math/rand"
1212
"os"
1313
"path/filepath"
14+
"strconv"
1415
"time"
1516
)
1617

17-
const patternSuffix = "*.tmp"
18+
const patternSuffix = ".tmp"
1819

1920
// Pattern returns a glob pattern that matches the unrenamed temporary files
2021
// created when writing to filename.
@@ -27,14 +28,14 @@ func Pattern(filename string) string {
2728
// final name.
2829
//
2930
// That ensures that the final location, if it exists, is always a complete file.
30-
func WriteFile(filename string, data []byte) (err error) {
31-
return WriteToFile(filename, bytes.NewReader(data))
31+
func WriteFile(filename string, data []byte, perm os.FileMode) (err error) {
32+
return WriteToFile(filename, bytes.NewReader(data), perm)
3233
}
3334

3435
// WriteToFile is a variant of WriteFile that accepts the data as an io.Reader
3536
// instead of a slice.
36-
func WriteToFile(filename string, data io.Reader) (err error) {
37-
f, err := ioutil.TempFile(filepath.Dir(filename), filepath.Base(filename)+patternSuffix)
37+
func WriteToFile(filename string, data io.Reader, perm os.FileMode) (err error) {
38+
f, err := tempFile(filepath.Dir(filename), filepath.Base(filename), perm)
3839
if err != nil {
3940
return err
4041
}
@@ -79,3 +80,16 @@ func WriteToFile(filename string, data io.Reader) (err error) {
7980
time.Sleep(5 * time.Millisecond)
8081
}
8182
}
83+
84+
// tempFile creates a new temporary file with given permission bits.
85+
func tempFile(dir, prefix string, perm os.FileMode) (f *os.File, err error) {
86+
for i := 0; i < 10000; i++ {
87+
name := filepath.Join(dir, prefix+strconv.Itoa(rand.Intn(1000000000))+patternSuffix)
88+
f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, perm)
89+
if os.IsExist(err) {
90+
continue
91+
}
92+
break
93+
}
94+
return
95+
}
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
// Copyright 2019 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// Package renameio writes files atomically by renaming temporary files.
6+
7+
//+build !nacl,!plan9,!windows,!js
8+
9+
package renameio
10+
11+
import (
12+
"io/ioutil"
13+
"os"
14+
"path/filepath"
15+
"syscall"
16+
"testing"
17+
)
18+
19+
func TestWriteFileModeAppliesUmask(t *testing.T) {
20+
dir, err := ioutil.TempDir("", "renameio")
21+
if err != nil {
22+
t.Fatalf("Failed to create temporary directory: %v", err)
23+
}
24+
25+
const mode = 0644
26+
const umask = 0007
27+
defer syscall.Umask(syscall.Umask(umask))
28+
29+
file := filepath.Join(dir, "testWrite")
30+
err = WriteFile(file, []byte("go-build"), mode)
31+
if err != nil {
32+
t.Fatalf("Failed to write file: %v", err)
33+
}
34+
defer os.RemoveAll(dir)
35+
36+
fi, err := os.Stat(file)
37+
if err != nil {
38+
t.Fatalf("Stat %q (looking for mode %#o): %s", file, mode, err)
39+
}
40+
41+
if fi.Mode()&os.ModePerm != 0640 {
42+
t.Errorf("Stat %q: mode %#o want %#o", file, fi.Mode()&os.ModePerm, 0640)
43+
}
44+
}

0 commit comments

Comments
 (0)