Metadata across the host boundary

Acorn files carry side-channel metadata that does not exist on a modern host filesystem:

  • a 32-bit load address (where the file goes in memory),

  • a 32-bit exec address (where execution starts after load),

  • an access byte (owner and public read, write, execute and lock), and

  • on RISC OS files, a 12-bit filetype encoded inside the load address.

A plain cp image.ssd:$.HELLO hello would lose every byte of this — host filesystems do not have a column for “Acorn exec address”. The four commands that cross the host boundary — disc get, disc put, disc export, disc import — therefore accept a --meta-format option that names how metadata is carried over the boundary. The choice has trade-offs, and the wrong choice silently loses information. This page is the single source of truth on what each format does and when each is the right pick.

The four commands that cross the host boundary

Command

Direction

Default --meta-format

disc get COMPOUND_PATH [HOST_PATH]

image → host (one file)

inf-trad

disc put COMPOUND_PATH [HOST_PATH]

host → image (one file)

import cascade (see What gets tried on import)

disc export IMAGE HOST_DIR

image → host (whole tree)

inf-trad

disc import IMAGE HOST_DIR

host → image (whole tree)

import cascade

disc cp between two image specs does not appear here — it copies inside oaknut’s own representation, so metadata travels fully without needing a host side-channel. disc cat and disc type print only the file’s bytes and never touch metadata.

The --meta-format choices

Every host-boundary command accepts the same seven values:

Value

What it carries

On-disk shape

inf-trad

filename, load, exec, length, attr

foo.bin plus foo.bin.inf containing $.FOO FFFF1900 FFFF8023 00000040 13 (see Traditional .inf files below)

inf-pieb

owner, load, exec, perm

foo.bin plus foo.bin.inf in the PiEconetBridge form owner load exec perm [homeof]: no filename field, and PiEB’s own perm layout (below)

xattr-acorn

load, exec, attr

foo.bin plus extended attributes user.acorn.load, user.acorn.exec, user.acorn.attr (uppercase hex)

xattr-pieb

load, exec, attr, owner

foo.bin plus extended attributes user.econet_load, user.econet_exec, user.econet_perm (PiEB layout), user.econet_owner

filename-riscos

load, exec or filetype

Filename rewritten: foo,xxx for a filetype-stamped file, foo,llllllll,eeeeeeee (8+8 lowercase hex) otherwise

filename-mos

load, exec

Filename rewritten: foo,load-exec with variable-width lowercase hex separated by a hyphen

none

nothing

Just the bytes. Metadata is lost.

Pick based on what you want next:

You want a single, widely-understood, archival-safe sidecar. Use inf-trad (the default). The .inf companion file is a short text line every Acorn-era utility recognises, and it travels through ZIP, tar, rsync, dropbox, USB sticks, and email attachments unchanged.

You are talking to a PiEconetBridge file server. Use inf-pieb (when staging files on disc) or xattr-pieb (when storing on a Linux filesystem PiEconetBridge will serve from). These omit the Acorn filename field but include the Econet owner ID — pass --owner N to set it. PiEconetBridge stores permissions in its own perm byte, which swaps the lock (&04) and execute-only (&08) bits relative to the Acorn access byte and uses &80 for hidden, which disc holds as the hidden attribute; disc translates it in both directions, so access always reads and prints the Acorn way.

You want zero sidecar clutter and zero filename changes. Use xattr-acorn. The metadata lives in extended attributes attached directly to the file on disc. Caveat: xattrs survive local copies on Linux/macOS but do not cross tar, ZIP, FAT, SMB/CIFS shares, or most network protocols.

You want metadata to survive any host conversion. Use filename-riscos or filename-mos. The metadata is in the filename, so anything that preserves the filename preserves the metadata. filename-riscos is the modern RISC OS convention (many emulators and converters speak it); filename-mos is the older BBC MOS form.

You explicitly do not want metadata (the file is plain data and will not go back). Use none. The file is written or read as raw bytes only.

What gets tried on import

disc put and disc import without --meta-format try each metadata source in turn, stopping at the first that yields results:

  1. Traditional INF sidecar — foo.bin.inf next to the data file. The line is parsed for load, exec, attr, and (for the traditional form) filename.

  2. Acorn xattrs — user.acorn.* first; if absent, the reader also tries the PiEconetBridge user.econet_* namespace before giving up on xattrs. A separate explicit --meta-format xattr-pieb cascade step would therefore be unreachable.

  3. RISC OS filename suffix — ,xxx or ,llllllll,eeeeeeee at the end of the host filename.

If none of the three yield metadata, the file is imported with load_address=0, exec_address=0, and the access a new file gets on the destination: WR/R on ADFS, WR/ on AFS and DFS. When a sidecar does record access, disc put and disc import both apply it; --access on put overrides it.

Traditional .inf files

A traditional .inf is read and written per the Stardot INF format specification, with J.G. Harston’s choices (Storing Acorn/BBC metadata on other systems) where it leaves room:

  • Fields may be dropped from the right, down to name load. A missing exec address is the load address, and a missing access field means &33 (WR/WR).

  • A lock marker — Locked, LOCKED or a bare L, as DFS-era tools write in place of the length or access — means &19 (LR/R).

  • A symbolic access field is case-sensitive: upper-case letters are the owner’s rights and lower-case the public’s, so WRr is WR/R and LWR is LWR/. D is ignored. The slash form disc itself uses (WR/R) is also accepted, case-insensitively, as on the command line.

  • Six-digit DFS-style addresses such as FF0E00 are widened to &FFFF0E00.

  • Names may be quoted and percent-encoded ("MY FILE", "A%22B"); the old TAPE prefix, extra fields such as CRC= and OPT4=, and NEXT are recognised.

disc get and disc export write 8-digit addresses and a 2-digit hex access byte, and quote and percent-encode any name that needs it. A name is written in the image’s own character set, as its bytes are stored on the disc: on DFS, £ is byte &60, so the sidecar for $.COST£ holds that byte, not Latin-1’s &A3. disc put and disc import decode a sidecar name in the destination image’s character set. A ZIP member without Acorn attributes has access &33, and its bundled .inf files are read by the same rules.

To override the cascade, pass --meta-format VALUE and only that format is consulted. Pass --meta-format none to ignore all metadata sources and import bytes only.

Overriding metadata at import time

disc put also accepts --load HEX and --exec HEX for ad-hoc cases that don’t fit any of the sidecar formats — for example, putting a freshly-built binary onto a disc with an explicit load address:

disc put 'hello.ssd:$.PROG' build/prog.bin --load 0x1900 --exec 0x1900

These override whatever the chosen --meta-format would have read. --access does the same for the file’s access; see File access below.

File access

Access is written as an access string: the owner’s rights to the left of a /, the public’s (other users of a file server) to the right.

Letter

Meaning

R

may be read (and *RUN)

W

may be written

E

may be executed; for the owner without R, the file is *RUN-only

L

locked: may not be deleted, renamed or overwritten

P

private, written before the owner’s letters: the public may not delete, rename or overwrite it (bit 7 of the access byte, the same as L after the /)

So WR/R is owner read and write with public read, and LR/ a locked, read-only file other users cannot read. E/ is a *RUN-only file: it may be run but not loaded, the copy protection ROMFS and cassette files use. Most filing systems treat a readable file as executable, so E is shown only when neither R nor W is, for the owner and the public alike (WR/E). The same value can be given as the hex access byte (0x13, 19), which disc ls -H displays.

Each filing system stores what it can. DFS records only a lock bit, which also means read-only, so a DFS file reads as WR/ or LR/ and writing to DFS keeps only L. ADFS stores owner R, W, E and L, public R, W and E, and P (New-format D, E and F discs drop both execute bits and P); AFS stores owner and public R and W and L; ROMFS whether a file is readable (R/) or *RUN-only (E/). A copy between filing systems keeps as much as the destination can store — so a file copied from DFS arrives with no public access. A *RUN-only file (E/) copied to a filing system that cannot store execute — AFS, DFS, or a New-format (D, E, F) ADFS disc — becomes readable (R/) there instead, and disc warns that the copy protection was not kept.

To change access:

  • disc chmod (Acorn alias *ACCESS) sets it on existing files, with wildcards and -r; --dry-run lists what would change.

  • --access on disc cp and disc put sets it as the files are written.

Both take an absolute string (R/R, 0x19), which replaces the access, or an incremental one starting with + or -, which edits it: +/R grants public read, -W removes owner write, and clauses combine (+L-W). On a Level 3 File Server, binaries other users run — the contents of $.Library, shared games — need public read:

disc cp -r 'game.dsd::0.G' 'scsi0.dat:afs:$.EliteGame' --access +/R
disc chmod 'scsi0.dat:afs:$.Library.Elite*' R/R

Where the in-image name comes from

An Acorn filename can hold characters a host filename cannot — a / is legal on DFS but not on a host, so an exporter stores test8/3 on disc as test8_3 on the host and records the true name in the sidecar. On import, disc chooses the in-image leaf name highest-priority first from:

  1. --name — an explicit override (disc put only), for a leaf the path syntax cannot express: one containing . (the Acorn separator), a leading space, or a file under a non-$ root.

  2. the destination leaf, when disc put is given one that names a file (disc put img:$.PROG file names it PROG).

  3. the Acorn name the metadata source carries — a traditional INF’s filename field, or a filename-encoded name — recovering the name the host filename transliterated.

  4. the host filename, with any encoded suffix stripped.

A disc put destination that names a directory — the root $, or an existing directory — puts the file into it under the derived name, so the sidecar name is used:

disc put tube.ssd:$ original/test8_3 --meta-format inf-trad
# -> in-image file  test8/3   (from the INF, not the host's test8_3)

disc import always targets a directory, so every file it imports uses its sidecar name where one is present, else the host filename.

Mixing formats in one direction

The chosen format applies uniformly across a bulk command — disc export writes every file in the chosen --meta-format. For mixed exports (some files as INF, others as RISC OS filenames) run disc get per file with different --meta-format values.

Imports are more flexible because the default cascade tries multiple formats per file, so a host directory mixing INF sidecars, xattr’d files, and filename-suffixed files imports correctly as one disc import HOST_DIR invocation.

Datestamps are reported at face value

A RISC OS file’s datestamp (held in the load/exec fields alongside the filetype) is a count of centiseconds since 1900 with no timezone recorded. disc ls, disc stat and disc get-datestamp report it exactly as stored — no timezone or daylight-saving conversion, and no guess about which era’s convention produced it.

This matters because the meaning of the stored instant is not fixed: RISC OS 3 and later store datestamps in UTC, while RISC OS 2 and earlier (the Arthur era) used the uncorrected system clock, usually set to local time. The disc does not record which. Reporting verbatim keeps oaknut’s output reproducible and independent of where or when you run it.

One visible consequence: a RISC OS Filer adjusts datestamps to the machine’s current timezone and daylight-saving setting when it displays them (a proleptic adjustment that ignores whether DST was actually in force on the file’s date). So on a DST-active machine the Filer can read up to an hour ahead of what oaknut reports. That is the Filer applying a local-time conversion oaknut deliberately does not — not a disagreement about the bytes.

DFS host (I/O processor) addresses

A DFS catalogue holds load and execution addresses in 18 bits. When the top two of those bits are both set, the address belongs to the I/O processor rather than a Second Processor, and DFS reports it as the 32-bit value &FFFFxxxx; any other pattern is a Second Processor address below &30000. oaknut reads the same values, so a file copied from DFS to AFS or ADFS still loads and runs in the I/O processor, and the .inf sidecar disc get writes records FFFF1900.

DFS listings show the low three bytes, as *INFO does — FF1900 — while the machine formats (--as json, --as tsv) carry the full value. Writing &FFFF1900, &FF1900 or the raw &31900 to DFS stores the same address. A 32-bit address with bits 16 and 17 both set, such as &00031900, has no separate DFS form: it reads back as &FFFF1900.

Address or datestamp? --metadata-lens

On ADFS a file’s load/exec fields hold either a real address pair or a filetype-and-datestamp — distinguished by the RISC OS marker “the top twelve bits of the load address are &FFF”. But that marker overlaps genuine addresses — the &FFFFxxxx host-address convention and the &FFFFFFFF “unset” sentinel both trip it — so the reading cannot be chosen reliably from a single file’s bytes. It is a format question: on DFS and the 8-bit ADFS shapes (S/M/L) a load/exec pair is almost always a genuine address, while on the Arthur and RISC OS ADFS shapes (D, E, F and their successors) it is almost always a filetype and datestamp.

disc ls and disc stat therefore default to a lens each filing system declares. Under the type-date lens a marked file shows Filetype and Datestamp columns and its raw load/exec are hidden from the human view (they are only the encoding); under the addresses lens the Load and Exec columns are shown and the decode is suppressed. The raw values are never lost either way — they stay in --as json / --as tsv output, and disc get-load / disc get-exec always report them.

Override the default with ``–metadata-lens``:

  • --metadata-lens=addresses forces the Load/Exec reading — use it when a RISC OS disc holds a genuinely addressed file, or when a coincidental &FFF shows a spurious date.

  • --metadata-lens=type-date forces the filetype/datestamp reading — use it to see a filetype you set on an 8-bit ADFS disc, which defaults to addresses.

  • --metadata-lens=auto (the default) follows the filing system.

It changes the display only; the stored bytes are untouched. Set OAKNUT_DISC_METADATA_LENS=addresses (or type-date) to make a reading the default across commands.

A filing system that keeps its datestamp outside load/exec — the Acorn File Server, with its native two-byte date — is unaffected by the lens: its Datestamp column shows under either reading, alongside the real load/exec addresses.

Note

--raw-addresses (and OAKNUT_DISC_RAW_ADDRESSES) is a deprecated alias for --metadata-lens=addresses, retained for existing scripts.

Cross-host gotchas

  • xattr survival depends on the filesystem and the transport. Local Linux ext4 and macOS APFS preserve xattrs through cp and mv. ZIP, tar (without --xattrs), FAT, exFAT, NTFS (the Linux driver), SMB/CIFS, and most cloud-storage clients strip them silently. If your files will travel, prefer inf-trad or filename-riscos.

  • Sidecar files double the file count. A directory of 1000 Acorn files exported as inf-trad lands as 2000 host files. filename-riscos keeps the count at 1000 — useful for filename-sensitive contexts like ZIP archives.

  • Filename-encoded metadata changes the host filename. A file saved as $.PROG exports under filename-riscos as PROG,FFFF1900,FFFF1900 — handy for round-trip preservation, but you cannot also use the host filename to identify the file.

  • The Acorn-side filename is only preserved by ``inf-trad``. All other formats use the host filename as the disc-side filename on re-import. If your Acorn filenames contain characters the host rejects (or vice-versa), the only round-trip-safe format is inf-trad.

When in doubt, --meta-format inf-trad is the safest default for archival and the most widely supported across other Acorn-aware tooling.