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