file_posix.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  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 || windows
  5. package os
  6. import (
  7. "runtime"
  8. "syscall"
  9. "time"
  10. )
  11. func sigpipe() // implemented in package runtime
  12. // Close closes the File, rendering it unusable for I/O.
  13. // On files that support SetDeadline, any pending I/O operations will
  14. // be canceled and return immediately with an ErrClosed error.
  15. // Close will return an error if it has already been called.
  16. func (f *File) Close() error {
  17. if f == nil {
  18. return ErrInvalid
  19. }
  20. return f.file.close()
  21. }
  22. // read reads up to len(b) bytes from the File.
  23. // It returns the number of bytes read and an error, if any.
  24. func (f *File) read(b []byte) (n int, err error) {
  25. n, err = f.pfd.Read(b)
  26. runtime.KeepAlive(f)
  27. return n, err
  28. }
  29. // pread reads len(b) bytes from the File starting at byte offset off.
  30. // It returns the number of bytes read and the error, if any.
  31. // EOF is signaled by a zero count with err set to nil.
  32. func (f *File) pread(b []byte, off int64) (n int, err error) {
  33. n, err = f.pfd.Pread(b, off)
  34. runtime.KeepAlive(f)
  35. return n, err
  36. }
  37. // write writes len(b) bytes to the File.
  38. // It returns the number of bytes written and an error, if any.
  39. func (f *File) write(b []byte) (n int, err error) {
  40. n, err = f.pfd.Write(b)
  41. runtime.KeepAlive(f)
  42. return n, err
  43. }
  44. // pwrite writes len(b) bytes to the File starting at byte offset off.
  45. // It returns the number of bytes written and an error, if any.
  46. func (f *File) pwrite(b []byte, off int64) (n int, err error) {
  47. n, err = f.pfd.Pwrite(b, off)
  48. runtime.KeepAlive(f)
  49. return n, err
  50. }
  51. // syscallMode returns the syscall-specific mode bits from Go's portable mode bits.
  52. func syscallMode(i FileMode) (o uint32) {
  53. o |= uint32(i.Perm())
  54. if i&ModeSetuid != 0 {
  55. o |= syscall.S_ISUID
  56. }
  57. if i&ModeSetgid != 0 {
  58. o |= syscall.S_ISGID
  59. }
  60. if i&ModeSticky != 0 {
  61. o |= syscall.S_ISVTX
  62. }
  63. // No mapping for Go's ModeTemporary (plan9 only).
  64. return
  65. }
  66. // See docs in file.go:Chmod.
  67. func chmod(name string, mode FileMode) error {
  68. longName := fixLongPath(name)
  69. e := ignoringEINTR(func() error {
  70. return syscall.Chmod(longName, syscallMode(mode))
  71. })
  72. if e != nil {
  73. return &PathError{Op: "chmod", Path: name, Err: e}
  74. }
  75. return nil
  76. }
  77. // See docs in file.go:(*File).Chmod.
  78. func (f *File) chmod(mode FileMode) error {
  79. if err := f.checkValid("chmod"); err != nil {
  80. return err
  81. }
  82. if e := f.pfd.Fchmod(syscallMode(mode)); e != nil {
  83. return f.wrapErr("chmod", e)
  84. }
  85. return nil
  86. }
  87. // Chown changes the numeric uid and gid of the named file.
  88. // If the file is a symbolic link, it changes the uid and gid of the link's target.
  89. // A uid or gid of -1 means to not change that value.
  90. // If there is an error, it will be of type *PathError.
  91. //
  92. // On Windows or Plan 9, Chown always returns the syscall.EWINDOWS or
  93. // EPLAN9 error, wrapped in *PathError.
  94. func Chown(name string, uid, gid int) error {
  95. e := ignoringEINTR(func() error {
  96. return syscall.Chown(name, uid, gid)
  97. })
  98. if e != nil {
  99. return &PathError{Op: "chown", Path: name, Err: e}
  100. }
  101. return nil
  102. }
  103. // Lchown changes the numeric uid and gid of the named file.
  104. // If the file is a symbolic link, it changes the uid and gid of the link itself.
  105. // If there is an error, it will be of type *PathError.
  106. //
  107. // On Windows, it always returns the syscall.EWINDOWS error, wrapped
  108. // in *PathError.
  109. func Lchown(name string, uid, gid int) error {
  110. e := ignoringEINTR(func() error {
  111. return syscall.Lchown(name, uid, gid)
  112. })
  113. if e != nil {
  114. return &PathError{Op: "lchown", Path: name, Err: e}
  115. }
  116. return nil
  117. }
  118. // Chown changes the numeric uid and gid of the named file.
  119. // If there is an error, it will be of type *PathError.
  120. //
  121. // On Windows, it always returns the syscall.EWINDOWS error, wrapped
  122. // in *PathError.
  123. func (f *File) Chown(uid, gid int) error {
  124. if err := f.checkValid("chown"); err != nil {
  125. return err
  126. }
  127. if e := f.pfd.Fchown(uid, gid); e != nil {
  128. return f.wrapErr("chown", e)
  129. }
  130. return nil
  131. }
  132. // Truncate changes the size of the file.
  133. // It does not change the I/O offset.
  134. // If there is an error, it will be of type *PathError.
  135. func (f *File) Truncate(size int64) error {
  136. if err := f.checkValid("truncate"); err != nil {
  137. return err
  138. }
  139. if e := f.pfd.Ftruncate(size); e != nil {
  140. return f.wrapErr("truncate", e)
  141. }
  142. return nil
  143. }
  144. // Sync commits the current contents of the file to stable storage.
  145. // Typically, this means flushing the file system's in-memory copy
  146. // of recently written data to disk.
  147. func (f *File) Sync() error {
  148. if err := f.checkValid("sync"); err != nil {
  149. return err
  150. }
  151. if e := f.pfd.Fsync(); e != nil {
  152. return f.wrapErr("sync", e)
  153. }
  154. return nil
  155. }
  156. // Chtimes changes the access and modification times of the named
  157. // file, similar to the Unix utime() or utimes() functions.
  158. //
  159. // The underlying filesystem may truncate or round the values to a
  160. // less precise time unit.
  161. // If there is an error, it will be of type *PathError.
  162. func Chtimes(name string, atime time.Time, mtime time.Time) error {
  163. var utimes [2]syscall.Timespec
  164. utimes[0] = syscall.NsecToTimespec(atime.UnixNano())
  165. utimes[1] = syscall.NsecToTimespec(mtime.UnixNano())
  166. if e := syscall.UtimesNano(fixLongPath(name), utimes[0:]); e != nil {
  167. return &PathError{Op: "chtimes", Path: name, Err: e}
  168. }
  169. return nil
  170. }
  171. // Chdir changes the current working directory to the file,
  172. // which must be a directory.
  173. // If there is an error, it will be of type *PathError.
  174. func (f *File) Chdir() error {
  175. if err := f.checkValid("chdir"); err != nil {
  176. return err
  177. }
  178. if e := f.pfd.Fchdir(); e != nil {
  179. return f.wrapErr("chdir", e)
  180. }
  181. return nil
  182. }
  183. // setDeadline sets the read and write deadline.
  184. func (f *File) setDeadline(t time.Time) error {
  185. if err := f.checkValid("SetDeadline"); err != nil {
  186. return err
  187. }
  188. return f.pfd.SetDeadline(t)
  189. }
  190. // setReadDeadline sets the read deadline.
  191. func (f *File) setReadDeadline(t time.Time) error {
  192. if err := f.checkValid("SetReadDeadline"); err != nil {
  193. return err
  194. }
  195. return f.pfd.SetReadDeadline(t)
  196. }
  197. // setWriteDeadline sets the write deadline.
  198. func (f *File) setWriteDeadline(t time.Time) error {
  199. if err := f.checkValid("SetWriteDeadline"); err != nil {
  200. return err
  201. }
  202. return f.pfd.SetWriteDeadline(t)
  203. }
  204. // checkValid checks whether f is valid for use.
  205. // If not, it returns an appropriate error, perhaps incorporating the operation name op.
  206. func (f *File) checkValid(op string) error {
  207. if f == nil {
  208. return ErrInvalid
  209. }
  210. return nil
  211. }
  212. // ignoringEINTR makes a function call and repeats it if it returns an
  213. // EINTR error. This appears to be required even though we install all
  214. // signal handlers with SA_RESTART: see #22838, #38033, #38836, #40846.
  215. // Also #20400 and #36644 are issues in which a signal handler is
  216. // installed without setting SA_RESTART. None of these are the common case,
  217. // but there are enough of them that it seems that we can't avoid
  218. // an EINTR loop.
  219. func ignoringEINTR(fn func() error) error {
  220. for {
  221. err := fn()
  222. if err != syscall.EINTR {
  223. return err
  224. }
  225. }
  226. }