Documentation
¶
Overview ¶
Package fsops defines the Backend interface that abstracts filesystem operations for qui's services. Current implementations: Local (delegates to os.* on the qui host) and Noop (returns ErrNoFilesystemAccess for instances without filesystem access). A Remote implementation (SSH-backed) is planned. Services still call os.* directly; they adopt this interface in a separate callsite migration, after which the transport is transparent to them.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrNoFilesystemAccess is returned by the NoopBackend for instances that // have no filesystem access configured (neither local nor remote). ErrNoFilesystemAccess = errors.New("filesystem access is not configured for this instance") )
Sentinel errors returned by Backend implementations.
Functions ¶
This section is empty.
Types ¶
type Backend ¶
type Backend interface {
// Stat returns metadata for a single path, following symlinks — FileID
// and Nlinks describe the target, so symlinked torrent data keeps its
// identity. Returns a non-nil error wrapping fs.ErrNotExist if the path
// does not exist. A failure to resolve identity is reported in
// LstatInfo.FileIDErr, not as a Stat error, so one identity-opaque file
// cannot fail callers that only need metadata.
Stat(ctx context.Context, path string) (*LstatInfo, error)
// Lstat is like Stat but does not follow symlinks.
Lstat(ctx context.Context, path string) (*LstatInfo, error)
// ReadDir returns directory entries.
ReadDir(ctx context.Context, path string) ([]DirEntry, error)
// WalkDir walks a directory tree and streams entries on the returned channel.
// The channel is closed when the walk completes, is cancelled via ctx, or
// hits an unrecoverable error. Callers must drain the channel or cancel
// ctx; abandoning it leaks the walk goroutine. Entries whose metadata
// cannot be read are skipped, not emitted — WalkEntry.Err carries only
// enumeration-level walk failures. Setting opts.EmitStatErrors emits
// those entries instead, with WalkEntry.StatErr set and only Path/RelPath
// valid, so delete preflights can fail closed on unverifiable paths.
WalkDir(ctx context.Context, root string, opts WalkOptions) (<-chan WalkEntry, error)
// Statfs returns free/total bytes for the filesystem containing path.
Statfs(ctx context.Context, path string) (*StatfsResult, error)
// SameFilesystem returns true if both paths reside on the same filesystem
// (same device ID on Unix, same volume serial on Windows).
SameFilesystem(ctx context.Context, p1, p2 string) (bool, error)
// MkdirAll creates a directory and all parents. Equivalent to os.MkdirAll.
// For torrent content and link-tree dirs, pass fsutil.ContentDirMode /
// fsutil.LinkTreeBaseDirMode rather than a hand-typed mode (#1704, #2086).
MkdirAll(ctx context.Context, path string, perm fs.FileMode) error
// Remove removes a file or directory. If opts.Recursive is true, removes
// the entire tree (like os.RemoveAll).
Remove(ctx context.Context, path string, opts RemoveOptions) error
// HardlinkTree creates a hardlink tree from plan. Rolls back what it
// created on partial failure. The result records the files and dirs this
// call made, for a later RemoveTree.
HardlinkTree(ctx context.Context, plan *hardlinktree.TreePlan) (*TreeCreateResult, error)
// ReflinkTree creates a reflink (CoW) tree from plan. Rolls back what it
// created on partial failure. The result records the files and dirs this
// call made, for a later RemoveTree.
ReflinkTree(ctx context.Context, plan *hardlinktree.TreePlan) (*TreeCreateResult, error)
// RemoveTree removes exactly the files and dirs recorded in created —
// never the whole plan, which could delete links shared with sibling
// torrents (discussion #2282). A plan root that already existed before
// the create is therefore NOT removed; callers own pruning it. Safe to
// call with a nil result.
RemoveTree(ctx context.Context, created *TreeCreateResult) error
// SupportsReflink returns whether the filesystem at path supports CoW
// reflinks. The string return is a human-readable reason when unsupported.
SupportsReflink(ctx context.Context, path string) (bool, string, error)
}
Backend abstracts filesystem operations so services work identically against a local filesystem or a future SSH-backed remote. It covers exactly the operations qui's services need: syscall-level primitives (stat, walk, mkdir, remove) plus the high-level tree operations (HardlinkTree, ReflinkTree, RemoveTree) that create-and-rollback as a unit. Path manipulation (filepath.Clean, filepath.Rel, etc.) is not part of this interface — it stays as direct calls in service code.
Every method accepts a context.Context and must respect cancellation.
Error semantics are portable across implementations: a missing path is reported compatibly with errors.Is(err, fs.ErrNotExist) and a denied one with errors.Is(err, fs.ErrPermission) — from Stat, Lstat, ReadDir, WalkDir (on entries), Remove, and Statfs alike. Remote backends must map their transport's errors onto the same sentinels.
type FileInfo ¶
type FileInfo struct {
Path string
Size int64
ModTime time.Time
IsDir bool
IsSymlink bool
Mode fs.FileMode
}
FileInfo holds metadata from a Stat call.
type LstatInfo ¶
type LstatInfo struct {
FileInfo
FileID hardlink.FileID
Nlinks uint64
// FileIDErr is set when FileID/Nlinks could not be resolved (e.g. a
// Windows ACL denial on an otherwise statable file). The rest of the
// struct is still valid; callers that need identity must check this
// instead of treating the whole stat as failed.
FileIDErr error
}
LstatInfo holds metadata from an Lstat call, including hardlink identity.
type Pool ¶
type Pool struct {
// contains filtered or unexported fields
}
Pool resolves an instance ID to the appropriate Backend. For instances with local filesystem access it returns the local backend; for instances without access it returns a noop backend that errors on every call. A future remote backend slots in here for instances with SSH access configured.
type RemoveOptions ¶
type RemoveOptions struct {
Recursive bool
}
RemoveOptions controls the behavior of a Remove call.
type StatfsResult ¶
StatfsResult holds filesystem space information.
type TreeCreateResult ¶
TreeCreateResult holds the outcome of a HardlinkTree or ReflinkTree call. Files and Dirs record what the call actually created on disk (pre-existing paths are excluded), so RemoveTree can undo exactly this call's work without touching links shared with sibling torrents (discussion #2282).
type WalkEntry ¶
type WalkEntry struct {
LstatInfo
RelPath string
Err error
// StatErr is set when the entry was enumerated but its metadata lookup
// failed; only Path and RelPath are valid then. Such entries are emitted
// only when WalkOptions.EmitStatErrors is set and skipped otherwise.
StatErr error
}
WalkEntry is emitted by WalkDir for each filesystem entry encountered.
type WalkOptions ¶
type WalkOptions struct {
SkipHidden bool
// IgnoreDirNames are directory basenames to skip, matched case-insensitively
// (OS/NAS metadata dirs like $RECYCLE.BIN and @eaDir vary in on-disk case).
IgnoreDirNames []string
// IgnoreDirNamePrefixes are matched case-insensitively.
IgnoreDirNamePrefixes []string
IgnorePaths []string
// WantFileID populates FileID and Nlinks on regular-file entries.
WantFileID bool
// EmitStatErrors emits entries whose metadata lookup failed with StatErr
// set instead of silently skipping them. Consumers that delete based on
// walk results use this to fail closed on paths they cannot verify.
EmitStatErrors bool
}
WalkOptions controls the behavior of a WalkDir call.
Directories
¶
| Path | Synopsis |
|---|---|
|
Package local implements fsops.Backend by delegating to the local filesystem via os.*, pkg/hardlinktree, pkg/reflinktree, pkg/hardlink, and pkg/fsutil.
|
Package local implements fsops.Backend by delegating to the local filesystem via os.*, pkg/hardlinktree, pkg/reflinktree, pkg/hardlink, and pkg/fsutil. |