github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/os/file_unix.go (about) 1 // Copyright 2009 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build aix darwin dragonfly freebsd js,wasm linux nacl netbsd openbsd solaris 6 7 package os 8 9 import ( 10 "internal/poll" 11 "internal/syscall/unix" 12 "runtime" 13 "syscall" 14 ) 15 16 // fixLongPath is a noop on non-Windows platforms. 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 // There are two independent errors this function can return: 25 // one for a bad oldname, and one for a bad newname. 26 // At this point we've determined the newname is bad. 27 // But just in case oldname is also bad, prioritize returning 28 // the oldname error because that's what we did historically. 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 // file is the real representation of *File. 45 // The extra level of indirection ensures that no clients of os 46 // can overwrite this data, which could cause the finalizer 47 // to close the wrong file descriptor. 48 type file struct { 49 pfd poll.FD 50 name string 51 dirinfo *dirInfo // nil unless directory being read 52 nonblock bool // whether we set nonblocking mode 53 stdoutOrErr bool // whether this is stdout or stderr 54 } 55 56 // Fd returns the integer Unix file descriptor referencing the open file. 57 // The file descriptor is valid only until f.Close is called or f is garbage collected. 58 // On Unix systems this will cause the SetDeadline methods to stop working. 59 func (f *File) Fd() uintptr { 60 if f == nil { 61 return ^(uintptr(0)) 62 } 63 64 // If we put the file descriptor into nonblocking mode, 65 // then set it to blocking mode before we return it, 66 // because historically we have always returned a descriptor 67 // opened in blocking mode. The File will continue to work, 68 // but any blocking operation will tie up a thread. 69 if f.nonblock { 70 f.pfd.SetBlocking() 71 } 72 73 return uintptr(f.pfd.Sysfd) 74 } 75 76 // NewFile returns a new File with the given file descriptor and 77 // name. The returned value will be nil if fd is not a valid file 78 // descriptor. On Unix systems, if the file descriptor is in 79 // non-blocking mode, NewFile will attempt to return a pollable File 80 // (one for which the SetDeadline methods work). 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 // newFileKind describes the kind of file to newFile. 90 type newFileKind int 91 92 const ( 93 kindNewFile newFileKind = iota 94 kindOpenFile 95 kindPipe 96 kindNonBlock 97 ) 98 99 // newFile is like NewFile, but if called from OpenFile or Pipe 100 // (as passed in the kind parameter) it tries to add the file to 101 // the runtime poller. 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 // Don't try to use kqueue with regular files on FreeBSD. 120 // It crashes the system unpredictably while running all.bash. 121 // Issue 19093. 122 // If the caller passed a non-blocking filedes (kindNonBlock), 123 // we assume they know what they are doing so we allow it to be 124 // used with kqueue. 125 if runtime.GOOS == "freebsd" && kind == kindOpenFile { 126 pollable = false 127 } 128 129 // On Darwin, kqueue does not work properly with fifos: 130 // closing the last writer does not cause a kqueue event 131 // for any readers. See issue #24164. 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 // An error here indicates a failure to register 141 // with the netpoll system. That can happen for 142 // a file descriptor that is not supported by 143 // epoll/kqueue; for example, disk files on 144 // GNU/Linux systems. We assume that any real error 145 // will show up in later I/O. 146 } else if pollable { 147 // We successfully registered with netpoll, so put 148 // the file into nonblocking mode. 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 // Auxiliary information if the File describes a directory 159 type dirInfo struct { 160 buf []byte // buffer for directory I/O 161 nbuf int // length of buf; return value from Getdirentries 162 bufp int // location of next record in buf. 163 } 164 165 // epipecheck raises SIGPIPE if we get an EPIPE error on standard 166 // output or standard error. See the SIGPIPE docs in os/signal, and 167 // issue 11845. 168 func epipecheck(file *File, e error) { 169 if e == syscall.EPIPE && file.stdoutOrErr { 170 sigpipe() 171 } 172 } 173 174 // DevNull is the name of the operating system's ``null device.'' 175 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL". 176 const DevNull = "/dev/null" 177 178 // openFileNolog is the Unix implementation of OpenFile. 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 // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause 196 // open(2) to be restarted for regular files. This is easy to reproduce on 197 // fuse file systems (see https://golang.org/issue/11180). 198 if runtime.GOOS == "darwin" && e == syscall.EINTR { 199 continue 200 } 201 202 return nil, &PathError{"open", name, e} 203 } 204 205 // open(2) itself won't handle the sticky bit on *BSD and Solaris 206 if setSticky { 207 setStickyBit(name) 208 } 209 210 // There's a race here with fork/exec, which we are 211 // content to live with. See ../syscall/exec_unix.go. 212 if !supportsCloseOnExec { 213 syscall.CloseOnExec(r) 214 } 215 216 return newFile(uintptr(r), name, kindOpenFile), nil 217 } 218 219 // Close closes the File, rendering it unusable for I/O. 220 // On files that support SetDeadline, any pending I/O operations will 221 // be canceled and return immediately with an error. 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 // no need for a finalizer anymore 242 runtime.SetFinalizer(file, nil) 243 return err 244 } 245 246 // read reads up to len(b) bytes from the File. 247 // It returns the number of bytes read and an error, if any. 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 // pread reads len(b) bytes from the File starting at byte offset off. 255 // It returns the number of bytes read and the error, if any. 256 // EOF is signaled by a zero count with err set to nil. 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 // write writes len(b) bytes to the File. 264 // It returns the number of bytes written and an error, if any. 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 // pwrite writes len(b) bytes to the File starting at byte offset off. 272 // It returns the number of bytes written and an error, if any. 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 // seek sets the offset for the next Read or Write on file to offset, interpreted 280 // according to whence: 0 means relative to the origin of the file, 1 means 281 // relative to the current offset, and 2 means relative to the end. 282 // It returns the new offset and an error, if any. 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 // Truncate changes the size of the named file. 290 // If the file is a symbolic link, it changes the size of the link's target. 291 // If there is an error, it will be of type *PathError. 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 // Remove removes the named file or (empty) directory. 300 // If there is an error, it will be of type *PathError. 301 func Remove(name string) error { 302 // System call interface forces us to know 303 // whether name is a file or directory. 304 // Try both: it is cheaper on average than 305 // doing a Stat plus the right one. 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 // Both failed: figure out which error to return. 316 // OS X and Linux differ on whether unlink(dir) 317 // returns EISDIR, so can't use that. However, 318 // both agree that rmdir(file) returns ENOTDIR, 319 // so we can use that to decide which error is real. 320 // Rmdir might also return ENOTDIR if given a bad 321 // file path, like /etc/passwd/foo, but in that case, 322 // both errors will be ENOTDIR, so it's okay to 323 // use the error from unlink. 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 // Link creates newname as a hard link to the oldname file. 343 // If there is an error, it will be of type *LinkError. 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 // Symlink creates newname as a symbolic link to oldname. 353 // If there is an error, it will be of type *LinkError. 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 }