Source file
src/os/tempfile.go
1
2
3
4
5 package os
6
7 import (
8 "errors"
9 "internal/bytealg"
10 "internal/itoa"
11 _ "unsafe"
12 )
13
14
15
16
17
18
19
20 func runtime_rand() uint64
21
22 func nextRandom() string {
23 return itoa.Uitoa(uint(uint32(runtime_rand())))
24 }
25
26
27
28
29
30
31
32
33
34
35 func CreateTemp(dir, pattern string) (*File, error) {
36 if dir == "" {
37 dir = TempDir()
38 }
39
40 prefix, suffix, err := prefixAndSuffix(pattern)
41 if err != nil {
42 return nil, &PathError{Op: "createtemp", Path: pattern, Err: err}
43 }
44 prefix = joinPath(dir, prefix)
45
46 try := 0
47 for {
48 name := prefix + nextRandom() + suffix
49 f, err := OpenFile(name, O_RDWR|O_CREATE|O_EXCL, 0600)
50 if IsExist(err) {
51 if try++; try < 10000 {
52 continue
53 }
54 return nil, &PathError{Op: "createtemp", Path: prefix + "*" + suffix, Err: ErrExist}
55 }
56 return f, err
57 }
58 }
59
60 var errPatternHasSeparator = errors.New("pattern contains path separator")
61
62
63
64 func prefixAndSuffix(pattern string) (prefix, suffix string, err error) {
65 for i := 0; i < len(pattern); i++ {
66 if IsPathSeparator(pattern[i]) {
67 return "", "", errPatternHasSeparator
68 }
69 }
70 if pos := bytealg.LastIndexByteString(pattern, '*'); pos != -1 {
71 prefix, suffix = pattern[:pos], pattern[pos+1:]
72 } else {
73 prefix = pattern
74 }
75 return prefix, suffix, nil
76 }
77
78
79
80
81
82
83
84
85
86 func MkdirTemp(dir, pattern string) (string, error) {
87 if dir == "" {
88 dir = TempDir()
89 }
90
91 prefix, suffix, err := prefixAndSuffix(pattern)
92 if err != nil {
93 return "", &PathError{Op: "mkdirtemp", Path: pattern, Err: err}
94 }
95 prefix = joinPath(dir, prefix)
96
97 try := 0
98 for {
99 name := prefix + nextRandom() + suffix
100 err := Mkdir(name, 0700)
101 if err == nil {
102 return name, nil
103 }
104 if IsExist(err) {
105 if try++; try < 10000 {
106 continue
107 }
108 return "", &PathError{Op: "mkdirtemp", Path: dir + string(PathSeparator) + prefix + "*" + suffix, Err: ErrExist}
109 }
110 if IsNotExist(err) {
111 if _, err := Stat(dir); IsNotExist(err) {
112 return "", err
113 }
114 }
115 return "", err
116 }
117 }
118
119 func joinPath(dir, name string) string {
120 if len(dir) > 0 && IsPathSeparator(dir[len(dir)-1]) {
121 return dir + name
122 }
123 return dir + string(PathSeparator) + name
124 }
125
View as plain text