github.com/megatontech/mynoteforgo@v0.0.0-20200507084910-5d0c6ea6e890/源码/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 "io" 13 "runtime" 14 "syscall" 15 ) 16 17 // fixLongPath is a noop on non-Windows platforms. 18 func fixLongPath(path string) string { 19 return path 20 } 21 22 func rename(oldname, newname string) error { 23 fi, err := Lstat(newname) 24 if err == nil && fi.IsDir() { 25 // There are two independent errors this function can return: 26 // one for a bad oldname, and one for a bad newname. 27 // At this point we've determined the newname is bad. 28 // But just in case oldname is also bad, prioritize returning 29 // the oldname error because that's what we did historically. 30 if _, err := Lstat(oldname); err != nil { 31 if pe, ok := err.(*PathError); ok { 32 err = pe.Err 33 } 34 return &LinkError{"rename", oldname, newname, err} 35 } 36 return &LinkError{"rename", oldname, newname, syscall.EEXIST} 37 } 38 err = syscall.Rename(oldname, newname) 39 if err != nil { 40 return &LinkError{"rename", oldname, newname, err} 41 } 42 return nil 43 } 44 45 // file is the real representation of *File. 46 // The extra level of indirection ensures that no clients of os 47 // can overwrite this data, which could cause the finalizer 48 // to close the wrong file descriptor. 49 type file struct { 50 pfd poll.FD 51 name string 52 dirinfo *dirInfo // nil unless directory being read 53 nonblock bool // whether we set nonblocking mode 54 stdoutOrErr bool // whether this is stdout or stderr 55 } 56 57 // Fd returns the integer Unix file descriptor referencing the open file. 58 // The file descriptor is valid only until f.Close is called or f is garbage collected. 59 // On Unix systems this will cause the SetDeadline methods to stop working. 60 func (f *File) Fd() uintptr { 61 if f == nil { 62 return ^(uintptr(0)) 63 } 64 65 // If we put the file descriptor into nonblocking mode, 66 // then set it to blocking mode before we return it, 67 // because historically we have always returned a descriptor 68 // opened in blocking mode. The File will continue to work, 69 // but any blocking operation will tie up a thread. 70 if f.nonblock { 71 f.pfd.SetBlocking() 72 } 73 74 return uintptr(f.pfd.Sysfd) 75 } 76 77 // NewFile returns a new File with the given file descriptor and 78 // name. The returned value will be nil if fd is not a valid file 79 // descriptor. On Unix systems, if the file descriptor is in 80 // non-blocking mode, NewFile will attempt to return a pollable File 81 // (one for which the SetDeadline methods work). 82 func NewFile(fd uintptr, name string) *File { 83 kind := kindNewFile 84 if nb, err := unix.IsNonblock(int(fd)); err == nil && nb { 85 kind = kindNonBlock 86 } 87 return newFile(fd, name, kind) 88 } 89 90 // newFileKind describes the kind of file to newFile. 91 type newFileKind int 92 93 const ( 94 kindNewFile newFileKind = iota 95 kindOpenFile 96 kindPipe 97 kindNonBlock 98 ) 99 100 // newFile is like NewFile, but if called from OpenFile or Pipe 101 // (as passed in the kind parameter) it tries to add the file to 102 // the runtime poller. 103 func newFile(fd uintptr, name string, kind newFileKind) *File { 104 fdi := int(fd) 105 if fdi < 0 { 106 return nil 107 } 108 f := &File{&file{ 109 pfd: poll.FD{ 110 Sysfd: fdi, 111 IsStream: true, 112 ZeroReadIsEOF: true, 113 }, 114 name: name, 115 stdoutOrErr: fdi == 1 || fdi == 2, 116 }} 117 118 pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock 119 120 // If the caller passed a non-blocking filedes (kindNonBlock), 121 // we assume they know what they are doing so we allow it to be 122 // used with kqueue. 123 if kind == kindOpenFile { 124 var st syscall.Stat_t 125 switch runtime.GOOS { 126 case "freebsd": 127 // On FreeBSD before 10.4 it used to crash the 128 // system unpredictably while running all.bash. 129 // When we stop supporting FreeBSD 10 we can merge 130 // this into the dragonfly/netbsd/openbsd case. 131 // Issue 27619. 132 pollable = false 133 134 case "dragonfly", "netbsd", "openbsd": 135 // Don't try to use kqueue with regular files on *BSDs. 136 // On FreeBSD a regular file is always 137 // reported as ready for writing. 138 // On Dragonfly, NetBSD and OpenBSD the fd is signaled 139 // only once as ready (both read and write). 140 // Issue 19093. 141 if err := syscall.Fstat(fdi, &st); err == nil && st.Mode&syscall.S_IFMT == syscall.S_IFREG { 142 pollable = false 143 } 144 145 case "darwin": 146 // In addition to the behavior described above for regular files, 147 // on Darwin, kqueue does not work properly with fifos: 148 // closing the last writer does not cause a kqueue event 149 // for any readers. See issue #24164. 150 if err := syscall.Fstat(fdi, &st); err == nil && (st.Mode&syscall.S_IFMT == syscall.S_IFIFO || st.Mode&syscall.S_IFMT == syscall.S_IFREG) { 151 pollable = false 152 } 153 } 154 } 155 156 if err := f.pfd.Init("file", pollable); err != nil { 157 // An error here indicates a failure to register 158 // with the netpoll system. That can happen for 159 // a file descriptor that is not supported by 160 // epoll/kqueue; for example, disk files on 161 // GNU/Linux systems. We assume that any real error 162 // will show up in later I/O. 163 } else if pollable { 164 // We successfully registered with netpoll, so put 165 // the file into nonblocking mode. 166 if err := syscall.SetNonblock(fdi, true); err == nil { 167 f.nonblock = true 168 } 169 } 170 171 runtime.SetFinalizer(f.file, (*file).close) 172 return f 173 } 174 175 // epipecheck raises SIGPIPE if we get an EPIPE error on standard 176 // output or standard error. See the SIGPIPE docs in os/signal, and 177 // issue 11845. 178 func epipecheck(file *File, e error) { 179 if e == syscall.EPIPE && file.stdoutOrErr { 180 sigpipe() 181 } 182 } 183 184 // DevNull is the name of the operating system's ``null device.'' 185 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL". 186 const DevNull = "/dev/null" 187 188 // openFileNolog is the Unix implementation of OpenFile. 189 // Changes here should be reflected in openFdAt, if relevant. 190 func openFileNolog(name string, flag int, perm FileMode) (*File, error) { 191 setSticky := false 192 if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 { 193 if _, err := Stat(name); IsNotExist(err) { 194 setSticky = true 195 } 196 } 197 198 var r int 199 for { 200 var e error 201 r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) 202 if e == nil { 203 break 204 } 205 206 // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause 207 // open(2) to be restarted for regular files. This is easy to reproduce on 208 // fuse file systems (see https://golang.org/issue/11180). 209 if runtime.GOOS == "darwin" && e == syscall.EINTR { 210 continue 211 } 212 213 return nil, &PathError{"open", name, e} 214 } 215 216 // open(2) itself won't handle the sticky bit on *BSD and Solaris 217 if setSticky { 218 setStickyBit(name) 219 } 220 221 // There's a race here with fork/exec, which we are 222 // content to live with. See ../syscall/exec_unix.go. 223 if !supportsCloseOnExec { 224 syscall.CloseOnExec(r) 225 } 226 227 return newFile(uintptr(r), name, kindOpenFile), nil 228 } 229 230 // Close closes the File, rendering it unusable for I/O. 231 // On files that support SetDeadline, any pending I/O operations will 232 // be canceled and return immediately with an error. 233 func (f *File) Close() error { 234 if f == nil { 235 return ErrInvalid 236 } 237 return f.file.close() 238 } 239 240 func (file *file) close() error { 241 if file == nil { 242 return syscall.EINVAL 243 } 244 if file.dirinfo != nil { 245 file.dirinfo.close() 246 } 247 var err error 248 if e := file.pfd.Close(); e != nil { 249 if e == poll.ErrFileClosing { 250 e = ErrClosed 251 } 252 err = &PathError{"close", file.name, e} 253 } 254 255 // no need for a finalizer anymore 256 runtime.SetFinalizer(file, nil) 257 return err 258 } 259 260 // read reads up to len(b) bytes from the File. 261 // It returns the number of bytes read and an error, if any. 262 func (f *File) read(b []byte) (n int, err error) { 263 n, err = f.pfd.Read(b) 264 runtime.KeepAlive(f) 265 return n, err 266 } 267 268 // pread reads len(b) bytes from the File starting at byte offset off. 269 // It returns the number of bytes read and the error, if any. 270 // EOF is signaled by a zero count with err set to nil. 271 func (f *File) pread(b []byte, off int64) (n int, err error) { 272 n, err = f.pfd.Pread(b, off) 273 runtime.KeepAlive(f) 274 return n, err 275 } 276 277 // write writes len(b) bytes to the File. 278 // It returns the number of bytes written and an error, if any. 279 func (f *File) write(b []byte) (n int, err error) { 280 n, err = f.pfd.Write(b) 281 runtime.KeepAlive(f) 282 return n, err 283 } 284 285 // pwrite writes len(b) bytes to the File starting at byte offset off. 286 // It returns the number of bytes written and an error, if any. 287 func (f *File) pwrite(b []byte, off int64) (n int, err error) { 288 n, err = f.pfd.Pwrite(b, off) 289 runtime.KeepAlive(f) 290 return n, err 291 } 292 293 // seek sets the offset for the next Read or Write on file to offset, interpreted 294 // according to whence: 0 means relative to the origin of the file, 1 means 295 // relative to the current offset, and 2 means relative to the end. 296 // It returns the new offset and an error, if any. 297 func (f *File) seek(offset int64, whence int) (ret int64, err error) { 298 ret, err = f.pfd.Seek(offset, whence) 299 runtime.KeepAlive(f) 300 return ret, err 301 } 302 303 // Truncate changes the size of the named file. 304 // If the file is a symbolic link, it changes the size of the link's target. 305 // If there is an error, it will be of type *PathError. 306 func Truncate(name string, size int64) error { 307 if e := syscall.Truncate(name, size); e != nil { 308 return &PathError{"truncate", name, e} 309 } 310 return nil 311 } 312 313 // Remove removes the named file or (empty) directory. 314 // If there is an error, it will be of type *PathError. 315 func Remove(name string) error { 316 // System call interface forces us to know 317 // whether name is a file or directory. 318 // Try both: it is cheaper on average than 319 // doing a Stat plus the right one. 320 e := syscall.Unlink(name) 321 if e == nil { 322 return nil 323 } 324 e1 := syscall.Rmdir(name) 325 if e1 == nil { 326 return nil 327 } 328 329 // Both failed: figure out which error to return. 330 // OS X and Linux differ on whether unlink(dir) 331 // returns EISDIR, so can't use that. However, 332 // both agree that rmdir(file) returns ENOTDIR, 333 // so we can use that to decide which error is real. 334 // Rmdir might also return ENOTDIR if given a bad 335 // file path, like /etc/passwd/foo, but in that case, 336 // both errors will be ENOTDIR, so it's okay to 337 // use the error from unlink. 338 if e1 != syscall.ENOTDIR { 339 e = e1 340 } 341 return &PathError{"remove", name, e} 342 } 343 344 func tempDir() string { 345 dir := Getenv("TMPDIR") 346 if dir == "" { 347 if runtime.GOOS == "android" { 348 dir = "/data/local/tmp" 349 } else { 350 dir = "/tmp" 351 } 352 } 353 return dir 354 } 355 356 // Link creates newname as a hard link to the oldname file. 357 // If there is an error, it will be of type *LinkError. 358 func Link(oldname, newname string) error { 359 e := syscall.Link(oldname, newname) 360 if e != nil { 361 return &LinkError{"link", oldname, newname, e} 362 } 363 return nil 364 } 365 366 // Symlink creates newname as a symbolic link to oldname. 367 // If there is an error, it will be of type *LinkError. 368 func Symlink(oldname, newname string) error { 369 e := syscall.Symlink(oldname, newname) 370 if e != nil { 371 return &LinkError{"symlink", oldname, newname, e} 372 } 373 return nil 374 } 375 376 func (f *File) readdir(n int) (fi []FileInfo, err error) { 377 dirname := f.name 378 if dirname == "" { 379 dirname = "." 380 } 381 names, err := f.Readdirnames(n) 382 fi = make([]FileInfo, 0, len(names)) 383 for _, filename := range names { 384 fip, lerr := lstat(dirname + "/" + filename) 385 if IsNotExist(lerr) { 386 // File disappeared between readdir + stat. 387 // Just treat it as if it didn't exist. 388 continue 389 } 390 if lerr != nil { 391 return fi, lerr 392 } 393 fi = append(fi, fip) 394 } 395 if len(fi) == 0 && err == nil && n > 0 { 396 // Per File.Readdir, the slice must be non-empty or err 397 // must be non-nil if n > 0. 398 err = io.EOF 399 } 400 return fi, err 401 }