Skip to content

Commit 42e8b9c

Browse files
author
Bryan C. Mills
committed
cmd/go/internal/modfetch: make directories read-only after renaming, not before
The call to os.Rename was failing on the darwin builders, despite having passed in the TryBots. (I tested this change by running 'go test cmd/go' manually on a darwin gomote.) This fixes the builder failures after CL 146382. Updates #26794 Fixes #29030 Change-Id: I3644773421789f65e56f183d077b4e4fd17b8325 Reviewed-on: https://go-review.googlesource.com/c/151798 Reviewed-by: Austin Clements <[email protected]> Run-TryBot: Austin Clements <[email protected]> TryBot-Result: Gobot Gobot <[email protected]>
1 parent 96a6bd4 commit 42e8b9c

File tree

2 files changed

+29
-18
lines changed

2 files changed

+29
-18
lines changed

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

+8-1
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,14 @@ func download(mod module.Version, dir string) (err error) {
120120
return err
121121
}
122122

123-
return os.Rename(tmpDir, dir)
123+
if err := os.Rename(tmpDir, dir); err != nil {
124+
return err
125+
}
126+
127+
// Make dir read-only only *after* renaming it.
128+
// os.Rename was observed to fail for read-only directories on macOS.
129+
makeDirsReadOnly(dir)
130+
return nil
124131
}
125132

126133
var downloadZipCache par.Cache

src/cmd/go/internal/modfetch/unzip.go

+21-17
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import (
1212
"os"
1313
"path"
1414
"path/filepath"
15-
"sort"
1615
"strings"
1716

1817
"cmd/go/internal/modfetch/codehost"
@@ -98,18 +97,12 @@ func Unzip(dir, zipfile, prefix string, maxSize int64) error {
9897
}
9998

10099
// Unzip, enforcing sizes checked earlier.
101-
dirs := map[string]bool{dir: true}
102100
for _, zf := range z.File {
103101
if zf.Name == prefix || strings.HasSuffix(zf.Name, "/") {
104102
continue
105103
}
106104
name := zf.Name[len(prefix):]
107105
dst := filepath.Join(dir, name)
108-
parent := filepath.Dir(dst)
109-
for parent != dir {
110-
dirs[parent] = true
111-
parent = filepath.Dir(parent)
112-
}
113106
if err := os.MkdirAll(filepath.Dir(dst), 0777); err != nil {
114107
return err
115108
}
@@ -137,19 +130,30 @@ func Unzip(dir, zipfile, prefix string, maxSize int64) error {
137130
}
138131
}
139132

140-
// Mark directories unwritable, best effort.
141-
var dirlist []string
142-
for dir := range dirs {
143-
dirlist = append(dirlist, dir)
133+
return nil
134+
}
135+
136+
// makeDirsReadOnly makes a best-effort attempt to remove write permissions for dir
137+
// and its transitive contents.
138+
func makeDirsReadOnly(dir string) {
139+
type pathMode struct {
140+
path string
141+
mode os.FileMode
144142
}
145-
sort.Strings(dirlist)
143+
var dirs []pathMode // in lexical order
144+
filepath.Walk(dir, func(path string, info os.FileInfo, err error) error {
145+
if err == nil && info.Mode()&0222 != 0 {
146+
if info.IsDir() {
147+
dirs = append(dirs, pathMode{path, info.Mode()})
148+
}
149+
}
150+
return nil
151+
})
152+
146153
// Run over list backward to chmod children before parents.
147-
for i := len(dirlist) - 1; i >= 0; i-- {
148-
// TODO(bcmills): Does this end up stomping on the umask of the cache directory?
149-
os.Chmod(dirlist[i], 0555)
154+
for i := len(dirs) - 1; i >= 0; i-- {
155+
os.Chmod(dirs[i].path, dirs[i].mode&^0222)
150156
}
151-
152-
return nil
153157
}
154158

155159
// RemoveAll removes a directory written by Download or Unzip, first applying

0 commit comments

Comments
 (0)