Documentation
¶
Index ¶
- Constants
- Variables
- func FileModeFromUnix(m uint64) os.FileMode
- func IsErrorCode(err error, code ErrorCode) bool
- func IsLinkError(err error) bool
- func IsPathError(err error) bool
- func ValidateIgnore(s string) error
- type Archive
- type ArchiveOption
- type Error
- type ErrorCode
- type File
- type Filesystem
- func (fs *Filesystem) CachedUsage() int64
- func (fs *Filesystem) Chmod(p string, mode os.FileMode) error
- func (fs *Filesystem) Chown(p string) error
- func (fs *Filesystem) Chtimes(p string, atime, mtime time.Time) error
- func (fs *Filesystem) Close() error
- func (fs *Filesystem) CompressFiles(ctx context.Context, dir string, name string, paths []string, extension string) (os.FileInfo, string, error)
- func (fs *Filesystem) Copy(p string) error
- func (fs *Filesystem) CreateDirectory(name string, p string) error
- func (fs *Filesystem) DecompressFile(ctx context.Context, dir string, file string) error
- func (fs *Filesystem) Delete(p string) error
- func (fs *Filesystem) DirectorySize(dir string) (int64, error)
- func (fs *Filesystem) DiskUsage(allowStaleValue bool) (int64, error)
- func (fs *Filesystem) ExtractStreamUnsafe(ctx context.Context, dir string, r io.Reader) error
- func (fs *Filesystem) File(p string) (*os.File, Stat, error)
- func (fs *Filesystem) HasSpaceAvailable(allowStaleValue bool) bool
- func (fs *Filesystem) HasSpaceErr(allowStaleValue bool) error
- func (fs *Filesystem) HasSpaceFor(size int64) error
- func (fs *Filesystem) IsIgnored(paths ...string) error
- func (fs *Filesystem) IsIgnoredNoFollow(paths ...string) error
- func (fs *Filesystem) ListDirectory(p string) ([]Stat, error)
- func (fs *Filesystem) MaxDisk() int64
- func (fs *Filesystem) Mkdir(p string, mode os.FileMode) error
- func (fs *Filesystem) NewArchive(dir string, opts ...ArchiveOption) (*Archive, error)
- func (fs *Filesystem) Path() string
- func (fs *Filesystem) ReadDir(p string) ([]fs2.DirEntry, error)
- func (fs *Filesystem) Rename(from string, to string) error
- func (fs *Filesystem) RestoreSymlink(name, target string) error
- func (fs *Filesystem) SafeDeleteRecursively(p string) error
- func (fs *Filesystem) SetDiskLimit(i int64)
- func (fs *Filesystem) SpaceAvailableForDecompression(ctx context.Context, dir string, file string) error
- func (fs *Filesystem) Stat(p string) (Stat, error)
- func (fs *Filesystem) Stat2(p string) (os.FileInfo, error)
- func (fs *Filesystem) Symlink(source, target string) error
- func (fs *Filesystem) Touch(p string, flag int, mode os.FileMode) (File, error)
- func (fs *Filesystem) TruncateRootDirectory() error
- func (fs *Filesystem) Write(p string, r io.Reader, newSize int64, mode os.FileMode) error
- func (fs *Filesystem) Writefile(p string, r io.Reader) errordeprecated
- type SpaceCheckingOpts
- type Stat
- type TarProgress
Constants ¶
const ( // MaxIgnoreLength is the maximum size, in bytes, of a pattern list. MaxIgnoreLength = 32 * 1024 // MaxIgnorePatterns is the maximum number of non-blank, non-comment lines in a list. MaxIgnorePatterns = 256 // MaxIgnorePatternWildcards is the maximum number of unescaped "*" characters in a pattern. MaxIgnorePatternWildcards = 16 )
Limits applied to the gitignore-style pattern lists used by an Archive, whether they come from the Panel with a backup request or from a server's .pelicanignore file.
Variables ¶
var ErrNoSpaceAvailable = errors.Sentinel("archive: no space available on disk")
Functions ¶
func FileModeFromUnix ¶
FileModeFromUnix converts a Unix mode such as 0o4755, as sent by the Panel, to an os.FileMode. Go keeps setuid, setgid and sticky in other bits than Unix does, so a plain os.FileMode(0o4755) loses them. Bits above 0o7777 are ignored, as chmod(2) does.
func IsErrorCode ¶
IsErrorCode checks if "err" is a filesystem Error type. If so, it will then drop in and check that the error code is the same as the provided ErrorCode passed in "code".
func IsLinkError ¶
func IsPathError ¶
func ValidateIgnore ¶
ValidateIgnore checks a pattern list against the limits above. The returned error describes the first limit exceeded and is safe to display to the user.
Types ¶
type Archive ¶
type Archive struct {
// contains filtered or unexported fields
}
func NewArchive ¶
NewArchive returns a new archive instance that can be used for generating an archive of files and folders within the provided os.Root. The "dir" value is a child directory within the `os.Root` instance, and the paths stored in the archive are relative to it. Ex. os.Root = '/var/lib/pelican/volumes/{server-uuid}' and dir = "worlds"
type ArchiveOption ¶
func WithIgnored ¶
func WithIgnored(patterns string) ArchiveOption
WithIgnored excludes every file matching the given gitignore-style pattern list from the archive. The list is validated against the limits defined in ignore.go, and an error is returned if it exceeds them.
func WithMatching ¶
func WithMatching(files []string) ArchiveOption
WithMatching limits the archive to the given files and directories (and everything within those directories). Paths are relative to the archive's base directory.
func WithProgress ¶
func WithProgress(p *progress.Progress) ArchiveOption
type Error ¶
type Error struct {
// contains filtered or unexported fields
}
type ErrorCode ¶
type ErrorCode string
const ( ErrCodeIsDirectory ErrorCode = "E_ISDIR" ErrCodeDiskSpace ErrorCode = "E_NODISK" ErrCodeUnknownArchive ErrorCode = "E_UNKNFMT" ErrCodeDenylistFile ErrorCode = "E_DENYLIST" ErrCodeUnknownError ErrorCode = "E_UNKNOWN" ErrNotExist ErrorCode = "E_NOTEXIST" ErrCodeNotRegular ErrorCode = "E_NOTREGULAR" // ErrCodeArchiveIsOutput is returned when decompressing a single-file archive // would write over the archive itself. resolved holds the extension the // archive should be renamed to end in. ErrCodeArchiveIsOutput ErrorCode = "E_ARCHIVEISOUTPUT" )
type File ¶
type File interface {
io.Reader
io.ReaderAt
io.Writer
io.WriterAt
io.Seeker
io.Closer
io.ReaderFrom
Name() string
Stat() (os.FileInfo, error)
Truncate(size int64) error
Sync() error
}
File is the handle returned by Filesystem.Touch. Writes made through it are accounted against the disk quota of the Filesystem that opened it.
type Filesystem ¶
type Filesystem struct {
// contains filtered or unexported fields
}
func New ¶
func New(path string, size int64, denylist []string) (*Filesystem, error)
New creates a new Filesystem instance for a given server.
func (*Filesystem) CachedUsage ¶
func (fs *Filesystem) CachedUsage() int64
Returns the cached value for the amount of disk space used by the filesystem. Do not rely on this function for critical logical checks. It should only be used in areas where the actual disk usage does not need to be perfect, e.g. API responses for server resource usage.
func (*Filesystem) Chmod ¶
func (fs *Filesystem) Chmod(p string, mode os.FileMode) error
Chmod changes the mode of the given file or directory. os.Root follows a symlink at p, so the mode of a denylisted file cannot be changed through a link to it. Changing it by its own name is left to the caller to allow or refuse, as before.
func (*Filesystem) Chown ¶
func (fs *Filesystem) Chown(p string) error
Chown recursively iterates over a file or directory and sets the owner on all the underlying files. Iterate over all the files and directories. If it is a file go ahead and perform the chown operation. Otherwise dig deeper into the directory until we've run out of directories to dig into.
The walk happens through the os.Root instance and never follows symlinks, so it cannot change the owner of anything outside the server's data directory.
func (*Filesystem) Chtimes ¶
func (fs *Filesystem) Chtimes(p string, atime, mtime time.Time) error
Chtimes changes the access and modification times of the given file.
func (*Filesystem) Close ¶
func (fs *Filesystem) Close() error
Close closes the underlying os.Root instance for the server, and any folder that was open before the server's folder was replaced.
func (*Filesystem) CompressFiles ¶
func (fs *Filesystem) CompressFiles(ctx context.Context, dir string, name string, paths []string, extension string) (os.FileInfo, string, error)
CompressFiles compresses all the files matching the given paths in the specified directory. This function also supports passing nested paths to only compress certain files and folders when working in a larger directory. This effectively creates a local backup, but rather than ignoring specific files and folders, it takes an allowlist of files and folders.
All paths are relative to the dir that is passed in as the first argument, and the compressed file will be placed at that location named `archive-{date}.tar.gz`.
func (*Filesystem) Copy ¶
func (fs *Filesystem) Copy(p string) error
Copies a given file to the same location and appends a suffix to the file to indicate that it has been copied.
func (*Filesystem) CreateDirectory ¶
func (fs *Filesystem) CreateDirectory(name string, p string) error
CreateDirectory creates a new directory ("name") at a specified path ("p") for the server.
p and name are joined before being cleaned, as main does, so a name such as "../name" under "/" stays inside the server, while "e/../../name" still fails.
func (*Filesystem) DecompressFile ¶
DecompressFile will decompress a file in a given directory by using the archiver tool to infer the file type and go from there. This will walk over all the files within the given archive and ensure that there is not a zip-slip attack being attempted by validating that the final path is within the server data directory.
func (*Filesystem) Delete ¶
func (fs *Filesystem) Delete(p string) error
Delete removes a file or folder from the system. Prevents the user from accidentally (or maliciously) removing their root server data directory.
func (*Filesystem) DirectorySize ¶
func (fs *Filesystem) DirectorySize(dir string) (int64, error)
DirectorySize determines the directory size of a given location. Returns the size in bytes. This can be a fairly taxing operation on locations with tons of files, so it is recommended that you cache the output.
The walk happens through the os.Root instance, so neither the directory being measured nor anything inside it can resolve to a location outside the server's data directory. Symlinks are never followed.
func (*Filesystem) DiskUsage ¶
func (fs *Filesystem) DiskUsage(allowStaleValue bool) (int64, error)
Internal helper function to allow other parts of the codebase to check the total used disk space as needed without overly taxing the system. This will prioritize the value from the cache to avoid excessive IO usage. We will only walk the filesystem and determine the size of the directory if there is no longer a cached value.
If "allowStaleValue" is set to true, a stale value MAY be returned to the caller if there is an expired cache value AND there is currently another lookup in progress. If there is no cached value but no other lookup is in progress, a fresh disk space response will be returned to the caller.
This is primarily to avoid a bunch of I/O operations from piling up on the server, especially on servers with a large amount of files.
func (*Filesystem) ExtractStreamUnsafe ¶
ExtractStreamUnsafe .
func (*Filesystem) File ¶
File returns a reader for a file instance as well as the stat information. Only regular files can be opened; directories return an ErrCodeIsDirectory error and any other type of file (named pipes, sockets, devices) returns an ErrCodeNotRegular error without the file ever being opened. Opening a named pipe for reading blocks until a writer appears, which would hang the caller.
func (*Filesystem) HasSpaceAvailable ¶
func (fs *Filesystem) HasSpaceAvailable(allowStaleValue bool) bool
HasSpaceAvailable checks if the directory a file is trying to be added to has enough space available for the file to be written to. Because determining the amount of space being used by a server is a taxing operation, we will load it all up into a cache and pull from that as long as the key is not expired.
This operation will potentially be blocked unless allowStaleValue is set to true. See the documentation on DiskUsage for how this affects the call.
func (*Filesystem) HasSpaceErr ¶
func (fs *Filesystem) HasSpaceErr(allowStaleValue bool) error
The same concept as HasSpaceAvailable however this will return an error if there is no space, rather than a boolean value.
func (*Filesystem) HasSpaceFor ¶
func (fs *Filesystem) HasSpaceFor(size int64) error
Helper function to determine if a server has space available for a file of a given size. If space is available, no error will be returned, otherwise an ErrNotEnoughSpace error will be raised.
func (*Filesystem) IsIgnored ¶
func (fs *Filesystem) IsIgnored(paths ...string) error
Checks if the given file or path is in the server's file denylist. If so, an Error is returned, otherwise nil is returned.
The path is checked as provided, after being cleaned, and after being cleaned as if it started at the server root. That way neither "foo/../config.yml" nor "../config.yml" can be used to get around an anchored pattern like "/config.yml"; callers do not all clean a leading "/" off the same way before using the path.
The path is also checked after resolving any symlinks in it, since os.Root follows symlinks that stay inside the server directory. Without that a link such as "notes -> config.yml" would give access to a denylisted file.
func (*Filesystem) IsIgnoredNoFollow ¶
func (fs *Filesystem) IsIgnoredNoFollow(paths ...string) error
IsIgnoredNoFollow is IsIgnored for operations that act on a directory entry itself rather than on what it points to: deleting and renaming. Symlinks in the parent directories are followed, since os.Root follows them too, but a symlink at the end of the path is not, so a link to a denylisted file can still be deleted or renamed without the file it points to being touched.
func (*Filesystem) ListDirectory ¶
func (fs *Filesystem) ListDirectory(p string) ([]Stat, error)
ListDirectory lists the contents of a given directory and returns stat information about each file and folder within it. If you only need to know the contents of the directory and do not need mimetype information, call Filesystem.ReadDir directly instead.
func (*Filesystem) MaxDisk ¶
func (fs *Filesystem) MaxDisk() int64
MaxDisk returns the maximum amount of disk space that this Filesystem instance is allowed to use.
func (*Filesystem) Mkdir ¶
func (fs *Filesystem) Mkdir(p string, mode os.FileMode) error
Mkdir creates a single directory, owned by the server user.
func (*Filesystem) NewArchive ¶
func (fs *Filesystem) NewArchive(dir string, opts ...ArchiveOption) (*Archive, error)
NewArchive returns a new archive of the given directory within the server's data directory.
func (*Filesystem) Path ¶
func (fs *Filesystem) Path() string
Path returns the root path for the Filesystem instance.
func (*Filesystem) ReadDir ¶
func (fs *Filesystem) ReadDir(p string) ([]fs2.DirEntry, error)
ReadDir returns all the contents of the given directory.
func (*Filesystem) Rename ¶
func (fs *Filesystem) Rename(from string, to string) error
Rename moves (or renames) a file or directory.
func (*Filesystem) RestoreSymlink ¶
func (fs *Filesystem) RestoreSymlink(name, target string) error
RestoreSymlink creates name as a symbolic link to target, creating any missing parent directories and replacing an existing file or link at that path. It is used when restoring archives that contain symbolic links. The target is stored as-is: every path Wings opens is resolved inside the server's os.Root, so a link pointing outside of it cannot be followed by Wings.
The link is created and chowned under a temporary name and then renamed into place, so an existing entry is only replaced once the new link is ready. A directory is never replaced.
func (*Filesystem) SafeDeleteRecursively ¶
func (fs *Filesystem) SafeDeleteRecursively(p string) error
SafeDeleteRecursively deletes a file or directory while respecting the denylist. Denylisted files and directories are left in place, as is every directory that still contains one of them.
func (*Filesystem) SetDiskLimit ¶
func (fs *Filesystem) SetDiskLimit(i int64)
SetDiskLimit sets the disk space limit for this Filesystem instance.
func (*Filesystem) SpaceAvailableForDecompression ¶
func (fs *Filesystem) SpaceAvailableForDecompression(ctx context.Context, dir string, file string) error
SpaceAvailableForDecompression returns an ErrCodeDiskSpace error when the files in the archive do not fit in the space the server has left, before anything is written, so a request that cannot fit fails without leaving half an archive behind. This is the check main makes.
The sizes come from the archive's own headers, which can be wrong (a zip can claim any size). That is fine: every write during the decompression still goes through a quota-tracked handle, which stops at the limit whatever the headers said. Single-file compression (.gz, .xz and so on) is not checked here because its size is not known without decompressing it; the per-write limit covers it.
func (*Filesystem) Stat ¶
func (fs *Filesystem) Stat(p string) (Stat, error)
Stat stats a file or folder and returns the base stat object from go along with the MIME data that can be used for editing files.
func (*Filesystem) Symlink ¶
func (fs *Filesystem) Symlink(source, target string) error
Symlink creates a symbolic link at "target" pointing to "source". "target" is relative to the root of the server. A relative "source" is relative to the directory the link is created in, as with symlink(2); an absolute "source" is relative to the root of the server. The link is written as a path relative to the directory it is created in so that it resolves to the same file both on the host and inside the server container. Sources that do not exist, or that are outside the root of the server, are refused.
os.Root.Symlink allows for the creation of a symlink that targets a file outside the root directory. This isn't the end of the world because every read and write in this package goes through os.Root, which refuses to follow it, and within a container it would just point to something in the container filesystem.
func (*Filesystem) Touch ¶
Touch acts by creating the given file and path on the disk if it is not present already. If it is present, the file is opened using the defaults which will truncate the contents. The opened file is then returned to the caller.
Writes made through the returned handle are accounted against the disk quota of the server, and will fail once the server runs out of space.
func (*Filesystem) TruncateRootDirectory ¶
func (fs *Filesystem) TruncateRootDirectory() error
TruncateRootDirectory removes _all_ files and directories from a server's data directory and resets the used disk space to zero.
func (*Filesystem) Writefile
deprecated
func (fs *Filesystem) Writefile(p string, r io.Reader) error
Writefile writes a file to the system. If the file does not already exist one will be created. This will also properly recalculate the disk space used by the server when writing new files or modifying existing ones.
The size of the data is not known ahead of time, so it is written through a quota-tracked handle which fails as soon as the server runs out of space.
Deprecated: prefer the use of Filesystem.Write, which checks that the file fits within the disk limit before writing anything.
type SpaceCheckingOpts ¶
type SpaceCheckingOpts struct {
AllowStaleResponse bool
}
type Stat ¶
func (*Stat) CTime ¶
CTime returns the time that the file/folder was created.
TODO: remove. Ctim is not actually ever been correct and doesn't actually return the creation time.
func (*Stat) MarshalJSON ¶
type TarProgress ¶
TarProgress .
func NewTarProgress ¶
func NewTarProgress(w *tar.Writer, p *progress.Progress) *TarProgress
NewTarProgress .