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