file.go 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. package hackpadfs
  2. import (
  3. "io"
  4. gofs "io/fs"
  5. "syscall"
  6. "time"
  7. )
  8. // Flags are bit-wise OR'd with each other in fs.OpenFile().
  9. // Exactly one of Read/Write flags must be specified, and any other flags can be OR'd together.
  10. const (
  11. FlagReadOnly int = syscall.O_RDONLY
  12. FlagWriteOnly int = syscall.O_WRONLY
  13. FlagReadWrite int = syscall.O_RDWR
  14. FlagAppend int = syscall.O_APPEND
  15. FlagCreate int = syscall.O_CREAT
  16. FlagExclusive int = syscall.O_EXCL
  17. FlagSync int = syscall.O_SYNC
  18. FlagTruncate int = syscall.O_TRUNC
  19. )
  20. // FileMode represents a file's mode and permission bits. Mirrors io/fs.FileMode.
  21. type FileMode = gofs.FileMode
  22. // Mode values are bit-wise OR'd with a file's permissions to form the FileMode. Mirror io/fs.Mode... values.
  23. const (
  24. ModeDir = gofs.ModeDir
  25. ModeAppend = gofs.ModeAppend
  26. ModeExclusive = gofs.ModeExclusive
  27. ModeTemporary = gofs.ModeTemporary
  28. ModeSymlink = gofs.ModeSymlink
  29. ModeDevice = gofs.ModeDevice
  30. ModeNamedPipe = gofs.ModeNamedPipe
  31. ModeSocket = gofs.ModeSocket
  32. ModeSetuid = gofs.ModeSetuid
  33. ModeSetgid = gofs.ModeSetgid
  34. ModeCharDevice = gofs.ModeCharDevice
  35. ModeSticky = gofs.ModeSticky
  36. ModeIrregular = gofs.ModeIrregular
  37. ModeType = gofs.ModeType
  38. ModePerm = gofs.ModePerm
  39. )
  40. // FileInfo describes a file and is returned by Stat(). Mirrors io/fs.FileInfo.
  41. type FileInfo = gofs.FileInfo
  42. // DirEntry is an entry read from a directory. Mirrors io/fs.DirEntry.
  43. type DirEntry = gofs.DirEntry
  44. // File provides access to a file. Mirrors io/fs.File.
  45. type File = gofs.File
  46. // ReadWriterFile is a File that supports Write() operations.
  47. type ReadWriterFile interface {
  48. File
  49. io.Writer
  50. }
  51. // ReaderAtFile is a File that supports ReadAt() operations.
  52. type ReaderAtFile interface {
  53. File
  54. io.ReaderAt
  55. }
  56. // WriterAtFile is a File that supports WriteAt() operations.
  57. type WriterAtFile interface {
  58. File
  59. io.WriterAt
  60. }
  61. // DirReaderFile is a File that supports ReadDir() operations. Mirrors io/fs.ReadDirFile.
  62. type DirReaderFile interface {
  63. File
  64. ReadDir(n int) ([]DirEntry, error)
  65. }
  66. // SeekerFile is a File that supports Seek() operations.
  67. type SeekerFile interface {
  68. File
  69. io.Seeker
  70. }
  71. // SyncerFile is a File that supports Sync() operations.
  72. type SyncerFile interface {
  73. File
  74. Sync() error
  75. }
  76. // TruncaterFile is a File that supports Truncate() operations.
  77. type TruncaterFile interface {
  78. File
  79. Truncate(size int64) error
  80. }
  81. // ChmoderFile is a File that supports Chmod() operations.
  82. type ChmoderFile interface {
  83. File
  84. Chmod(mode FileMode) error
  85. }
  86. // ChownerFile is a File that supports Chown() operations.
  87. type ChownerFile interface {
  88. File
  89. Chown(uid, gid int) error
  90. }
  91. // ChtimeserFile is a File that supports Chtimes() operations.
  92. type ChtimeserFile interface {
  93. File
  94. Chtimes(atime time.Time, mtime time.Time) error
  95. }
  96. // ChmodFile runs file.Chmod() is available, fails with a not implemented error otherwise.
  97. func ChmodFile(file File, mode FileMode) error {
  98. if file, ok := file.(ChmoderFile); ok {
  99. return file.Chmod(mode)
  100. }
  101. info, err := file.Stat()
  102. if err != nil {
  103. return err
  104. }
  105. return &PathError{Op: "chmod", Path: info.Name(), Err: ErrNotImplemented}
  106. }
  107. // ChownFile runs file.Chown() is available, fails with a not implemented error otherwise.
  108. func ChownFile(file File, uid, gid int) error {
  109. if file, ok := file.(ChownerFile); ok {
  110. return file.Chown(uid, gid)
  111. }
  112. info, err := file.Stat()
  113. if err != nil {
  114. return err
  115. }
  116. return &PathError{Op: "chmod", Path: info.Name(), Err: ErrNotImplemented}
  117. }
  118. // ChtimesFile runs file.Chtimes() is available, fails with a not implemented error otherwise.
  119. func ChtimesFile(file File, atime, mtime time.Time) error {
  120. if file, ok := file.(ChtimeserFile); ok {
  121. return file.Chtimes(atime, mtime)
  122. }
  123. info, err := file.Stat()
  124. if err != nil {
  125. return err
  126. }
  127. return &PathError{Op: "chtimes", Path: info.Name(), Err: ErrNotImplemented}
  128. }
  129. // ReadAtFile runs file.ReadAt() is available, fails with a not implemented error otherwise.
  130. func ReadAtFile(file File, p []byte, off int64) (n int, err error) {
  131. if file, ok := file.(ReaderAtFile); ok {
  132. return file.ReadAt(p, off)
  133. }
  134. info, err := file.Stat()
  135. if err != nil {
  136. return 0, err
  137. }
  138. return 0, &PathError{Op: "readat", Path: info.Name(), Err: ErrNotImplemented}
  139. }
  140. // WriteFile runs file.Write() is available, fails with a not implemented error otherwise.
  141. func WriteFile(file File, p []byte) (n int, err error) {
  142. if file, ok := file.(ReadWriterFile); ok {
  143. return file.Write(p)
  144. }
  145. info, err := file.Stat()
  146. if err != nil {
  147. return 0, err
  148. }
  149. return 0, &PathError{Op: "write", Path: info.Name(), Err: ErrNotImplemented}
  150. }
  151. // WriteAtFile runs file.WriteAt() is available, fails with a not implemented error otherwise.
  152. func WriteAtFile(file File, p []byte, off int64) (n int, err error) {
  153. if file, ok := file.(WriterAtFile); ok {
  154. return file.WriteAt(p, off)
  155. }
  156. info, err := file.Stat()
  157. if err != nil {
  158. return 0, err
  159. }
  160. return 0, &PathError{Op: "writeat", Path: info.Name(), Err: ErrNotImplemented}
  161. }
  162. // ReadDirFile runs file.ReadDir() is available, fails with a not implemented error otherwise.
  163. func ReadDirFile(file File, n int) ([]DirEntry, error) {
  164. if file, ok := file.(DirReaderFile); ok {
  165. return file.ReadDir(n)
  166. }
  167. info, err := file.Stat()
  168. if err != nil {
  169. return nil, err
  170. }
  171. return nil, &PathError{Op: "readdir", Path: info.Name(), Err: ErrNotImplemented}
  172. }
  173. // SeekFile runs file.Seek() is available, fails with a not implemented error otherwise.
  174. func SeekFile(file File, offset int64, whence int) (int64, error) {
  175. if file, ok := file.(SeekerFile); ok {
  176. return file.Seek(offset, whence)
  177. }
  178. info, err := file.Stat()
  179. if err != nil {
  180. return 0, err
  181. }
  182. return 0, &PathError{Op: "seek", Path: info.Name(), Err: ErrNotImplemented}
  183. }
  184. // SyncFile runs file.Sync() is available, fails with a not implemented error otherwise.
  185. func SyncFile(file File) error {
  186. if file, ok := file.(SyncerFile); ok {
  187. return file.Sync()
  188. }
  189. info, err := file.Stat()
  190. if err != nil {
  191. return err
  192. }
  193. return &PathError{Op: "sync", Path: info.Name(), Err: ErrNotImplemented}
  194. }
  195. // TruncateFile runs file.Truncate() is available, fails with a not implemented error otherwise.
  196. func TruncateFile(file File, size int64) error {
  197. if file, ok := file.(TruncaterFile); ok {
  198. return file.Truncate(size)
  199. }
  200. info, err := file.Stat()
  201. if err != nil {
  202. return err
  203. }
  204. return &PathError{Op: "truncate", Path: info.Name(), Err: ErrNotImplemented}
  205. }