Source file
src/os/file_unix.go
Documentation: os
1
2
3
4
5
6
7 package os
8
9 import (
10 "internal/poll"
11 "runtime"
12 "syscall"
13 )
14
15
16 func fixLongPath(path string) string {
17 return path
18 }
19
20 func rename(oldname, newname string) error {
21 fi, err := Lstat(newname)
22 if err == nil && fi.IsDir() {
23
24
25
26
27
28 if _, err := Lstat(oldname); err != nil {
29 if pe, ok := err.(*PathError); ok {
30 err = pe.Err
31 }
32 return &LinkError{"rename", oldname, newname, err}
33 }
34 return &LinkError{"rename", oldname, newname, syscall.EEXIST}
35 }
36 err = syscall.Rename(oldname, newname)
37 if err != nil {
38 return &LinkError{"rename", oldname, newname, err}
39 }
40 return nil
41 }
42
43
44
45
46
47 type file struct {
48 pfd poll.FD
49 name string
50 dirinfo *dirInfo
51 nonblock bool
52 stdoutOrErr bool
53 }
54
55
56
57
58 func (f *File) Fd() uintptr {
59 if f == nil {
60 return ^(uintptr(0))
61 }
62
63
64
65
66
67
68 if f.nonblock {
69 f.pfd.SetBlocking()
70 }
71
72 return uintptr(f.pfd.Sysfd)
73 }
74
75
76
77
78 func NewFile(fd uintptr, name string) *File {
79 return newFile(fd, name, kindNewFile)
80 }
81
82
83 type newFileKind int
84
85 const (
86 kindNewFile newFileKind = iota
87 kindOpenFile
88 kindPipe
89 )
90
91
92
93
94 func newFile(fd uintptr, name string, kind newFileKind) *File {
95 fdi := int(fd)
96 if fdi < 0 {
97 return nil
98 }
99 f := &File{&file{
100 pfd: poll.FD{
101 Sysfd: fdi,
102 IsStream: true,
103 ZeroReadIsEOF: true,
104 },
105 name: name,
106 stdoutOrErr: fdi == 1 || fdi == 2,
107 }}
108
109
110
111
112 if runtime.GOOS == "freebsd" && kind == kindOpenFile {
113 kind = kindNewFile
114 }
115
116 pollable := kind == kindOpenFile || kind == kindPipe
117 if err := f.pfd.Init("file", pollable); err != nil {
118
119
120
121
122
123
124 } else if pollable {
125
126
127 if err := syscall.SetNonblock(fdi, true); err == nil {
128 f.nonblock = true
129 }
130 }
131
132 runtime.SetFinalizer(f.file, (*file).close)
133 return f
134 }
135
136
137 type dirInfo struct {
138 buf []byte
139 nbuf int
140 bufp int
141 }
142
143
144
145
146 func epipecheck(file *File, e error) {
147 if e == syscall.EPIPE && file.stdoutOrErr {
148 sigpipe()
149 }
150 }
151
152
153
154 const DevNull = "/dev/null"
155
156
157 func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
158 chmod := false
159 if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
160 if _, err := Stat(name); IsNotExist(err) {
161 chmod = true
162 }
163 }
164
165 var r int
166 for {
167 var e error
168 r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
169 if e == nil {
170 break
171 }
172
173
174
175
176 if runtime.GOOS == "darwin" && e == syscall.EINTR {
177 continue
178 }
179
180 return nil, &PathError{"open", name, e}
181 }
182
183
184 if chmod {
185 Chmod(name, perm)
186 }
187
188
189
190 if !supportsCloseOnExec {
191 syscall.CloseOnExec(r)
192 }
193
194 return newFile(uintptr(r), name, kindOpenFile), nil
195 }
196
197
198
199 func (f *File) Close() error {
200 if f == nil {
201 return ErrInvalid
202 }
203 return f.file.close()
204 }
205
206 func (file *file) close() error {
207 if file == nil {
208 return syscall.EINVAL
209 }
210 var err error
211 if e := file.pfd.Close(); e != nil {
212 if e == poll.ErrFileClosing {
213 e = ErrClosed
214 }
215 err = &PathError{"close", file.name, e}
216 }
217
218
219 runtime.SetFinalizer(file, nil)
220 return err
221 }
222
223
224
225 func (f *File) read(b []byte) (n int, err error) {
226 n, err = f.pfd.Read(b)
227 runtime.KeepAlive(f)
228 return n, err
229 }
230
231
232
233
234 func (f *File) pread(b []byte, off int64) (n int, err error) {
235 n, err = f.pfd.Pread(b, off)
236 runtime.KeepAlive(f)
237 return n, err
238 }
239
240
241
242 func (f *File) write(b []byte) (n int, err error) {
243 n, err = f.pfd.Write(b)
244 runtime.KeepAlive(f)
245 return n, err
246 }
247
248
249
250 func (f *File) pwrite(b []byte, off int64) (n int, err error) {
251 n, err = f.pfd.Pwrite(b, off)
252 runtime.KeepAlive(f)
253 return n, err
254 }
255
256
257
258
259
260 func (f *File) seek(offset int64, whence int) (ret int64, err error) {
261 ret, err = f.pfd.Seek(offset, whence)
262 runtime.KeepAlive(f)
263 return ret, err
264 }
265
266
267
268
269 func Truncate(name string, size int64) error {
270 if e := syscall.Truncate(name, size); e != nil {
271 return &PathError{"truncate", name, e}
272 }
273 return nil
274 }
275
276
277
278 func Remove(name string) error {
279
280
281
282
283 e := syscall.Unlink(name)
284 if e == nil {
285 return nil
286 }
287 e1 := syscall.Rmdir(name)
288 if e1 == nil {
289 return nil
290 }
291
292
293
294
295
296
297
298
299
300
301 if e1 != syscall.ENOTDIR {
302 e = e1
303 }
304 return &PathError{"remove", name, e}
305 }
306
307 func tempDir() string {
308 dir := Getenv("TMPDIR")
309 if dir == "" {
310 if runtime.GOOS == "android" {
311 dir = "/data/local/tmp"
312 } else {
313 dir = "/tmp"
314 }
315 }
316 return dir
317 }
318
319
320
321 func Link(oldname, newname string) error {
322 e := syscall.Link(oldname, newname)
323 if e != nil {
324 return &LinkError{"link", oldname, newname, e}
325 }
326 return nil
327 }
328
329
330
331 func Symlink(oldname, newname string) error {
332 e := syscall.Symlink(oldname, newname)
333 if e != nil {
334 return &LinkError{"symlink", oldname, newname, e}
335 }
336 return nil
337 }
338
View as plain text