github.com/ccccaoqing/test@v0.0.0-20220510085219-3985d23445c0/src/io/ioutil/tempfile.go (about) 1 // Copyright 2010 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 ioutil 6 7 import ( 8 "os" 9 "path/filepath" 10 "strconv" 11 "sync" 12 "time" 13 ) 14 15 // Random number state. 16 // We generate random temporary file names so that there's a good 17 // chance the file doesn't exist yet - keeps the number of tries in 18 // TempFile to a minimum. 19 var rand uint32 20 var randmu sync.Mutex 21 22 func reseed() uint32 { 23 return uint32(time.Now().UnixNano() + int64(os.Getpid())) 24 } 25 26 func nextSuffix() string { 27 randmu.Lock() 28 r := rand 29 if r == 0 { 30 r = reseed() 31 } 32 r = r*1664525 + 1013904223 // constants from Numerical Recipes 33 rand = r 34 randmu.Unlock() 35 return strconv.Itoa(int(1e9 + r%1e9))[1:] 36 } 37 38 // TempFile creates a new temporary file in the directory dir 39 // with a name beginning with prefix, opens the file for reading 40 // and writing, and returns the resulting *os.File. 41 // If dir is the empty string, TempFile uses the default directory 42 // for temporary files (see os.TempDir). 43 // Multiple programs calling TempFile simultaneously 44 // will not choose the same file. The caller can use f.Name() 45 // to find the pathname of the file. It is the caller's responsibility 46 // to remove the file when no longer needed. 47 func TempFile(dir, prefix string) (f *os.File, err error) { 48 if dir == "" { 49 dir = os.TempDir() 50 } 51 52 nconflict := 0 53 for i := 0; i < 10000; i++ { 54 name := filepath.Join(dir, prefix+nextSuffix()) 55 f, err = os.OpenFile(name, os.O_RDWR|os.O_CREATE|os.O_EXCL, 0600) 56 if os.IsExist(err) { 57 if nconflict++; nconflict > 10 { 58 rand = reseed() 59 } 60 continue 61 } 62 break 63 } 64 return 65 } 66 67 // TempDir creates a new temporary directory in the directory dir 68 // with a name beginning with prefix and returns the path of the 69 // new directory. If dir is the empty string, TempDir uses the 70 // default directory for temporary files (see os.TempDir). 71 // Multiple programs calling TempDir simultaneously 72 // will not choose the same directory. It is the caller's responsibility 73 // to remove the directory when no longer needed. 74 func TempDir(dir, prefix string) (name string, err error) { 75 if dir == "" { 76 dir = os.TempDir() 77 } 78 79 nconflict := 0 80 for i := 0; i < 10000; i++ { 81 try := filepath.Join(dir, prefix+nextSuffix()) 82 err = os.Mkdir(try, 0700) 83 if os.IsExist(err) { 84 if nconflict++; nconflict > 10 { 85 rand = reseed() 86 } 87 continue 88 } 89 if err == nil { 90 name = try 91 } 92 break 93 } 94 return 95 }