file_unix.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  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. //go:build aix || darwin || dragonfly || freebsd || hurd || (js && wasm) || linux || netbsd || openbsd || solaris
  5. package os
  6. import (
  7. "internal/poll"
  8. "internal/syscall/unix"
  9. "runtime"
  10. "syscall"
  11. )
  12. // fixLongPath is a noop on non-Windows platforms.
  13. func fixLongPath(path string) string {
  14. return path
  15. }
  16. func rename(oldname, newname string) error {
  17. fi, err := Lstat(newname)
  18. if err == nil && fi.IsDir() {
  19. // There are two independent errors this function can return:
  20. // one for a bad oldname, and one for a bad newname.
  21. // At this point we've determined the newname is bad.
  22. // But just in case oldname is also bad, prioritize returning
  23. // the oldname error because that's what we did historically.
  24. // However, if the old name and new name are not the same, yet
  25. // they refer to the same file, it implies a case-only
  26. // rename on a case-insensitive filesystem, which is ok.
  27. if ofi, err := Lstat(oldname); err != nil {
  28. if pe, ok := err.(*PathError); ok {
  29. err = pe.Err
  30. }
  31. return &LinkError{"rename", oldname, newname, err}
  32. } else if newname == oldname || !SameFile(fi, ofi) {
  33. return &LinkError{"rename", oldname, newname, syscall.EEXIST}
  34. }
  35. }
  36. err = ignoringEINTR(func() error {
  37. return syscall.Rename(oldname, newname)
  38. })
  39. if err != nil {
  40. return &LinkError{"rename", oldname, newname, err}
  41. }
  42. return nil
  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. appendMode bool // whether file is opened for appending
  55. }
  56. // Fd returns the integer Unix file descriptor referencing the open file.
  57. // If f is closed, the file descriptor becomes invalid.
  58. // If f is garbage collected, a finalizer may close the file descriptor,
  59. // making it invalid; see runtime.SetFinalizer for more information on when
  60. // a finalizer might be run. On Unix systems this will cause the SetDeadline
  61. // methods to stop working.
  62. // Because file descriptors can be reused, the returned file descriptor may
  63. // only be closed through the Close method of f, or by its finalizer during
  64. // garbage collection. Otherwise, during garbage collection the finalizer
  65. // may close an unrelated file descriptor with the same (reused) number.
  66. //
  67. // As an alternative, see the f.SyscallConn method.
  68. func (f *File) Fd() uintptr {
  69. if f == nil {
  70. return ^(uintptr(0))
  71. }
  72. // If we put the file descriptor into nonblocking mode,
  73. // then set it to blocking mode before we return it,
  74. // because historically we have always returned a descriptor
  75. // opened in blocking mode. The File will continue to work,
  76. // but any blocking operation will tie up a thread.
  77. if f.nonblock {
  78. f.pfd.SetBlocking()
  79. }
  80. return uintptr(f.pfd.Sysfd)
  81. }
  82. // NewFile returns a new File with the given file descriptor and
  83. // name. The returned value will be nil if fd is not a valid file
  84. // descriptor. On Unix systems, if the file descriptor is in
  85. // non-blocking mode, NewFile will attempt to return a pollable File
  86. // (one for which the SetDeadline methods work).
  87. //
  88. // After passing it to NewFile, fd may become invalid under the same
  89. // conditions described in the comments of the Fd method, and the same
  90. // constraints apply.
  91. func NewFile(fd uintptr, name string) *File {
  92. kind := kindNewFile
  93. if nb, err := unix.IsNonblock(int(fd)); err == nil && nb {
  94. kind = kindNonBlock
  95. }
  96. return newFile(fd, name, kind)
  97. }
  98. // newFileKind describes the kind of file to newFile.
  99. type newFileKind int
  100. const (
  101. kindNewFile newFileKind = iota
  102. kindOpenFile
  103. kindPipe
  104. kindNonBlock
  105. )
  106. // newFile is like NewFile, but if called from OpenFile or Pipe
  107. // (as passed in the kind parameter) it tries to add the file to
  108. // the runtime poller.
  109. func newFile(fd uintptr, name string, kind newFileKind) *File {
  110. fdi := int(fd)
  111. if fdi < 0 {
  112. return nil
  113. }
  114. f := &File{&file{
  115. pfd: poll.FD{
  116. Sysfd: fdi,
  117. IsStream: true,
  118. ZeroReadIsEOF: true,
  119. },
  120. name: name,
  121. stdoutOrErr: fdi == 1 || fdi == 2,
  122. }}
  123. pollable := kind == kindOpenFile || kind == kindPipe || kind == kindNonBlock
  124. // If the caller passed a non-blocking filedes (kindNonBlock),
  125. // we assume they know what they are doing so we allow it to be
  126. // used with kqueue.
  127. if kind == kindOpenFile {
  128. switch runtime.GOOS {
  129. case "darwin", "ios", "dragonfly", "freebsd", "netbsd", "openbsd":
  130. var st syscall.Stat_t
  131. err := ignoringEINTR(func() error {
  132. return syscall.Fstat(fdi, &st)
  133. })
  134. typ := st.Mode & syscall.S_IFMT
  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. // Also don't add directories to the netpoller.
  142. if err == nil && (typ == syscall.S_IFREG || typ == syscall.S_IFDIR) {
  143. pollable = false
  144. }
  145. // In addition to the behavior described above for regular files,
  146. // on Darwin, kqueue does not work properly with fifos:
  147. // closing the last writer does not cause a kqueue event
  148. // for any readers. See issue #24164.
  149. if (runtime.GOOS == "darwin" || runtime.GOOS == "ios") && typ == syscall.S_IFIFO {
  150. pollable = false
  151. }
  152. }
  153. }
  154. if err := f.pfd.Init("file", pollable); err != nil {
  155. // An error here indicates a failure to register
  156. // with the netpoll system. That can happen for
  157. // a file descriptor that is not supported by
  158. // epoll/kqueue; for example, disk files on
  159. // Linux systems. We assume that any real error
  160. // will show up in later I/O.
  161. } else if pollable {
  162. // We successfully registered with netpoll, so put
  163. // the file into nonblocking mode.
  164. if err := syscall.SetNonblock(fdi, true); err == nil {
  165. f.nonblock = true
  166. }
  167. }
  168. runtime.SetFinalizer(f.file, (*file).close)
  169. return f
  170. }
  171. // Auxiliary information if the File describes a directory
  172. type dirInfo struct {
  173. dir *syscall.DIR // from opendir
  174. }
  175. func (d *dirInfo) close() {
  176. if d.dir != nil {
  177. syscall.Entersyscall()
  178. libc_closedir(d.dir)
  179. syscall.Exitsyscall()
  180. d.dir = nil
  181. }
  182. }
  183. // epipecheck raises SIGPIPE if we get an EPIPE error on standard
  184. // output or standard error. See the SIGPIPE docs in os/signal, and
  185. // issue 11845.
  186. func epipecheck(file *File, e error) {
  187. if e == syscall.EPIPE && file.stdoutOrErr {
  188. sigpipe()
  189. }
  190. }
  191. // DevNull is the name of the operating system's ``null device.''
  192. // On Unix-like systems, it is "/dev/null"; on Windows, "NUL".
  193. const DevNull = "/dev/null"
  194. // openFileNolog is the Unix implementation of OpenFile.
  195. // Changes here should be reflected in openFdAt, if relevant.
  196. func openFileNolog(name string, flag int, perm FileMode) (*File, error) {
  197. setSticky := false
  198. if !supportsCreateWithStickyBit && flag&O_CREATE != 0 && perm&ModeSticky != 0 {
  199. if _, err := Stat(name); IsNotExist(err) {
  200. setSticky = true
  201. }
  202. }
  203. var r int
  204. for {
  205. var e error
  206. r, e = syscall.Open(name, flag|syscall.O_CLOEXEC, syscallMode(perm))
  207. if e == nil {
  208. break
  209. }
  210. // We have to check EINTR here, per issues 11180 and 39237.
  211. if e == syscall.EINTR {
  212. continue
  213. }
  214. return nil, &PathError{Op: "open", Path: name, Err: e}
  215. }
  216. // open(2) itself won't handle the sticky bit on *BSD and Solaris
  217. if setSticky {
  218. setStickyBit(name)
  219. }
  220. // There's a race here with fork/exec, which we are
  221. // content to live with. See ../syscall/exec_unix.go.
  222. if !supportsCloseOnExec {
  223. syscall.CloseOnExec(r)
  224. }
  225. return newFile(uintptr(r), name, kindOpenFile), nil
  226. }
  227. func (file *file) close() error {
  228. if file == nil {
  229. return syscall.EINVAL
  230. }
  231. var err error
  232. if file.dirinfo != nil {
  233. file.dirinfo.close()
  234. file.dirinfo = nil
  235. }
  236. if e := file.pfd.Close(); e != nil {
  237. if e == poll.ErrFileClosing {
  238. e = ErrClosed
  239. }
  240. err = &PathError{Op: "close", Path: file.name, Err: e}
  241. }
  242. // no need for a finalizer anymore
  243. runtime.SetFinalizer(file, nil)
  244. return err
  245. }
  246. // seek sets the offset for the next Read or Write on file to offset, interpreted
  247. // according to whence: 0 means relative to the origin of the file, 1 means
  248. // relative to the current offset, and 2 means relative to the end.
  249. // It returns the new offset and an error, if any.
  250. func (f *File) seek(offset int64, whence int) (ret int64, err error) {
  251. if f.dirinfo != nil {
  252. // Free cached dirinfo, so we allocate a new one if we
  253. // access this file as a directory again. See #35767 and #37161.
  254. f.dirinfo.close()
  255. f.dirinfo = nil
  256. }
  257. ret, err = f.pfd.Seek(offset, whence)
  258. runtime.KeepAlive(f)
  259. return ret, err
  260. }
  261. // Truncate changes the size of the named file.
  262. // If the file is a symbolic link, it changes the size of the link's target.
  263. // If there is an error, it will be of type *PathError.
  264. func Truncate(name string, size int64) error {
  265. e := ignoringEINTR(func() error {
  266. return syscall.Truncate(name, size)
  267. })
  268. if e != nil {
  269. return &PathError{Op: "truncate", Path: name, Err: e}
  270. }
  271. return nil
  272. }
  273. // Remove removes the named file or (empty) directory.
  274. // If there is an error, it will be of type *PathError.
  275. func Remove(name string) error {
  276. // System call interface forces us to know
  277. // whether name is a file or directory.
  278. // Try both: it is cheaper on average than
  279. // doing a Stat plus the right one.
  280. e := ignoringEINTR(func() error {
  281. return syscall.Unlink(name)
  282. })
  283. if e == nil {
  284. return nil
  285. }
  286. e1 := ignoringEINTR(func() error {
  287. return syscall.Rmdir(name)
  288. })
  289. if e1 == nil {
  290. return nil
  291. }
  292. // Both failed: figure out which error to return.
  293. // OS X and Linux differ on whether unlink(dir)
  294. // returns EISDIR, so can't use that. However,
  295. // both agree that rmdir(file) returns ENOTDIR,
  296. // so we can use that to decide which error is real.
  297. // Rmdir might also return ENOTDIR if given a bad
  298. // file path, like /etc/passwd/foo, but in that case,
  299. // both errors will be ENOTDIR, so it's okay to
  300. // use the error from unlink.
  301. if e1 != syscall.ENOTDIR {
  302. e = e1
  303. }
  304. return &PathError{Op: "remove", Path: name, Err: e}
  305. }
  306. func tempDir() string {
  307. dir := Getenv("TMPDIR")
  308. if dir == "" {
  309. if runtime.GOOS == "android" {
  310. dir = "/data/local/tmp"
  311. } else {
  312. dir = "/tmp"
  313. }
  314. }
  315. return dir
  316. }
  317. // Link creates newname as a hard link to the oldname file.
  318. // If there is an error, it will be of type *LinkError.
  319. func Link(oldname, newname string) error {
  320. e := ignoringEINTR(func() error {
  321. return syscall.Link(oldname, newname)
  322. })
  323. if e != nil {
  324. return &LinkError{"link", oldname, newname, e}
  325. }
  326. return nil
  327. }
  328. // Symlink creates newname as a symbolic link to oldname.
  329. // On Windows, a symlink to a non-existent oldname creates a file symlink;
  330. // if oldname is later created as a directory the symlink will not work.
  331. // If there is an error, it will be of type *LinkError.
  332. func Symlink(oldname, newname string) error {
  333. e := ignoringEINTR(func() error {
  334. return syscall.Symlink(oldname, newname)
  335. })
  336. if e != nil {
  337. return &LinkError{"symlink", oldname, newname, e}
  338. }
  339. return nil
  340. }
  341. // Readlink returns the destination of the named symbolic link.
  342. // If there is an error, it will be of type *PathError.
  343. func Readlink(name string) (string, error) {
  344. for len := 128; ; len *= 2 {
  345. b := make([]byte, len)
  346. var (
  347. n int
  348. e error
  349. )
  350. for {
  351. n, e = fixCount(syscall.Readlink(name, b))
  352. if e != syscall.EINTR {
  353. break
  354. }
  355. }
  356. // buffer too small
  357. if runtime.GOOS == "aix" && e == syscall.ERANGE {
  358. continue
  359. }
  360. if e != nil {
  361. return "", &PathError{Op: "readlink", Path: name, Err: e}
  362. }
  363. if n < len {
  364. return string(b[0:n]), nil
  365. }
  366. }
  367. }
  368. type unixDirent struct {
  369. parent string
  370. name string
  371. typ FileMode
  372. info FileInfo
  373. }
  374. func (d *unixDirent) Name() string { return d.name }
  375. func (d *unixDirent) IsDir() bool { return d.typ.IsDir() }
  376. func (d *unixDirent) Type() FileMode { return d.typ }
  377. func (d *unixDirent) Info() (FileInfo, error) {
  378. if d.info != nil {
  379. return d.info, nil
  380. }
  381. return lstat(d.parent + "/" + d.name)
  382. }
  383. func newUnixDirent(parent, name string, typ FileMode) (DirEntry, error) {
  384. ude := &unixDirent{
  385. parent: parent,
  386. name: name,
  387. typ: typ,
  388. }
  389. if typ != ^FileMode(0) && !testingForceReadDirLstat {
  390. return ude, nil
  391. }
  392. info, err := lstat(parent + "/" + name)
  393. if err != nil {
  394. return nil, err
  395. }
  396. ude.typ = info.Mode().Type()
  397. ude.info = info
  398. return ude, nil
  399. }