github.com/rakyll/go@v0.0.0-20170216000551-64c02460d703/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 darwin dragonfly freebsd linux nacl netbsd openbsd solaris 6 7 package os 8 9 import ( 10 "internal/poll" 11 "runtime" 12 "syscall" 13 ) 14 15 // fixLongPath is a noop on non-Windows platforms. 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 return &LinkError{"rename", oldname, newname, syscall.EEXIST} 24 } 25 e := syscall.Rename(oldname, newname) 26 if e != nil { 27 return &LinkError{"rename", oldname, newname, e} 28 } 29 return nil 30 } 31 32 // file is the real representation of *File. 33 // The extra level of indirection ensures that no clients of os 34 // can overwrite this data, which could cause the finalizer 35 // to close the wrong file descriptor. 36 type file struct { 37 pfd poll.FD 38 name string 39 dirinfo *dirInfo // nil unless directory being read 40 nonblock bool // whether we set nonblocking mode 41 } 42 43 // Fd returns the integer Unix file descriptor referencing the open file. 44 // The file descriptor is valid only until f.Close is called or f is garbage collected. 45 func (f *File) Fd() uintptr { 46 if f == nil { 47 return ^(uintptr(0)) 48 } 49 50 // If we put the file descriptor into nonblocking mode, 51 // then set it to blocking mode before we return it, 52 // because historically we have always returned a descriptor 53 // opened in blocking mode. The File will continue to work, 54 // but any blocking operation will tie up a thread. 55 if f.nonblock { 56 syscall.SetNonblock(f.pfd.Sysfd, false) 57 } 58 59 return uintptr(f.pfd.Sysfd) 60 } 61 62 // NewFile returns a new File with the given file descriptor and name. 63 func NewFile(fd uintptr, name string) *File { 64 return newFile(fd, name, false) 65 } 66 67 // newFile is like NewFile, but if pollable is true it tries to add the 68 // file to the runtime poller. 69 func newFile(fd uintptr, name string, pollable bool) *File { 70 fdi := int(fd) 71 if fdi < 0 { 72 return nil 73 } 74 f := &File{&file{ 75 pfd: poll.FD{ 76 Sysfd: fdi, 77 IsStream: true, 78 ZeroReadIsEOF: true, 79 }, 80 name: name, 81 }} 82 83 // Don't try to use kqueue with regular files on FreeBSD. 84 // It crashes the system unpredictably while running all.bash. 85 // Issue 19093. 86 if runtime.GOOS == "freebsd" { 87 pollable = false 88 } 89 90 if pollable { 91 if err := f.pfd.Init(); err != nil { 92 // An error here indicates a failure to register 93 // with the netpoll system. That can happen for 94 // a file descriptor that is not supported by 95 // epoll/kqueue; for example, disk files on 96 // GNU/Linux systems. We assume that any real error 97 // will show up in later I/O. 98 } else { 99 // We successfully registered with netpoll, so put 100 // the file into nonblocking mode. 101 if err := syscall.SetNonblock(fdi, true); err == nil { 102 f.nonblock = true 103 } 104 } 105 } 106 107 runtime.SetFinalizer(f.file, (*file).close) 108 return f 109 } 110 111 // Auxiliary information if the File describes a directory 112 type dirInfo struct { 113 buf []byte // buffer for directory I/O 114 nbuf int // length of buf; return value from Getdirentries 115 bufp int // location of next record in buf. 116 } 117 118 // epipecheck raises SIGPIPE if we get an EPIPE error on standard 119 // output or standard error. See the SIGPIPE docs in os/signal, and 120 // issue 11845. 121 func epipecheck(file *File, e error) { 122 if e == syscall.EPIPE && (file.pfd.Sysfd == 1 || file.pfd.Sysfd == 2) { 123 sigpipe() 124 } 125 } 126 127 // DevNull is the name of the operating system's ``null device.'' 128 // On Unix-like systems, it is "/dev/null"; on Windows, "NUL". 129 const DevNull = "/dev/null" 130 131 // OpenFile is the generalized open call; most users will use Open 132 // or Create instead. It opens the named file with specified flag 133 // (O_RDONLY etc.) and perm, (0666 etc.) if applicable. If successful, 134 // methods on the returned File can be used for I/O. 135 // If there is an error, it will be of type *PathError. 136 func OpenFile(name string, flag int, perm FileMode) (*File, error) { 137 chmod := false 138 if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 { 139 if _, err := Stat(name); IsNotExist(err) { 140 chmod = true 141 } 142 } 143 144 var r int 145 for { 146 var e error 147 r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm)) 148 if e == nil { 149 break 150 } 151 152 // On OS X, sigaction(2) doesn't guarantee that SA_RESTART will cause 153 // open(2) to be restarted for regular files. This is easy to reproduce on 154 // fuse file systems (see http://golang.org/issue/11180). 155 if runtime.GOOS == "darwin" && e == syscall.EINTR { 156 continue 157 } 158 159 return nil, &PathError{"open", name, e} 160 } 161 162 // open(2) itself won't handle the sticky bit on *BSD and Solaris 163 if chmod { 164 Chmod(name, perm) 165 } 166 167 // There's a race here with fork/exec, which we are 168 // content to live with. See ../syscall/exec_unix.go. 169 if !supportsCloseOnExec { 170 syscall.CloseOnExec(r) 171 } 172 173 return newFile(uintptr(r), name, true), nil 174 } 175 176 // Close closes the File, rendering it unusable for I/O. 177 // It returns an error, if any. 178 func (f *File) Close() error { 179 if f == nil { 180 return ErrInvalid 181 } 182 return f.file.close() 183 } 184 185 func (file *file) close() error { 186 if file == nil || file.pfd.Sysfd == badFd { 187 return syscall.EINVAL 188 } 189 var err error 190 if e := file.pfd.Close(); e != nil { 191 err = &PathError{"close", file.name, e} 192 } 193 file.pfd.Sysfd = badFd // so it can't be closed again 194 195 // no need for a finalizer anymore 196 runtime.SetFinalizer(file, nil) 197 return err 198 } 199 200 // read reads up to len(b) bytes from the File. 201 // It returns the number of bytes read and an error, if any. 202 func (f *File) read(b []byte) (n int, err error) { 203 n, err = f.pfd.Read(b) 204 runtime.KeepAlive(f) 205 return n, err 206 } 207 208 // pread reads len(b) bytes from the File starting at byte offset off. 209 // It returns the number of bytes read and the error, if any. 210 // EOF is signaled by a zero count with err set to nil. 211 func (f *File) pread(b []byte, off int64) (n int, err error) { 212 n, err = f.pfd.Pread(b, off) 213 runtime.KeepAlive(f) 214 return n, err 215 } 216 217 // write writes len(b) bytes to the File. 218 // It returns the number of bytes written and an error, if any. 219 func (f *File) write(b []byte) (n int, err error) { 220 n, err = f.pfd.Write(b) 221 runtime.KeepAlive(f) 222 return n, err 223 } 224 225 // pwrite writes len(b) bytes to the File starting at byte offset off. 226 // It returns the number of bytes written and an error, if any. 227 func (f *File) pwrite(b []byte, off int64) (n int, err error) { 228 n, err = f.pfd.Pwrite(b, off) 229 runtime.KeepAlive(f) 230 return n, err 231 } 232 233 // seek sets the offset for the next Read or Write on file to offset, interpreted 234 // according to whence: 0 means relative to the origin of the file, 1 means 235 // relative to the current offset, and 2 means relative to the end. 236 // It returns the new offset and an error, if any. 237 func (f *File) seek(offset int64, whence int) (ret int64, err error) { 238 ret, err = f.pfd.Seek(offset, whence) 239 runtime.KeepAlive(f) 240 return ret, err 241 } 242 243 // Truncate changes the size of the named file. 244 // If the file is a symbolic link, it changes the size of the link's target. 245 // If there is an error, it will be of type *PathError. 246 func Truncate(name string, size int64) error { 247 if e := syscall.Truncate(name, size); e != nil { 248 return &PathError{"truncate", name, e} 249 } 250 return nil 251 } 252 253 // Remove removes the named file or directory. 254 // If there is an error, it will be of type *PathError. 255 func Remove(name string) error { 256 // System call interface forces us to know 257 // whether name is a file or directory. 258 // Try both: it is cheaper on average than 259 // doing a Stat plus the right one. 260 e := syscall.Unlink(name) 261 if e == nil { 262 return nil 263 } 264 e1 := syscall.Rmdir(name) 265 if e1 == nil { 266 return nil 267 } 268 269 // Both failed: figure out which error to return. 270 // OS X and Linux differ on whether unlink(dir) 271 // returns EISDIR, so can't use that. However, 272 // both agree that rmdir(file) returns ENOTDIR, 273 // so we can use that to decide which error is real. 274 // Rmdir might also return ENOTDIR if given a bad 275 // file path, like /etc/passwd/foo, but in that case, 276 // both errors will be ENOTDIR, so it's okay to 277 // use the error from unlink. 278 if e1 != syscall.ENOTDIR { 279 e = e1 280 } 281 return &PathError{"remove", name, e} 282 } 283 284 // TempDir returns the default directory to use for temporary files. 285 func TempDir() string { 286 dir := Getenv("TMPDIR") 287 if dir == "" { 288 if runtime.GOOS == "android" { 289 dir = "/data/local/tmp" 290 } else { 291 dir = "/tmp" 292 } 293 } 294 return dir 295 } 296 297 // Link creates newname as a hard link to the oldname file. 298 // If there is an error, it will be of type *LinkError. 299 func Link(oldname, newname string) error { 300 e := syscall.Link(oldname, newname) 301 if e != nil { 302 return &LinkError{"link", oldname, newname, e} 303 } 304 return nil 305 } 306 307 // Symlink creates newname as a symbolic link to oldname. 308 // If there is an error, it will be of type *LinkError. 309 func Symlink(oldname, newname string) error { 310 e := syscall.Symlink(oldname, newname) 311 if e != nil { 312 return &LinkError{"symlink", oldname, newname, e} 313 } 314 return nil 315 }