oaknut.filesystem

The pluggable filesystem contract shared by the disc family. A filesystem (Acorn DFS, Watford DFS, ADFS, AFS, …) is the unit of extension, registered on the oaknut.filesystem entry-point axis. Each Filesystem detects itself (probe()), opens a region into a Mount exposing a small core plus opt-in capability protocols, and declares its physical Geometry grammar.

Geometry (the physical byte→sector layout) and the filesystem (the logical structure) are kept strictly apart. identify() runs the registered filesystems over an image, ranks the candidates, and recurses into reserved regions to build a per-partition Identification tree — depending on, and importing, no concrete filesystem package.

Every name documented here is importable directly from oaknut.filesystem.

The filesystem contract

class oaknut.filesystem.Filesystem(name, **kwargs)

Base class for a pluggable filesystem.

Registered under oaknut.filesystem in a package’s pyproject.toml:

[project.entry-points."oaknut.filesystem"]
acorn_dfs = "oaknut.dfs.filesystem:AcornDFS"

The entry-point key (acorn-dfs) is the filesystem’s user-facing name: enumerated by disc list-filesystems, explained by disc describe-filesystem, and forced by --filesystem.

Parameters:

name (str)

extensions: frozenset[str] = frozenset({})

Extensions conventionally used for this filesystem (lower-case, with leading dot). Consulted by the coordinator only to break ties between equally-confident candidates — never to identify.

priority: int = 0

Ordering hint among same-confidence, same-extension candidates; higher wins (e.g. Watford outranks Acorn DFS, which excludes it).

creates: frozenset[str] = frozenset({})

Extensions this filesystem is the default creator for — disc create infers the filesystem from the target’s extension via this. A subset of (or disjoint from) extensions: a niche variant (Watford) or a non-standalone filesystem (AFS, made inside an ADFS disc) leaves it empty and is reached only via --filesystem.

wildcard_syntax: WildcardSyntax = WildcardSyntax(metacharacters=(('*', 'any sequence of characters'), ('?', 'exactly one character')))

This filesystem’s filename wildcard vocabulary, reported by disc describe-filesystem. Defaults to Unix (* / ?); the Acorn filing systems override it with * / # (? literal).

abstractmethod probe(reader)

Inspect the region in reader; identify it, or return None.

On a match, return an Identification carrying the confidence, evidence, the proposed geometry (only this filesystem can read its own capacity hints), any geometry ambiguities the bytes cannot settle, and — for a host filesystem — the reserved_regions for the coordinator to recurse into. Must not raise on data that simply isn’t this filesystem.

Parameters:

reader (ImageReader)

Return type:

Identification | None

abstractmethod open(reader, geometry, *, surface=0)

Open the region in reader at geometry, returning a mount.

The returned object implements Mount plus whichever capability protocols this filesystem supports. surface selects which volume of a multi-volume image to open (a DFS side); the default 0 is the whole image / first volume, which is all most filesystems have.

Parameters:
Return type:

Mount

split_volume(inner_path, geometry, ambiguities=())

Split a leading volume token from inner_path.

Returns (surface_index, geometry, residual_path). The returned geometry may differ from the one passed in, because the volume token can imply a geometry — a non-zero DFS drive on a length-ambiguous image implies the double-sided reading drawn from ambiguities. The default has no notion of a sub-volume: surface 0, the geometry unchanged, and the whole path. DFS overrides this to parse the Acorn :drive. prefix.

Parameters:
Return type:

tuple[int, Geometry, str]

volumes(geometry)

The independently-addressable volumes at geometry.

The default is a single, undesignated volume — most filesystems span the whole image. A double-sided DFS reports one per side, designated :0 / :2. Round-trips with split_volume(): every designation here parses back to the same surface.

Parameters:

geometry (Geometry)

Return type:

tuple[Volume, …]

designation_for(surface, geometry)

The user-facing designation of surface, for diagnostics.

Looks the surface up among volumes(), so messages quote the filesystem’s own vocabulary (:2, not the cardinal index). A surface with no enumerated volume falls back to :N so a diagnostic about an absent second side still reads naturally.

Parameters:
Return type:

str

abstractmethod geometry_grammar()

The geometries this filesystem supports — presets and kinds.

Used to resolve --geometry and to enumerate choices for disc create and describe-filesystem.

Return type:

GeometryGrammar

default_geometry(suffix)

The geometry to create a suffix image with, or None.

None means there is no sensible default for this extension — it is ambiguous (ADFS .adf could be S or M) or open-ended (a hard disc) — so disc create requires an explicit --geometry. The default implementation has none.

Parameters:

suffix (str)

Return type:

Geometry | None

create(filepath, geometry, *, title)

Create a new empty image of this filesystem at filepath.

Filesystems that are not created standalone (AFS lives inside an ADFS disc; archives) do not override this and decline.

Parameters:
Return type:

None

oaknut.filesystem.FILESYSTEM_KIND = 'filesystem'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to ‘utf-8’. errors defaults to ‘strict’.

oaknut.filesystem.FILESYSTEM_NAMESPACE = 'oaknut.filesystem'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to ‘utf-8’. errors defaults to ‘strict’.

Capabilities

A mount exposes a small required core (Mount) plus whichever of these runtime_checkable protocols its filesystem supports. Commands gate on the capability, never on the filesystem type, so a filesystem that cannot do something simply does not implement the protocol.

class oaknut.filesystem.Mount(*args, **kwargs)

The core every mounted filesystem provides.

Paths are strings in the filesystem’s own syntax ($.DIR.FILE for Acorn, DIRFILE for FAT, D.DIR.FILE for a DDOS volume); the filesystem parses them — the CLI never does.

path_root()

The root path string (e.g. "$" for Acorn filesystems).

Return type:

str

stat(path)

The Entry for path (name, kind, length, full path).

Parameters:

path (str)

Return type:

Entry

join(parent, name)

The path of child name under directory parent.

The filesystem owns its path syntax ($.A for Acorn, the root sometimes nameless), so the CLI builds new paths through this rather than concatenating — needed when creating a path that does not exist yet (e.g. a bulk import target).

Parameters:
Return type:

str

iter_entries(path)

Yield the entries of the directory at path.

Parameters:

path (str)

Return type:

Iterable[Entry]

exists(path)

Whether anything exists at path.

Parameters:

path (str)

Return type:

bool

read_bytes(path)

The contents of the file at path.

Parameters:

path (str)

Return type:

bytes

write_bytes(path, data)

Write data to path, creating or replacing the file.

Parameters:
Return type:

None

remove(path, *, force=False)

Delete the file or directory at path.

A directory is removed if the filesystem represents one (a flat catalogue has none, so removing its notional directory is a no-op). force overrides a lock — the filesystem unlocks the entry first, owning its own locked-entry semantics so the access byte’s layout never leaks to the caller.

Parameters:
Return type:

None

rename(old_path, new_path)

Rename / move the entry at old_path to new_path in place.

Parameters:
  • old_path (str)

  • new_path (str)

Return type:

None

class oaknut.filesystem.Entry(name, is_dir, length=0, path='')

One directory entry, in filesystem-agnostic terms.

Acorn-specific metadata (load/exec/access) is reached through the AcornMetadata capability, not carried here, so a foreign filesystem’s entries need none of it.

Parameters:
path: str = ''

The entry’s full in-partition path, so a caller can address it (e.g. fetch its metadata) without re-joining in the filesystem’s own syntax. Empty only for a bare, unaddressed entry.

class oaknut.filesystem.HierarchicalDirectories(*args, **kwargs)

The filesystem nests directories arbitrarily (ADFS, AFS, FAT, DDOS).

Its absence marks a flat catalogue (Acorn/Watford DFS: a single top-level directory only).

make_directory(path, *, parents=False, exist_ok=False, title=None)

Create a directory at path.

parents creates missing ancestors; exist_ok tolerates an existing directory. title sets the new directory’s title where the filesystem supports per-directory titles (ADFS) and is rejected (before anything is created) where it does not (AFS).

Parameters:
Return type:

None

class oaknut.filesystem.AcornMetadata(*args, **kwargs)

Files carry Acorn load/exec addresses and an access byte.

acorn_meta(path)

The Acorn metadata of the file at path.

Parameters:

path (str)

Return type:

AcornMeta

set_acorn_meta(path, meta)

Replace the Acorn metadata of the file at path.

Parameters:
Return type:

None

class oaknut.filesystem.Titled(*args, **kwargs)

The disc carries a title / name (DFS, ADFS, AFS).

property title: str

The disc title / name.

set_title(title)

Set the disc title / name.

Parameters:

title (str)

Return type:

None

class oaknut.filesystem.DirectoryTitled(*args, **kwargs)

Directories carry their own title, distinct from the disc’s (ADFS).

Its absence marks a filesystem whose directories have no title field (DFS, AFS) — setting one there is rejected.

directory_title(path)

The title of the directory at path.

Parameters:

path (str)

Return type:

str

set_directory_title(path, title)

Set the title of the directory at path.

Parameters:
Return type:

None

class oaknut.filesystem.Bootable(*args, **kwargs)

The disc carries a *OPT 4 boot option (DFS, ADFS).

property boot_option: BootOption

The disc’s *OPT 4 boot option.

set_boot_option(option)

Set the disc’s *OPT 4 boot option.

Parameters:

option (BootOption | int)

Return type:

None

class oaknut.filesystem.FreeSpace(*args, **kwargs)

The filesystem reports its free space (ADFS, AFS).

free_bytes()

Free space remaining, in bytes.

Return type:

int

class oaknut.filesystem.FreeMap(*args, **kwargs)

The filesystem can report which of its sectors are free.

free_map()

The free-space map as partition-relative sector runs.

Return type:

FreeMapData

class oaknut.filesystem.FreeMapData(free_regions, total_sectors)

A filesystem’s free space as partition-relative sector runs.

Carries no geometry: the renderer lays the total_sectors out as a sector matrix sized to the terminal, marking those in free_regions free and the rest used. Each region is (start_sector, length).

Parameters:
class oaknut.filesystem.Sized(*args, **kwargs)

The filesystem reports its own occupied size (its partition’s span).

size_bytes()

The size of this filesystem’s partition, in bytes.

For a filesystem sharing a disc (ADFS with an AFS tail) this is its slice, not the whole image — so partition sizes sum to the disc.

Return type:

int

class oaknut.filesystem.PhysicalGeometry(*args, **kwargs)

The filesystem knows the disc’s physical geometry (ADFS, AFS).

A flat-catalogue floppy filesystem (DFS) records no geometry and does not advertise this.

disc_geometry()

The disc’s physical geometry.

Return type:

DiscGeometry

class oaknut.filesystem.DiscGeometry(label, sectors_per_cylinder, total_sectors)

A disc’s physical geometry, for the stat summary.

label is a human description in the filesystem’s own vocabulary (ADFS speaks cylinders/heads/track; AFS speaks cylinders/sectors-per- cylinder). sectors_per_cylinder lets the caller place a partition’s logical-sector span into a cylinder range without parsing the label.

Parameters:
  • label (str)

  • sectors_per_cylinder (int)

  • total_sectors (int)

class oaknut.filesystem.Compactable(*args, **kwargs)

The filesystem can defragment in place, consolidating free space.

compact(*, order=())

Defragment, returning a filesystem-defined measure of work done.

order is a partial list of paths to lay down first, in the lowest/earliest positions (in the given order); files it does not name follow in their current order. It lets a caller place boot or loader files where they load fastest. A filesystem whose layout order is fixed or undefined rejects a non-empty order; the CLI offers --order only where the mount also reports a storage order (StorageOrdered).

Parameters:

order (Sequence[str])

Return type:

int

class oaknut.filesystem.Validatable(*args, **kwargs)

The filesystem can check its on-disc structure for defects.

validate()

Return a list of structural defects (empty when clean).

The entries are the filesystem’s own validation-error objects, rendered by the CLI’s error formatter; the caller treats them opaquely.

Return type:

list

class oaknut.filesystem.StatusReporting(*args, **kwargs)

The filesystem can report human-readable status notes for stat.

Notes are short advisories about the partition as a whole — for example that a ROMFS image is an incomplete fragment of a multi-ROM set, or is read-only because it carries code after the filing system. disc stat renders them as a line; most filesystems have nothing to say and do not implement this.

status_notes()

Short status advisories for this partition (empty when none).

Return type:

tuple[str, …]

class oaknut.filesystem.StorageOrdered(*args, **kwargs)

The filesystem can order its paths by physical position on the medium.

storage_key() returns an opaque sort key for a path; sorting a directory’s siblings by it yields the order in which their data is laid down on the medium — ascending start sector for a random-access filesystem (DFS, ADFS), stream order for a sequential one (CFS/ROMFS). A multi-file cp uses it to reproduce the source’s on-disc order at the destination instead of reversing it (a flat catalogue read highest-sector-first, re-laid lowest-sector-first, would otherwise flip the order and slow loading on a seeking drive).

The key is comparable only against other keys from the same mount and carries no meaning beyond ordering — the caller never inspects it. Filesystems with no storage order (a hash table) or one that is ill-defined (a fragmented AFS file spans many extents, so it has no single position) do not implement this.

storage_key(path)

An opaque, sortable key for path’s position on the medium.

Parameters:

path (str)

Return type:

SupportsRichComparison

class oaknut.filesystem.WildcardMatching(*args, **kwargs)

The filesystem owns its filename wildcard syntax and matching.

Acorn filing systems glob with * and #, and ? is an ordinary filename character; a DOS/FAT filesystem globs with * and ?. The CLI defers to the mount so a pattern is read in the filesystem’s own terms, falling back to a Unix default (* / ?) for a mount that does not implement this.

property wildcard_syntax: WildcardSyntax

This filesystem’s wildcard vocabulary, for help and diagnostics.

is_pattern(name)

Whether name contains any wildcard metacharacter of this syntax.

Parameters:

name (str)

Return type:

bool

matches(pattern, name)

Whether name matches the wildcard pattern under this syntax.

Parameters:
Return type:

bool

class oaknut.filesystem.WildcardSyntax(metacharacters)

A filesystem’s filename-wildcard vocabulary, for help and errors.

Each pair is (metacharacter, what it matches) — Acorn filing systems use * and #; a DOS/FAT filesystem uses * and ?. This carries only the human-facing description; the matching itself is WildcardMatching.matches(), since a syntax like DOS 8.3 is more than a choice of metacharacters.

Parameters:

metacharacters (tuple[tuple[str, str], ...])

property chars: str

Just the metacharacters, e.g. "*#" — for detecting a pattern.

summary()

A one-line gloss, e.g. "* (any sequence), # (one character)".

Return type:

str

class oaknut.filesystem.UserDatabase(*args, **kwargs)

The filesystem has user accounts (AFS passwords / quota).

user_names()

The names of the registered users.

Return type:

tuple[str, …]

class oaknut.filesystem.RegionHost(*args, **kwargs)

The filesystem reserves regions another filesystem may occupy.

An ADFS host reserves tail cylinders that an AFS or (DRDOS) FAT filesystem lives in; the coordinator recurses into these. The host stays ignorant of what occupies them.

reserved_regions()

The regions reserved within this filesystem, for recursion.

Return type:

tuple[‘Partition’, …]

Geometry

The physical layout beneath a filesystem. A filesystem declares a GeometryGrammar (named presets plus a parameterised form), --geometry is resolved against it, and probe() proposes one in the same terms.

class oaknut.filesystem.Geometry(surface_specs, label='', cylinders=None, heads=None, sectors_per_track=None)

A physical layout: the surface specs an image is read through.

Pure geometry — no catalogue or filesystem. label is a short human description (e.g. "ADFS-L (80T DS interleaved)").

cylinders/heads/sectors_per_track are the optional CHS the layout was built from — a hard disc’s, carried so a filesystem can report it (the surface specs themselves linearise CHS away). They are None when the source did not record CHS.

Parameters:
property image_size: int

Total bytes a full image in this geometry occupies.

property num_sectors: int

Total logical sectors across all surfaces.

class oaknut.filesystem.GeometryGrammar(presets=<factory>, kinds=())

How a filesystem accepts a geometry on the command line / API.

presets are the enumerable named layouts (s/m/l for ADFS floppies); kinds are the parameterised forms it also accepts (floppy and/or winchester). parse() resolves a string to a Geometry, trying a preset name first, then a parameterised key=value form.

Parameters:
oaknut.filesystem.floppy_geometry(*, tracks, sides, sectors_per_track=10, bytes_per_sector=256, interleaved=True, label='')

Build a floppy Geometry.

sides is 1 or 2; for double-sided, interleaved selects the Acorn-conventional interleaved layout (side 0/side 1 alternating per track) over the sequential one.

Parameters:
  • tracks (int)

  • sides (int)

  • sectors_per_track (int)

  • bytes_per_sector (int)

  • interleaved (bool)

  • label (str)

Return type:

Geometry

oaknut.filesystem.winchester_geometry(*, cylinders, heads, sectors_per_track, bytes_per_sector=256, label='')

Build a hard-disc Geometry as one linear sector surface.

Acorn hard-disc images present a flat linear sector space; the CHS figures determine its extent. (They are also recorded in a .dsc sidecar, but the image itself is linear.)

Parameters:
  • cylinders (int)

  • heads (int)

  • sectors_per_track (int)

  • bytes_per_sector (int)

  • label (str)

Return type:

Geometry

oaknut.filesystem.geometry_from_dsc(dsc_bytes, *, sectors_per_track=33)

Build a hard-disc Geometry from a 22-byte .dsc sidecar.

Geometry resolution, not filesystem identification: the .dsc carries the CHS a hard-disc image’s bytes cannot, so the caller can report it. Raises GeometryError on a malformed sidecar.

Parameters:
  • dsc_bytes (bytes)

  • sectors_per_track (int)

Return type:

Geometry

oaknut.filesystem.region_reader(reader, geometry, start_sector, num_sectors)

A reader over the logical sector run [start_sector, +num_sectors).

When the host is linear (no geometry, or a single contiguous surface — a hard disc), the run is a byte window that shares the backing, so it is cheap and inherits the host’s writability: writes to a tail filesystem reach the file. When the host is interleaved (a double-sided floppy) the run’s bytes are scattered, so the host’s UnifiedDisc de-interleaves them into a contiguous view a tail filesystem can address linearly. That view is a copy, so it is read-only: writing to an interleaved reserved region would not reach the file, and is refused rather than silently lost.

Parameters:
Return type:

ImageReader

oaknut.filesystem.FLOPPY = 'floppy'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to ‘utf-8’. errors defaults to ‘strict’.

oaknut.filesystem.WINCHESTER = 'winchester'

str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str

Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to ‘utf-8’. errors defaults to ‘strict’.

Identification

The result model returned by identify(): a tree of per-region Identification nodes, each with a Confidence and the Partition it describes.

class oaknut.filesystem.Confidence(*values)

How sure a filesystem is it identified a region — higher is surer.

Candidates are ranked by this first, so an unambiguous magic number beats a structural heuristic, which beats a guess from size alone.

POSSIBLE = 10

Only weak signals agree — image size, or nothing but the extension.

PROBABLE = 20

Structural heuristics pass (e.g. a well-formed DFS catalogue).

STRONG = 30

Heuristics plus an integrity check agree (checksum, redundant copy).

CERTAIN = 40

An unambiguous on-disc magic number was found (e.g. AFS0).

class oaknut.filesystem.Identification(filesystem, confidence, evidence=(), geometry=None, ambiguities=(), partition=None, reserved_regions=(), contained=<factory>)

What a filesystem reports a region to be.

An empty filesystem marks a region that something reserved but no installed filesystem recognised — so a host disc with an unhandled tail still shows the tail honestly.

Parameters:
filesystem: str

Filesystem extension key ("acorn-dfs"), or "" if unidentified.

confidence: Confidence

How sure the identification is.

evidence: tuple[str, ...] = ()

Human-readable reasons it matched.

geometry: Geometry | None = None

The proposed physical geometry, when determinable.

ambiguities: tuple[Geometry, ...] = ()

Equally-plausible geometries the content cannot distinguish.

partition: Partition | None = None

The region this identifies (None for the whole image / root).

reserved_regions: tuple[Partition, ...] = ()

Regions reserved within this one, for the coordinator to recurse into.

contained: tuple[Identification, ...]

Identifications of those reserved regions (filled by the coordinator).

property identified: bool

True unless this is a reserved-but-unrecognised region.

with_contained(contained)

A copy with contained set (this dataclass is frozen).

Parameters:

contained (tuple[Identification, ...])

Return type:

Identification

class oaknut.filesystem.Partition(name, start_sector, num_sectors, index=0)

A named logical sector region within its parent.

Sectors, not bytes, so a region of an interleaved host (an ADFS-L floppy’s AFS tail) is contiguous: the bytes are scattered, but the logical sectors are a run. The coordinator materialises the bytes through the host’s geometry (see region_reader()).

name is the user-facing selector label — the filesystem the region is identified as ("adfs", "afs") — and index disambiguates several partitions of the same kind (afs.0, afs.1).

Parameters:
  • name (str)

  • start_sector (int)

  • num_sectors (int)

  • index (int)

property selector: str

The path selector for this partition (afs or afs.1).

class oaknut.filesystem.Volume(designation, surface=0)

One independently-addressable volume within a filesystem.

Most filesystems are a single volume spanning the whole image (a sole, undesignated Volume). A double-sided DFS image is the exception: each physical surface is an independent volume with its own catalogue, title and free space, addressed by a filesystem-specific designation — the Acorn drive token :0 / :2 for the DFS family. The designation is the very string a user types to reach the volume, and is what diagnostics quote (never the internal surface index).

Parameters:
  • designation (str)

  • surface (int)

designation: str

The path token addressing this volume (":0", ":2"; "" when the filesystem has a single, undesignated volume).

surface: int = 0

The surface index this volume occupies, passed to open.

The coordinator

Discovery and enumeration over the oaknut.filesystem axis. Every installed filesystem package contributes automatically, so the set grows with what is installed; nothing here imports a concrete filesystem.

oaknut.filesystem.identify(source, *, suffix_hint=None, filesystems=None)

Identify the filesystem(s) on source, best candidate first.

Returns the whole-image candidates ranked by confidence (extension only a tie-breaker), each with its reserved regions recursively identified in Identification.contained. An empty list means no installed filesystem recognised the image.

filesystems overrides the discovered set — used by tests and to simulate a partial install (the extensibility invariant).

Parameters:
Return type:

list[Identification]

oaknut.filesystem.filesystem_names()

The entry-point names of every registered filesystem.

Return type:

list[str]

oaknut.filesystem.describe_filesystem(name, *, single_line=False)

The description of one filesystem (its class docstring).

Parameters:
Return type:

str

oaknut.filesystem.create_filesystem(name)

Instantiate one filesystem by name.

Parameters:

name (str)

Return type:

Filesystem

oaknut.filesystem.creating_filesystem(suffix, *, filesystems=None)

The filesystem that creates suffix images by default, or None.

disc create infers the filesystem from the target’s extension via each filesystem’s creates set. Returns None when no installed filesystem is the default creator for the extension (so the user must pass --filesystem).

Parameters:
Return type:

str | None

Reading images

class oaknut.filesystem.ImageReader(data, *, base=0, length=None, suffix=None, writable=False, _closeables=())

A clamped, read-only view over a region of a disc image.

Construct via reader_for(). A reader covers [base, base + size) of an underlying buffer (bytes, memoryview or mmap.mmap); all offsets passed to read(), find(), and window() are relative to this region.

Parameters:
property size: int

Number of bytes in this region.

property writable: bool

Whether write() (and a live buffer()) is available.

True when the reader is backed by writable storage (a file mapped for writing). Windows inherit it from their parent.

property suffix: str | None

The source file extension (lower-cased, with dot), if known.

A tie-breaking hint for the coordinator only — never present on a window, and filesystems identify by content and ignore it.

read(offset, length)

Return up to length bytes at offset, clamped to the region.

Reading at or past the end yields b""; a range overrunning the end yields only the bytes that exist.

Parameters:
Return type:

bytes

write(offset, data)

Write data at region-relative offset, into the backing store.

Only valid on a writable reader (see writable()); the write reaches the underlying file/buffer directly. Writing past the end of the region is an error rather than a silent truncation.

Parameters:
Return type:

None

buffer()

A buffer over this region for the underlying filesystem class.

On a writable reader this is a live window onto the backing store, so mutations the filesystem makes reach the file. On a read-only reader it is a private copy, so a stray write cannot corrupt a shared (possibly read-only-mapped) backing.

Return type:

memoryview

find(needle, start=0)

Region-relative offset of the first needle at/after start, or -1.

Searches only within this region, in place (via mmap.find / bytes.find) so a large image is not copied.

Parameters:
Return type:

int

window(offset, length)

A sub-region reader over [offset, offset + length).

Shares this reader’s backing buffer (no copy) and is clamped to what is available. It does not own the underlying file/mmap — the top-level reader does — so closing a window is a no-op.

Parameters:
Return type:

ImageReader

oaknut.filesystem.ImageSource

alias of ImageReader | bytes | bytearray | memoryview | str | Path

oaknut.filesystem.reader_for(source, *, suffix_hint=None, writable=False)

Build an ImageReader for source.

Accepts an existing reader (returned unchanged), an in-memory buffer, or a filesystem path. Path sources are memory-mapped so a large hard-disc image is not read wholesale; the mapping is released when the reader is closed. writable maps the file for writing, so writes through the reader (and mutations of ImageReader.buffer()) reach the file directly — used by the mutating CLI commands.

Parameters:
Return type:

ImageReader

Exceptions

exception oaknut.filesystem.FilesystemError(*args, exit_code=None)

Base for errors raised by the oaknut filesystem layer.

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None

exception oaknut.filesystem.GeometryError(*args, exit_code=None)

A geometry specification could not be parsed, or is invalid.

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None

exception oaknut.filesystem.NoSuchVolumeError(*args, exit_code=None)

A volume designation addresses a volume the image does not have.

Raised when a path names a volume (a DFS drive, :2) that the geometry has no surface for — e.g. drive :2 on a single-sided image. The addressed thing is absent, so this carries the “path not found” exit code. The message quotes the designation, never the internal surface index.

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None

exception oaknut.filesystem.VolumeNotFormattedError(*args, exit_code=None)

An addressed volume’s surface carries no valid filesystem.

The surface exists in the geometry but holds no valid structure — e.g. the second side implied for a length-ambiguous image turns out to be unformatted, so the image was single-sided after all. The data on that surface is not what the filesystem requires, so this carries the invalid-data exit code (the FilesystemError default).

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None

exception oaknut.filesystem.ReadOnlyFilesystemError(*args, exit_code=None)

A mutating operation was attempted on a read-only mount.

Raised by a Mount whose backing filesystem cannot be written (a ZIP archive, say). Carries the “operation not permitted” exit code so the CLI reports a clear refusal rather than a generic data error.

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None

exception oaknut.filesystem.FilesystemExtensionError(*args, exit_code=None)

A filesystem extension could not be discovered or loaded.

A missing or mis-registered filesystem plug-in is an environment problem, so this inherits the configuration exit code via ExtensionError.

Parameters:
  • args (object)

  • exit_code (Optional[ExitCode])

Return type:

None