vfs

package
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Sep 4, 2026 License: MIT Imports: 12 Imported by: 0

Documentation

Overview

Package vfs assembles the read-only filesystem instigator exports: one logical install set per configured name, each the ordered merge of its layers - SGI CD images opened in place and pre-extracted directories - plus the files instigator generates in memory. The assembled tree is an io/fs.FS, and every path in it resolves to exactly one Origin naming the layer or generator its bytes came from.

Index

Constants

This section is empty.

Variables

View Source
var ErrNotFound = errors.New("not found")

ErrNotFound is returned for a logical path that does not resolve in the assembled tree.

Functions

This section is empty.

Types

type Disc

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

Disc is one opened CD image: its volume header and the EFS filesystem inside it.

func OpenImage

func OpenImage(path string) (*Disc, error)

OpenImage opens an SGI CD image at a filesystem path.

func OpenImageReader added in v0.2.0

func OpenImageReader(r io.ReaderAt, c io.Closer, name string) (*Disc, error)

OpenImageReader opens an SGI CD image from an arbitrary reader: parse the volume header at block 0, locate the EFS partition, open the EFS inside it. c is closed by Disc.Close; name appears in errors.

func (*Disc) Close

func (d *Disc) Close() error

Close releases the disc's underlying resource.

func (*Disc) FS

func (d *Disc) FS() *efs.FS

FS returns the disc's filesystem.

func (*Disc) FSys added in v0.2.0

func (d *Disc) FSys() fs.FS

FSys returns the disc's filesystem as an io/fs.FS.

func (*Disc) Header

func (d *Disc) Header() *dvh.Header

Header returns the disc's volume header.

type File

type File interface {
	fs.File
	io.ReaderAt
	Size() int64
}

File is an opened regular file: a standard fs.File that also supports random access, which TFTP and instcmd need.

type LayerSpec

type LayerSpec struct {
	Name   string
	Source string
	Base   string
	Dist   string
	Stand  string
	Boot   bool
}

LayerSpec is one ordered contribution to an install set: a source reference and the distribution directory within it to merge.

Source is the layer's source reference - a local path (an SGI EFS disc image, or a pre-extracted read-only directory) or an http(s) URL - which the Resolver turns into a read-only filesystem. An image is opened once and shared across every view of it; a directory is opened with os.OpenRoot so served paths cannot escape it through a symlink.

Base rebases the layer within that source: Dist and Stand are joined under it, so a source whose tree sits below a subdirectory - an extracted archive, say - names that subdirectory here and the rest of the layer reads as if it were the root. Empty means the source root.

Dist names the distribution directory inside the (possibly rebased) source, and it always lands on the set's own dist. Ordinary media call it "dist", which is the default when Dist is empty. A version-stub disc keeps its real catalog somewhere else - "dist6.5" at the root, or "dist/dist6.5" hidden behind a .redirect - and naming it here rebases it, so inst only ever sees /<set>/dist however the media were laid out.

Boot marks the one layer per set whose stand directory is served at /<set>/stand, where the PROM fetches fx.64. Stand names it, defaulting to "stand"; only a bootable set needs one; sa and the miniroot live under dist and merge like everything else.

Name identifies the layer in origins, collision winners, and the startup report.

type Metadata

type Metadata struct {
	Ino    uint64
	UID    uint32
	GID    uint32
	Nlink  int
	Origin Origin
}

Metadata is FileInfo.Sys() for a tree path: the fields ls -l/-i and the recorder need beyond fs.FileInfo. Ino is the stable per-path inode.

type Origin

type Origin struct {
	Kind   OriginKind
	Source string
	Path   string
}

Origin is the resolved provenance of one served path: which configured layer or generator produced its bytes, and where within that source the bytes live. Every file in the tree resolves to exactly one Origin - generated files included - so a caller (the served-file manifest log, the install recorder) can always name what it just read.

Source is the configured layer name (image and directory origins) or the generator name (generated origins). Path is the source-relative path - the in-image or in-directory path - and is empty for a generated file, whose bytes exist only in memory.

type OriginKind

type OriginKind int

OriginKind is where a served file's bytes come from.

const (
	// OriginImage is a file inside a configured EFS disc image.
	OriginImage OriginKind = iota + 1
	// OriginDirectory is a file inside a configured read-only directory
	// layer, opened with os.OpenRoot.
	OriginDirectory
	// OriginGenerated is a file instigator synthesizes in memory: the
	// admin-source command file and .related_dists. It has
	// no backing media.
	OriginGenerated
)

func (OriginKind) String

func (k OriginKind) String() string

type Resolved added in v0.2.0

type Resolved struct {
	FS     fs.FS
	Kind   OriginKind
	Closer io.Closer
}

Resolved is a layer's source, opened: the read-only filesystem it serves, the kind of payload it is, and the closer that frees it.

type Resolver added in v0.2.0

type Resolver interface {
	Resolve(ref string) (Resolved, error)
}

Resolver turns a layer's source reference - a local path or a URL - into a read-only filesystem, the kind of payload it is, and the closer that frees it.

type SetSpec

type SetSpec struct {
	Name       string
	Layers     []LayerSpec
	Collisions map[string]string
}

SetSpec is one logical install set: an ordered list of layers merged into /<Name>/dist, plus the exact collision winners that resolve differing files. A set with a boot layer also serves /<Name>/stand.

Layers merge in order. Directories union; a regular file present in more than one layer must be byte-identical (its origin then being the earliest contributing layer) unless Collisions names a winner. Collisions maps a full logical tree path (for example "applications/dist/inst.README") to the Name of the layer whose copy wins; a differing collision with no matching entry fails Build, so the served bytes are never guessed.

type Tree

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

Tree is the assembled install-set filesystem: one directory per configured set, each the ordered merge of that set's layers, plus whatever instigator generates in memory. It is read-only and safe for concurrent use once Build returns.

Names are io/fs names throughout - "." for the root, no leading slash, no ".." - so a client can only ever address a path the build itself materialized. Protocol adapters strip or add the leading slash their wire format wants.

func Build

func Build(sets []SetSpec, r Resolver) (*Tree, error)

Build assembles the configured install sets into one read-only tree. Each set becomes a directory holding the ordered merge of its layers' distribution directories at <set>/dist, plus <set>/stand from the set's boot layer if it has one; no disc name appears anywhere in the result. The resolver r opens each layer's source - local path or remote URL - and every unique source is opened once and stays open for the tree's life, so Close it when done.

A layer's Dist and Stand are joined under its Base, so a source whose tree sits below a subdirectory is read as if that subdirectory were the root.

Build fails rather than guess: a layer whose source or distribution directory is missing, a boot layer whose source has no stand directory, a file present with different bytes in two layers and no configured winner for that exact path, a configured winner no layer delivers, or a symlink that does not resolve, contained, to a regular file all stop the build. Content is read lazily on Open; only files two layers both claim are read here, to compare them.

func (*Tree) AddGenerated

func (t *Tree) AddGenerated(name, generator string, content []byte) error

AddGenerated inserts a file instigator synthesizes in memory at the given io/fs path, creating any missing parent directories, and records generator as its origin. Generated files then read, list, stat and resolve exactly like backed ones - there is no side map for a caller to miss.

An existing regular file at path is shadowed: its bytes and origin are replaced. That is how the generated .related_dists menu aid takes over the stock copy a primary layer's media ships. An existing directory is an error, because burying a directory of served media under one file is never what a generator means.

func (*Tree) Close

func (t *Tree) Close() error

Close releases every source the build opened.

func (*Tree) Open

func (t *Tree) Open(name string) (fs.File, error)

Open opens a tree path. A directory opens as an fs.ReadDirFile; a regular file opens as a File, so a caller that needs random access can assert for it.

func (*Tree) ReadDir

func (t *Tree) ReadDir(name string) ([]fs.DirEntry, error)

ReadDir lists a tree directory, sorted lexically.

func (*Tree) Resolve

func (t *Tree) Resolve(name string) (Origin, error)

Resolve reports where a tree path's bytes come from: the configured layer or generator, and the path within it. Every file resolves, generated ones included, so a served-file manifest line can always name its source. The tree root and the set directories are structural - no single layer backs them - and resolve to the zero Origin.

func (*Tree) Stat

func (t *Tree) Stat(name string) (fs.FileInfo, error)

Stat describes a tree path. Sys reports a *Metadata: the stable inode, the owner and link count, and the resolved origin.

Jump to

Keyboard shortcuts

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