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