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