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