Skip to content

dos.library: MakeLink, ReadLink, LockRecord family (#160) - #163

Merged
sidick merged 1 commit into
mainfrom
issue-160-makelink-readlink-lockrecord
Oct 18, 2026
Merged

sidick merged 1 commit into
mainfrom
issue-160-makelink-readlink-lockrecord

Conversation

@sidick

@sidick sidick commented Oct 18, 2026

Copy link
Copy Markdown
Owner

Summary

Issue #160's "Tier 3" follow-up to #159/#161/#162's dos.library gap scan.

  • MakeLink/ReadLink: real AmigaOS soft-link semantics map naturally onto a host symlink, hard-link onto a host hard link.

    • MakeLink(name, dest, soft) (doslock.rs): soft == FALSE creates a real std::fs::hard_link from dest's lock; soft != FALSE creates a real symlink (#[cfg(unix)] via std::os::unix::fs::symlink) pointing at dest's Amiga path, resolved via ResolveMode::ParentMustExist so the target need not exist yet (soft-link targets are "resolved lazily", per the NDK autodoc). name itself also uses ParentMustExist and fails with ERROR_OBJECT_EXISTS if something's already there, matching CreateDir's own convention.
    • ReadLink(port, lock, path, buffer, size) (doslock.rs): resolves lock's directory + relative path, calls std::fs::read_link on a real host symlink, and writes the raw target string back (not a re-derived Amiga path -- see the doc comment on DosState::read_link for why that's the most faithful thing to report).
  • LockRecord/LockRecords/UnLockRecord/UnLockRecords (dosfile.rs): cheap stubs matching this runtime's existing no-real-concurrency posture (InitSemaphore/ObtainSemaphore, AddTask, ChangeMode). LockRecord/UnLockRecord validate the filehandle is currently open; LockRecords/UnLockRecords always report success (there's no single real-AmigaOS struct layout for recArray to validate against, and nothing to enforce either way).

Judgment calls

  1. Soft-link target resolve mode: MakeLink's dest Amiga path (for a soft link) is resolved via ResolveMode::ParentMustExist -- the closest existing primitive that turns an Amiga path into a host path without requiring the target to already exist, matching real AmigaOS's documented "resolved lazily" soft-link semantics.

  2. ST_SOFTLINK detection in Examine/ExNext/ExAll -- deliberately cut. fill_fib (doslock.rs) and dosexall.rs's equivalent scan use std::fs::metadata, which follows symlinks, so a soft link currently lists as whatever it resolves to (or fails to list at all if dangling). Detecting it would need symlink_metadata + is_symlink() at every fill_fib call site -- cut for scope rather than touching that shared, already-tested machinery. Documented explicitly in doslock.rs's module docs.

  3. Windows symlink creation: gated #[cfg(unix)]; on any other target, MakeLink(soft) reports a clean ERROR_ACTION_NOT_KNOWN (never a panic/hang) without attempting the host call at all, since Windows symlink creation needs elevated privileges/Developer Mode that can't be known in advance, and there's no dedicated real-AmigaOS error code for "this filesystem doesn't support soft links".

  4. ReadLink's port argument: read (so the real register convention holds) but otherwise unused. Real ReadLink is normally called by DOS itself after a filesystem handler process's packet reply comes back ERROR_IS_SOFT_LINK, and port identifies that handler for a real multi-process AmigaOS to route back to. This runtime has no real per-filesystem handler process for ordinary volumes (same posture as dosdevproc.rs/dospkt.rs), and read_link resolves everything directly from self.locks + the host filesystem -- so there's no handler for port to identify, and ignoring it changes nothing observable.

Also not implemented (out of scope per the issue): the real AmigaOS "filesystem returns ERROR_IS_SOFT_LINK, DOS calls ReadLink, retries" protocol inside Lock/Open/Examine. Host symlinks already transparently resolve via ordinary host filesystem calls, so Lock/Open/Examine "just work" on a soft link without any extra code here.

Test plan

  • Unit tests for every new DosState method (doslock.rs/dosfile.rs): success paths, every documented failure path (ERROR_OBJECT_EXISTS, ERROR_INVALID_LOCK, ERROR_OBJECT_WRONG_TYPE, mapped I/O errors), plus #[cfg(unix)]/#[cfg(not(unix))]-gated symlink-specific cases.
  • Real end-to-end tests driving actual A-line trap dispatch for all 6 calls at their real LVO offsets (MakeLink -444, ReadLink -438, LockRecord -270, LockRecords -276, UnLockRecord -282, UnLockRecords -288).
  • cargo test --workspace (1102 tests, up from 1080) passes; cargo clippy --all-targets -- -D warnings and cargo fmt --all --check clean.

Closing

Addresses #160. Fully implements MakeLink/ReadLink/LockRecord/LockRecords/UnLockRecord/UnLockRecords as scoped by the issue. Deliberately deferred (see judgment call #2 above): ST_SOFTLINK reporting in Examine/ExNext/ExAll for a host symlink entry -- not implemented, documented in doslock.rs's module docs as a scope cut, not a bug.

🤖 Generated with Claude Code

MakeLink/ReadLink map onto real host hard links/symlinks (symlink
creation gated #[cfg(unix)], a clean IoErr on other platforms rather
than a panic or an attempted but likely-failing Windows symlink).
LockRecord/UnLockRecord validate the filehandle exists; LockRecords/
UnLockRecords are unconditional-success stubs, matching this runtime's
existing no-real-concurrency posture (InitSemaphore/ObtainSemaphore,
AddTask, ChangeMode).

Deliberately out of scope (documented in doslock.rs's module docs and
the PR body): the real ERROR_IS_SOFT_LINK retry protocol in
Lock/Open/Examine, and ST_SOFTLINK detection in Examine/ExNext/ExAll
for a host symlink entry.
@sidick
sidick merged commit 8bd3d77 into main Oct 18, 2026
9 checks passed
@sidick
sidick deleted the issue-160-makelink-readlink-lockrecord branch October 18, 2026 13:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant