You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

203 lines
7.9 KiB

  1. package billy
  2. import (
  3. "errors"
  4. "io"
  5. "os"
  6. "time"
  7. )
  8. var (
  9. ErrReadOnly = errors.New("read-only filesystem")
  10. ErrNotSupported = errors.New("feature not supported")
  11. ErrCrossedBoundary = errors.New("chroot boundary crossed")
  12. )
  13. // Capability holds the supported features of a billy filesystem. This does
  14. // not mean that the capability has to be supported by the underlying storage.
  15. // For example, a billy filesystem may support WriteCapability but the
  16. // storage be mounted in read only mode.
  17. type Capability uint64
  18. const (
  19. // WriteCapability means that the fs is writable.
  20. WriteCapability Capability = 1 << iota
  21. // ReadCapability means that the fs is readable.
  22. ReadCapability
  23. // ReadAndWriteCapability is the ability to open a file in read and write mode.
  24. ReadAndWriteCapability
  25. // SeekCapability means it is able to move position inside the file.
  26. SeekCapability
  27. // TruncateCapability means that a file can be truncated.
  28. TruncateCapability
  29. // LockCapability is the ability to lock a file.
  30. LockCapability
  31. // DefaultCapabilities lists all capable features supported by filesystems
  32. // without Capability interface. This list should not be changed until a
  33. // major version is released.
  34. DefaultCapabilities Capability = WriteCapability | ReadCapability |
  35. ReadAndWriteCapability | SeekCapability | TruncateCapability |
  36. LockCapability
  37. // AllCapabilities lists all capable features.
  38. AllCapabilities Capability = WriteCapability | ReadCapability |
  39. ReadAndWriteCapability | SeekCapability | TruncateCapability |
  40. LockCapability
  41. )
  42. // Filesystem abstract the operations in a storage-agnostic interface.
  43. // Each method implementation mimics the behavior of the equivalent functions
  44. // at the os package from the standard library.
  45. type Filesystem interface {
  46. Basic
  47. TempFile
  48. Dir
  49. Symlink
  50. Chroot
  51. }
  52. // Basic abstract the basic operations in a storage-agnostic interface as
  53. // an extension to the Basic interface.
  54. type Basic interface {
  55. // Create creates the named file with mode 0666 (before umask), truncating
  56. // it if it already exists. If successful, methods on the returned File can
  57. // be used for I/O; the associated file descriptor has mode O_RDWR.
  58. Create(filename string) (File, error)
  59. // Open opens the named file for reading. If successful, methods on the
  60. // returned file can be used for reading; the associated file descriptor has
  61. // mode O_RDONLY.
  62. Open(filename string) (File, error)
  63. // OpenFile is the generalized open call; most users will use Open or Create
  64. // instead. It opens the named file with specified flag (O_RDONLY etc.) and
  65. // perm, (0666 etc.) if applicable. If successful, methods on the returned
  66. // File can be used for I/O.
  67. OpenFile(filename string, flag int, perm os.FileMode) (File, error)
  68. // Stat returns a FileInfo describing the named file.
  69. Stat(filename string) (os.FileInfo, error)
  70. // Rename renames (moves) oldpath to newpath. If newpath already exists and
  71. // is not a directory, Rename replaces it. OS-specific restrictions may
  72. // apply when oldpath and newpath are in different directories.
  73. Rename(oldpath, newpath string) error
  74. // Remove removes the named file or directory.
  75. Remove(filename string) error
  76. // Join joins any number of path elements into a single path, adding a
  77. // Separator if necessary. Join calls filepath.Clean on the result; in
  78. // particular, all empty strings are ignored. On Windows, the result is a
  79. // UNC path if and only if the first path element is a UNC path.
  80. Join(elem ...string) string
  81. }
  82. type TempFile interface {
  83. // TempFile creates a new temporary file in the directory dir with a name
  84. // beginning with prefix, opens the file for reading and writing, and
  85. // returns the resulting *os.File. If dir is the empty string, TempFile
  86. // uses the default directory for temporary files (see os.TempDir).
  87. // Multiple programs calling TempFile simultaneously will not choose the
  88. // same file. The caller can use f.Name() to find the pathname of the file.
  89. // It is the caller's responsibility to remove the file when no longer
  90. // needed.
  91. TempFile(dir, prefix string) (File, error)
  92. }
  93. // Dir abstract the dir related operations in a storage-agnostic interface as
  94. // an extension to the Basic interface.
  95. type Dir interface {
  96. // ReadDir reads the directory named by dirname and returns a list of
  97. // directory entries sorted by filename.
  98. ReadDir(path string) ([]os.FileInfo, error)
  99. // MkdirAll creates a directory named path, along with any necessary
  100. // parents, and returns nil, or else returns an error. The permission bits
  101. // perm are used for all directories that MkdirAll creates. If path is/
  102. // already a directory, MkdirAll does nothing and returns nil.
  103. MkdirAll(filename string, perm os.FileMode) error
  104. }
  105. // Symlink abstract the symlink related operations in a storage-agnostic
  106. // interface as an extension to the Basic interface.
  107. type Symlink interface {
  108. // Lstat returns a FileInfo describing the named file. If the file is a
  109. // symbolic link, the returned FileInfo describes the symbolic link. Lstat
  110. // makes no attempt to follow the link.
  111. Lstat(filename string) (os.FileInfo, error)
  112. // Symlink creates a symbolic-link from link to target. target may be an
  113. // absolute or relative path, and need not refer to an existing node.
  114. // Parent directories of link are created as necessary.
  115. Symlink(target, link string) error
  116. // Readlink returns the target path of link.
  117. Readlink(link string) (string, error)
  118. }
  119. // Change abstract the FileInfo change related operations in a storage-agnostic
  120. // interface as an extension to the Basic interface
  121. type Change interface {
  122. // Chmod changes the mode of the named file to mode. If the file is a
  123. // symbolic link, it changes the mode of the link's target.
  124. Chmod(name string, mode os.FileMode) error
  125. // Lchown changes the numeric uid and gid of the named file. If the file is
  126. // a symbolic link, it changes the uid and gid of the link itself.
  127. Lchown(name string, uid, gid int) error
  128. // Chown changes the numeric uid and gid of the named file. If the file is a
  129. // symbolic link, it changes the uid and gid of the link's target.
  130. Chown(name string, uid, gid int) error
  131. // Chtimes changes the access and modification times of the named file,
  132. // similar to the Unix utime() or utimes() functions.
  133. //
  134. // The underlying filesystem may truncate or round the values to a less
  135. // precise time unit.
  136. Chtimes(name string, atime time.Time, mtime time.Time) error
  137. }
  138. // Chroot abstract the chroot related operations in a storage-agnostic interface
  139. // as an extension to the Basic interface.
  140. type Chroot interface {
  141. // Chroot returns a new filesystem from the same type where the new root is
  142. // the given path. Files outside of the designated directory tree cannot be
  143. // accessed.
  144. Chroot(path string) (Filesystem, error)
  145. // Root returns the root path of the filesystem.
  146. Root() string
  147. }
  148. // File represent a file, being a subset of the os.File
  149. type File interface {
  150. // Name returns the name of the file as presented to Open.
  151. Name() string
  152. io.Writer
  153. io.Reader
  154. io.ReaderAt
  155. io.Seeker
  156. io.Closer
  157. // Lock locks the file like e.g. flock. It protects against access from
  158. // other processes.
  159. Lock() error
  160. // Unlock unlocks the file.
  161. Unlock() error
  162. // Truncate the file.
  163. Truncate(size int64) error
  164. }
  165. // Capable interface can return the available features of a filesystem.
  166. type Capable interface {
  167. // Capabilities returns the capabilities of a filesystem in bit flags.
  168. Capabilities() Capability
  169. }
  170. // Capabilities returns the features supported by a filesystem. If the FS
  171. // does not implement Capable interface it returns all features.
  172. func Capabilities(fs Basic) Capability {
  173. capable, ok := fs.(Capable)
  174. if !ok {
  175. return DefaultCapabilities
  176. }
  177. return capable.Capabilities()
  178. }
  179. // CapabilityCheck tests the filesystem for the provided capabilities and
  180. // returns true in case it supports all of them.
  181. func CapabilityCheck(fs Basic, capabilities Capability) bool {
  182. fsCaps := Capabilities(fs)
  183. return fsCaps&capabilities == capabilities
  184. }