From b078f175bb3d0de54df4b2ff1497ce19f9583fce Mon Sep 17 00:00:00 2001 From: Caleb Brown Date: Sat, 17 Sep 2022 05:39:57 +1000 Subject: [PATCH] Add a custom createTemp function that uses consistent file permissions. (#3166) Signed-off-by: Caleb Brown --- blob/fileblob/fileblob.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/blob/fileblob/fileblob.go b/blob/fileblob/fileblob.go index 8587017c50..3fc7ac281a 100644 --- a/blob/fileblob/fileblob.go +++ b/blob/fileblob/fileblob.go @@ -642,6 +642,29 @@ func (r *reader) As(i interface{}) bool { return true } +func createTemp(path string) (*os.File, error) { + // Use a custom createTemp function rather than os.CreateTemp() as + // os.CreateTemp() sets the permissions of the tempfile to 0600, rather than + // 0666, making it inconsistent with the directories and attribute files. + try := 0 + for { + // Append the current time with nanosecond precision and .tmp to the + // path. If the file already exists try again. Nanosecond changes enough + // between each iteration to make a conflict unlikely. Using the full + // time lowers the chance of a collision with a file using a similar + // pattern, but has undefined behavior after the year 2262. + name := path + "." + strconv.FormatInt(time.Now().UnixNano(), 16) + ".tmp" + f, err := os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0666) + if os.IsExist(err) { + if try++; try < 10000 { + continue + } + return nil, &os.PathError{Op: "createtemp", Path: path + ".*.tmp", Err: os.ErrExist} + } + return f, err + } +} + // NewTypedWriter implements driver.NewTypedWriter. func (b *bucket) NewTypedWriter(ctx context.Context, key string, contentType string, opts *driver.WriterOptions) (driver.Writer, error) { path, err := b.path(key) @@ -651,7 +674,7 @@ func (b *bucket) NewTypedWriter(ctx context.Context, key string, contentType str if err := os.MkdirAll(filepath.Dir(path), os.FileMode(0777)); err != nil { return nil, err } - f, err := ioutil.TempFile(filepath.Dir(path), "fileblob") + f, err := createTemp(path) if err != nil { return nil, err }