Utility: copy - copy a file or a whole subtree
Status: Built + QEMU-verified (osdev test files) - the file form and the
recursive directory form, as a shell built-in. On hierarchical GSFS
(docs/persistence.md). Trails CLAUDE.md; does not amend it.
1. What it is
copy <src> <dst> duplicates a file - same drive or across drives (copy 0:data/a 1:backup/a), since every drive is addressable by [index:]label/path. It replaces POSIX
cp; the full word is barely longer and not cryptic.
2. Usage
copy 0.4.0 - copy a file or a whole subtree
usage:
copy <src> <dst> copy file <src> to <dst>
copy <src> <dst> recursive copy directory <src> and everything under it
copy version print the version
copy help print this message
<src>,<dst> = [index:]label/path | /abs | rel (see docs/drives.md §4.1)
3. Behaviour
copy <src> <dst> reads src and writes dst (read + write underneath), so cross-drive
copy is just read-here, write-there - the no-shared-memory data path (§2.5,
docs/persistence.md §6.1). Success prints copied <src> → <dst> (N bytes). src is left
untouched.
copy <src> <dst> recursive duplicates a whole directory subtree. It is the safe default's
opt-in: a plain copy of a directory is refused with copy: source is a directory (use 'copy <src> <dst> recursive'), so the large operation only happens when you ask for it (mirrors
mkdir … parents, delete … recursive). Refuses to copy a directory into its own subtree
(copy /a /a/inner recursive) - that would never terminate - and refuses the root. The
destination directory must not already exist. A file that fails to copy prints copy: skipped (copy failed): <path> and the walk continues; the closing line is copied <src> → <dst> (N dirs, M files), where M counts only the files that copied.
4. Implementation
Mutating, so the least-authority shape of the other writers (19_write.md §4): it stats the
source (STAT_FILE, op 12), allocates the destination at full size (WRITE_NEW, op 24), then
streams IO_CHUNK pieces with READ_AT (op 26) and WRITE_AT (op 25), so a file of any size
copies through one fixed buffer. The recursive form adds no new fs surface -
copy already lives in the shell, so it walks the source subtree with the same bounded
PathStack find uses (§26.6): pop a source dir, recreate it under dst (Mkdir, op 13),
copy each file, push each subdir. Loud if the tree is wider than the walk's pending-dir cap
(§3.12), exactly like find.
5. Later (separate doc so it can grow)
- Copy-from/to a pipe. The capability pipe has landed (
docs/pipes.md), andread <src> | write <dst>already copies through one; acopypipe stage is not built. - Overwrite confirm, mirroring
write/flash, if wanted.
6. Conformance
Built spec-first against 0_conventions.md: implements its own copy help / copy version.