fs

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 15, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package fs implements blob.Store on a local directory tree. It is the "no bucket" storage option and the target of `backyard deploy --method rsync`, and also works on top of mounted buckets (gcsfuse, blobfuse2; see below for mountpoint-s3).

Keys map to files below the root directory ("sites/foo/index.html" → <root>/sites/foo/index.html). All access goes through os.Root handles, so no operation can reach outside the root. Beyond that, every directory on a key's path is opened one component at a time and must be a real directory (verified against its Lstat result); files are then created, renamed, read and removed by name relative to that directory handle. A concurrent writer below the root (e.g. a racing rsync) that swaps a directory for a symlink therefore cannot redirect a write, read or delete to another part of the tree (such as a database file kept in the root).

Writes are atomic: data is written to a hidden temporary file in the destination directory and renamed into place. Path segments starting with ".backyard-tmp-" are reserved for these files: such keys are rejected with blob.ErrInvalidKey and such entries are hidden from List.

Because files may be written by tools other than Backyard (rsync), object metadata is derived from the file itself:

  • ETag is a hash of size and modification time (nanoseconds), so it changes whenever rsync replaces a file. Put sets a fresh, unique mtime.
  • Content type comes from blob.DetectContentType (extension, else sniffing); the contentType argument of Put is not persisted.

Symbolic links (rsync -a preserves them) are handled conservatively: a symlink is only followed when it is the last path component and its target is a relative path without ".." segments (so it resolves within the link's own directory subtree); chains are followed up to 8 links. Symlinked directories, absolute targets and targets containing ".." are never followed; such entries are invisible to Get/Stat/List. Directories reached through symlinks are never written to, listed or deleted from.

Writes need rename support, so the fs store cannot write on mountpoint-s3; use the s3 backend there.

The fs store cannot presign URLs; PresignPut and PresignGet return blob.ErrNotSupported (the deploy gateway serves self-hosted upload URLs instead).

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Option

type Option func(*Store)

Option configures a Store.

func WithFsync

func WithFsync(on bool) Option

WithFsync makes Put fsync the file before renaming it into place and the directory afterwards (durable, slower). Default off.

func WithLogger

func WithLogger(l *slog.Logger) Option

WithLogger sets the logger (default slog.Default()).

type Store

type Store struct {
	// contains filtered or unexported fields
}

Store is a blob.Store backed by a local directory. It is safe for concurrent use.

func New

func New(dir string, opts ...Option) (*Store, error)

New opens (creating it if needed) the directory dir as a blob store.

func (*Store) Close

func (s *Store) Close() error

Close releases the root directory handle. It is safe to call more than once.

func (*Store) Delete

func (s *Store) Delete(ctx context.Context, key string) error

Delete removes an object; missing objects (and directories) are ignored. A symlink key removes the link, never its target.

func (*Store) DeletePrefix

func (s *Store) DeletePrefix(ctx context.Context, prefix string) error

DeletePrefix removes every object whose key starts with prefix and prunes directories left empty. Symlinks are removed, never followed. An empty prefix is rejected.

func (*Store) Describe

func (s *Store) Describe() blob.Description

Describe returns {type: "fs"}; the local path is deliberately not exposed.

func (*Store) Dir

func (s *Store) Dir() string

Dir returns the absolute root directory.

func (*Store) Get

func (s *Store) Get(ctx context.Context, key string) (io.ReadCloser, *blob.ObjectInfo, error)

Get opens an object for reading.

func (*Store) GetRange

func (s *Store) GetRange(ctx context.Context, key string, offset, length int64) (io.ReadCloser, *blob.ObjectInfo, error)

GetRange reads length bytes from offset (length < 0 = to the end). The returned ObjectInfo describes the whole object. Ranges past the end yield an empty body.

func (*Store) List

func (s *Store) List(ctx context.Context, prefix, delimiter string) (*blob.ListResult, error)

List returns objects under prefix sorted by key. With delimiter "/", sub-directories that contain at least one object are returned as Prefixes.

func (*Store) Ping

func (s *Store) Ping(ctx context.Context) error

Ping verifies the root directory is writable.

func (*Store) PresignGet

func (s *Store) PresignGet(_ context.Context, key string, _ time.Duration) (*blob.PresignedRequest, error)

PresignGet is not supported by the fs backend.

func (*Store) PresignPut

PresignPut is not supported by the fs backend.

func (*Store) Put

func (s *Store) Put(ctx context.Context, key string, r io.Reader, size int64, contentType string) (*blob.ObjectInfo, error)

Put writes an object atomically. The contentType argument is not stored: the fs backend always derives content types from the key (and content).

func (*Store) Stat

func (s *Store) Stat(ctx context.Context, key string) (*blob.ObjectInfo, error)

Stat returns object metadata or blob.ErrNotFound.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL