github.com/richardwilkes/toolbox@v1.121.0/xio/fs/internal/temp.go (about) 1 // Copyright (c) 2016-2024 by Richard A. Wilkes. All rights reserved. 2 // 3 // This Source Code Form is subject to the terms of the Mozilla Public 4 // License, version 2.0. If a copy of the MPL was not distributed with 5 // this file, You can obtain one at http://mozilla.org/MPL/2.0/. 6 // 7 // This Source Code Form is "Incompatible With Secondary Licenses", as 8 // defined by the Mozilla Public License, version 2.0. 9 10 package internal 11 12 import ( 13 "errors" 14 "math" 15 "os" 16 "path/filepath" 17 "strconv" 18 "strings" 19 20 "github.com/richardwilkes/toolbox/xmath/rand" 21 ) 22 23 // CreateTemp is essentially the same as os.CreateTemp, except it allows you to specify the file mode of the newly 24 // created file. This is here solely because having it in the fs package would cause circular references. 25 func CreateTemp(dir, pattern string, perm os.FileMode) (*os.File, error) { 26 if dir == "" { 27 dir = os.TempDir() 28 } 29 for i := 0; i < len(pattern); i++ { 30 if os.IsPathSeparator(pattern[i]) { 31 return nil, &os.PathError{Op: "createtemp", Path: pattern, Err: errors.New("pattern contains path separator")} 32 } 33 } 34 var prefix, suffix string 35 if pos := strings.LastIndexByte(pattern, '*'); pos != -1 { 36 prefix, suffix = pattern[:pos], pattern[pos+1:] 37 } else { 38 prefix = pattern 39 } 40 if dir != "" && os.IsPathSeparator(dir[len(dir)-1]) { 41 prefix = dir + prefix 42 } else { 43 prefix = filepath.Join(dir, prefix) 44 } 45 try := 0 46 for { 47 f, err := os.OpenFile(prefix+strconv.Itoa(rand.NewCryptoRand().Intn(math.MaxInt))+suffix, 48 os.O_RDWR|os.O_CREATE|os.O_EXCL, perm) 49 if os.IsExist(err) { 50 try++ 51 if try < 1000 { 52 continue 53 } 54 return nil, &os.PathError{Op: "createtemp", Path: prefix + "*" + suffix, Err: os.ErrExist} 55 } 56 return f, err 57 } 58 }