package fileops import ( "crypto/rand" "encoding/hex" "fmt" "os" "path/filepath" "strings" ) // createPrivateTemp follows CreateTemp's pattern syntax while installing native // private permissions at creation, rather than inheriting a shared Windows DACL. func createPrivateTemp(dir, pattern string) (*os.File, error) { if pattern != "" && filepath.Base(pattern) != pattern { return nil, fmt.Errorf("temporary pattern contains a path separator: %s", pattern) } if dir == "" { dir = os.TempDir() } prefix, suffix := pattern, "" if index := strings.LastIndexByte(pattern, '*'); index >= 0 { prefix, suffix = pattern[:index], pattern[index+1:] } for attempt := 0; attempt < 10; attempt++ { var nonce [16]byte if _, err := rand.Read(nonce[:]); err != nil { return nil, err } path := filepath.Join(dir, prefix+hex.EncodeToString(nonce[:])+suffix) file, err := CreatePrivateFile(path) if os.IsExist(err) { continue } return file, err } return nil, fmt.Errorf("could not reserve a unique private file") }