diff --git a/TODO.md b/TODO.md index 45aad8f..391d60e 100644 --- a/TODO.md +++ b/TODO.md @@ -112,28 +112,6 @@ Follow-up: a real requester, especially where MARS-NWE currently relies on the existing underlying share implementation. -### AFP Set File Information timestamp coverage - -Current status: - -- AFP Set File Information (`0x09`) and AFP 2.0 Set File Information (`0x10`) - now accept the file modification timestamp bitmap (`0x0010`) for path-backed - file requests. -- Timestamp writes are routed through the existing NetWare `nw_utime_node()` - helper so trustee Modify rights and the established Unix `utime(2)` fallback - behavior are reused instead of inventing AFP-specific timestamp handling. -- The AFP smoke helper verifies the AFP date/time fields via the follow-up - Get File Information response, and the smoke suite also records `stat -c %Y` - for the backing Unix file. - -Follow-up: - -- Add directory timestamp handling once the shared AFP path/object resolver grows - directory-specific Set File Information semantics. -- Keep create/access/backup timestamp writes disabled until their exact AFP to - NetWare/Unix metadata mapping is deliberately wired and tested. -- Keep Delete/Rename/Create/Remove for later patches that can reuse the existing - NetWare server helpers and trustee checks. ### Extended volume information field mapping @@ -213,289 +191,24 @@ Follow-up: Current status: -- `NCP 0x23` still returns invalid namespace for AFP calls that are not implemented yet. -- `AFP Get Entry ID From Path Name` is implemented when the optional - mars_nwe AFP xattr metadata backend is available. Entry IDs are now derived first from - existing mars_nwe NetWare namespace/basehandle state rather than from a - parallel AFP/stat fallback generator. AFP smoke coverage exists in - `tests/afp/afp_entry_id_smoke`; the latest full-suite run against - `SYS:PUBLIC/pmdflts.ini` returned `entry_id=0x00000004`. -- `AFP Get Entry ID From Name` is implemented for the same path-backed - smoke mode. AFP smoke coverage uses - `tests/afp/afp_entry_id_smoke --from-name`; the identity source follows the - same NetWare namespace/basehandle path as Entry ID From Path Name. -- `AFP Get File Information` is implemented for read-only path-based requests. - AFP smoke coverage exists in `tests/afp/afp_file_info_smoke` and has - been verified against `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST`. - The same test verifies the AFP 2.0 Get File Information subfunction via - `--afp20` against the same paths, using the same path-backed read-only reply - for now. The current reply fills stat/mars_nwe AFP xattr-derived fields and leaves - persistent CNID Parent ID / fuller Mac namespace metadata as future work. -- `AFP Scan File Information` (`0x0a`) and `AFP 2.0 Scan File Information` - (`0x11`) are implemented for path-backed read-only directory scans. Linux - smoke coverage exists in `tests/afp/afp_scan_info_smoke`; the helper - defaults to the AFP 2.0 subfunction and uses `--afp10` for the older - endpoint. Runtime coverage has been verified against `SYS:PUBLIC` by - walking multiple directory entries with the returned `next_last_seen` AFP - Entry ID continuation value. The verified AFP 2.0 and older `0x0a` first - records now expose NetWare namespace/basehandle-derived Entry IDs. The - latest full-suite run against `SYS:PUBLIC` returned - `next_last_seen=0x00000004` and `entry_id=0x00000004` for the first scanned - record while preserving the expected file metadata. -- `AFP Get Entry ID From NetWare Handle` is implemented for read-only data-fork - file handles that are opened in the same client connection. Linux smoke - coverage uses `tests/afp/afp_entry_id_smoke --from-handle`. The latest - full-suite run verified `SYS:PUBLIC/pmdflts.ini`, returning volume 0, - `fork=0`, and the same NetWare namespace/basehandle-derived - `entry_id=0x00000004` as the path-backed lookup. -- `AFP Open File Fork` is implemented for the same path-backed smoke subset. - Raw `VOL:`-style paths resolve the effective NetWare volume from the path - prefix instead of assuming volume 0, so the same smoke path can cover `SYS:` - and non-`SYS:` volumes. It opens only the data fork read-only and returns a - normal six-byte NetWare file handle plus the current data-fork length; the - AFP smoke helper - `tests/afp/afp_open_file_fork_smoke` closes the returned handle in the same - connection. Runtime smoke coverage is green for - `SYS:PUBLIC/pmdflts.ini` (`fork_len=8161`) and `SYS:PUBLIC/ohlogscr.bat` - (`fork_len=1296`) using `fork=0` and read access `0x01`. The smoke suite - now also asserts that write-open requests fail with completion `0x84` and - resource-fork opens fail with completion `0x9c`, keeping the current - unsupported cases explicit until AppleDouble/resource-fork, AFP write-open, - and persistent CNID/base-ID semantics are available. -- `AFP Alloc Temporary Directory Handle` is implemented for the same - path-backed smoke subset. Raw `VOL:`-style paths resolve the effective - NetWare volume from the path prefix instead of assuming volume 0. Linux - smoke coverage exists in - `tests/afp/afp_temp_dir_handle_smoke`; runtime smoke coverage is green for - `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST`. The helper returns a - temporary NetWare directory handle plus the AFP one-byte access-rights mask - and immediately deallocates the handle in the same connection. Server - diagnostics log the wider internal NetWare effective-rights mask, so - privileged directories can show `rights=0x1ff` while the client prints - `rights=0xff`. Entry-ID-only allocation remains TODO until persistent - CNID/base-ID lookup exists. -- `AFP Set File Information` (`0x09`) and `AFP 2.0 Set File Information` - (`0x10`) now require the fixed WebSDK/NWAFP request layouts for path-backed - file metadata smoke writes. The legacy request uses `path_len` at offset 54; - the AFP 2.0 request uses ProDOSInfo at offsets 54..59 and `path_len` at - offset 60. The compact mars_nwe-only smoke packet layout has been removed. - The covered bitmaps are FinderInfo (`0x4000`), Attributes (`0x0100`), Access - Date/Time (`0x0400`), Create Date/Time (`0x0800`), Modify Date/Time - (`0x1000`), and Backup Date/Time (`0x2000`). FinderInfo is stored in - `org.mars-nwe.afp.finder-info`; Hidden/System/Archive attributes are mapped - to the existing NetWare attribute path; `org.mars-nwe.afp.attributes` is only - for future AFP-only bits that are not NetWare attributes. Create and Backup - Date/Time use the existing - mars_nwe NetWare metadata helpers; Access Date/Time uses the normal file - `atime` path; and Modify Date/Time uses the shared timestamp helper. Linux - smoke coverage exists in `tests/afp/afp_set_file_info_smoke`, which now - always reports the WebSDK request shape and verifies the result through AFP 2.0 Get - File Information. Runtime status: the WebSDK-layout-only smoke run for - `SYS:PUBLIC/pmdflts.ini` completed with `failures=0`, including legacy `0x09` - and AFP 2.0 `0x10` FinderInfo, Hidden/System/Archive set/clear, - Access/Create/Modify/Backup timestamp probes, and the NOPASSUSER Modify-rights - negative probes. -- The AFP dispatcher now decodes the WebSDK/NWAFP subfunction number in - diagnostics so real client probes can be mapped to the corresponding AFP - call before implementation work starts. -- AFP metadata now uses the standalone mars_nwe AFP xattr backend. There is no - Netatalk/libatalk dependency for Entry ID, FinderInfo, or AFP-only attribute - storage; AFP protocol support remains limited to the endpoints explicitly - implemented in `nwconn.c` and guarded by the existing build configuration. - Runtime status after the standalone backend change: the full AFP smoke suite - completed with `failures=0`, including path-backed and entry-id-only Open File - Fork, FinderInfo xattr verification, absent optional AFP-only attributes xattr, - and NetWare-backed Hidden/System/Archive/timestamp probes. -- Existing mars_nwe private xattr payloads use the `org.mars-nwe..*` - namespace (`org.mars-nwe.netware.archive` and `org.mars-nwe.netware.fileinfo`) rather than - the unreleased test-only `user.mars_nwe.*` names. There is no legacy read - fallback because the old names never shipped outside local test systems. - On Linux, mars_nwe's local xattr helper maps source-level `org.mars-nwe..*` - names to the portable `user.org.mars-nwe..*` storage namespace, mirroring - the xattr abstraction used for Apple metadata. -- NetWare AFP calls are NCP entry points for Mac namespace semantics on a - NetWare volume, not transport-level AFP proxy calls to `afpd`. -- AFP Get DOS Name From Entry ID (0x12) is implemented as a conservative - read-only reverse lookup that first uses the existing mars_nwe - `map_directory_number_to_path()` namespace/basehandle path for directory - objects. Regular file Entry IDs stay on the cached AFP/fallback path until a - reliable file-object reverse mapper is available. The legacy - `nwatalk_get_entry_id()` volume scan remains as the fallback for cached AFP - file IDs. +- The active AFP compatibility slice is implemented and covered by the smoke + tests under `tests/afp/`. Endpoint inventory, WebSDK audit notes, and AFP + implementation history live in that directory instead of this project-level + TODO file. +- The only AFP endpoint still tracked here is `0x13 AFP Get Macintosh Info On + Deleted Files`. It depends on a real mars_nwe salvage/deleted-entry backend + and must not be implemented as an AFP-local deleted-file scan. Follow-up: -- Implement the NetWare AFP NCP calls locally, using mars_nwe AFP xattr helpers rather - than proxying requests to `afpd`. Create Directory, Create File, AFP - Delete, and AFP Rename are now implemented through existing mars_nwe create/remove/rename helpers - and covered by Linux smoke tests. -- Candidate future AFP-only pieces should stay under `org.mars-nwe.afp.*`. - FinderInfo and regular-file Entry IDs are already implemented there. Do not - add NetWare semantics such as Hidden/System/Archive attributes or timestamps to - AFP xattrs; route them through the existing mars_nwe NetWare helpers. -- Keep returning invalid namespace for AFP calls that still lack a real per-volume Mac - namespace/AFP metadata layer. Do not return success for additional AFP calls without - data/resource fork and Finder Info semantics. -- AFP Entry IDs now prefer the existing mars_nwe NetWare namespace/basehandle - mapping for directories. Regular files use mars_nwe AFP xattr Entry IDs for - entry-id-only reverse lookup. AFP must not grow a second mars_nwe object-id - resolver in parallel to the existing - namespace machinery. -- The full smoke suite verifies path-backed file identity end to end: - Entry ID From Path Name, Entry ID From NetWare Handle, Get File Information, - Set File Information verification, and Get DOS Name From Entry ID all returned - or consumed a cached AFP/fallback file ID for the sample - `SYS:PUBLIC/pmdflts.ini` path, while directory-scan entries continue to use - the existing namespace/basehandle identity. AFP directory-scan continuation - remains directory iteration based: `last_seen` skips past the previously - returned object, but the next returned Entry ID is not required to be - numerically greater than the continuation token. The latest full smoke run - also verified AFP Delete cleanup for Create Directory/Create File, AFP Rename - for both directories and files, and WebSDK-layout-only Set File Information - for FinderInfo, attributes, and timestamps; it ended with `failures=0`. - FinderInfo plus the Finder Hidden/System/Archive AFP attributes now have - deliberately narrow write paths through AFP Set File Information `0x09` and - AFP 2.0 Set File Information `0x10`; CNID - allocation and broader AFP metadata writes still need a deliberate write-safe - design. -- Put additional future mars_nwe-owned AFP metadata under `org.mars-nwe.afp.*` - (or a compact `org.mars-nwe.afp.metadata` record) and keep externally owned Apple metadata under its own keys. -- Extend the Linux AFP smoke tests once additional AFP subfunctions are - implemented, especially Finder Info updates, fork open/read/write paths, - resource-fork handling, and broader directory-scan edge cases. - - -### AFP implementation convergence plan - -Current status: - -- The AFP/NWAFP work is now broad enough that future endpoint patches should - treat AFP as an Apple-facing adapter over the existing mars_nwe NetWare - server machinery rather than as a parallel file server implementation. -- The safe baseline already includes path-backed Entry ID, Get/Scan File - Information, temporary directory handles, read-only data-fork Open File - Fork, narrow Set File Information metadata writes, NetWare-backed Archive - attribute mapping, Modify timestamp writes through `nw_utime_node()`, and - a conservative Get DOS Name From Entry ID reverse lookup. -- The Get DOS Name From Entry ID helper now returns the canonical DOS namespace - spelling from the existing mars_nwe `namedos.c` alias builder. The follow-up - smoke run confirms `PUBLIC/PMDFLTS.INI` for `SYS:PUBLIC/pmdflts.ini`, replacing - the earlier raw Unix/realcase `public/pmdflts.ini` result. - -Design rule: - -- AFP request handlers should parse the WebSDK/NWAFP request, resolve volume, - path, directory handle, or entry id to an existing mars_nwe object, call the - established NetWare helper, and translate the result into the AFP reply - layout. -- Do not introduce direct `open(2)`, `unlink(2)`, `rename(2)`, `mkdir(2)`, - `utime(2)`, attribute, trustee, or directory-scan logic inside AFP handlers - when a mars_nwe helper or wrapper already exists. -- Only keep AFP-specific storage for metadata that has no NetWare equivalent, - such as FinderInfo, AFP Entry IDs/CNIDs, and narrowly scoped AFP-only - attributes that are deliberately not mapped to NetWare attributes yet. - -Refactor/wrapper follow-up: - -- Continue reusing the existing mars_nwe volume, namespace, basehandle, and - directory-handle helpers for AFP object lookup. Do not add an AFP-local - object resolver where `conn_get_kpl_unxname()`, `nw_vol_inode_to_handle()`, - `map_directory_number_to_path()`, or related namespace helpers already cover - the case. -- Route all AFP writes through existing mars_nwe policy checks before changing - metadata. Archive and Modify timestamp already do this through NetWare - helpers. FinderInfo and AFP-only Hidden/System xattr writes are now gated - by the same trustee/effective-rights Modify policy before the AFP metadata - xattrs are updated. -- Continue moving AFP-visible NetWare attributes onto the existing NetWare - attribute store. Hidden, System, and Archive are mapped to `FILE_ATTR_H`, `FILE_ATTR_S`, and `FILE_ATTR_A`; ReadOnly, - ExecuteOnly, and Shareable still need either a real mapping - through existing attribute helpers or an explicit unsupported result. -- Extend Set File Information timestamps only through existing mars_nwe helpers: - Modify is routed through `nw_utime_node()`, Access through the existing - `st_atime`/`utime()` path, and Create/Backup through the existing - `nwarchive.c` metadata helpers. -- Normalize Get/Scan File Information so each field comes from the existing - mars_nwe source of truth where possible: NetWare attributes, file size, - timestamps, owner information, archive date/time, FinderInfo, resource-fork - size, and Entry ID/CNID metadata. AccessPrivileges are now derived from - `tru_get_eff_rights()` instead of static AFP masks and have readonly smoke - coverage under a temporary `[RF]` trustee assignment. -- Revisit Scan File Information after the resolver work and prefer mars_nwe's - existing directory/search machinery over the current AFP-local directory walk - for search attributes, namespace filtering, and multi-record replies. -- The current Get DOS Name From Entry ID path first uses the existing - `map_directory_number_to_path()` namespace/basehandle lookup and only falls - back to the legacy AFP metadata volume walk when necessary. Future CNID work - should plug into that same resolver order rather than reintroducing a - parallel path database. - - -AFP Set File Information metadata-rights convergence: - -- AFP FinderInfo writes and AFP-only Hidden/System attribute xattr writes no - longer bypass NetWare policy just because their storage is AFP-specific. - `afp_set_file_information()` now checks the resolved file through the existing - trustee/effective-rights Modify policy before writing `org.mars-nwe.afp.*` - metadata. -- Archive continues to route through the NetWare attribute helper (`FILE_ATTR_A`), - and Modify timestamp continues to route through `nw_utime_node()`. The new - check only covers metadata that has to remain AFP-specific, keeping AFP as an - Apple-facing adapter over mars_nwe policy rather than a parallel file server. -- The Linux AFP smoke suite now has optional negative coverage for this policy - gate. With `--readonly-user NOPASSUSER --readonly-no-password`, the suite can - run FinderInfo, Hidden, and System writes as a user that is expected to lack - Modify rights and assert completion `0x8c`. With `--prepare-readonly-rights`, - the suite uses the existing ncpfs `nwgrant`/`nwrevoke` trustee utilities to - grant only read/file-scan rights (`[RF]` by default) before the negative probe - and revoke the explicit trustee assignment afterwards. -- Runtime status: the negative smoke has been verified with `NOPASSUSER` as a - no-password test user. The suite temporarily granted `[RF]` on - `SYS:PUBLIC/pmdflts.ini`, confirmed FinderInfo, Hidden, and System Set - File Information requests are rejected with completion `0x8c`, and then - successfully revoked the temporary trustee assignment. The same run ended - with `failures=0`, preserved the final `TEXT/MARS` FinderInfo xattr, kept - `org.mars-nwe.afp.attributes` clear after the attribute cleanup probes, and - left the Modify timestamp at the expected smoke value. - -Endpoint order: - -- AFP Create Directory (`0x01`) and AFP 2.0 Create Directory (`0x0d`) are now - routed through the existing NetWare directory-create helper for temporary - smoke paths. The Linux smoke suite creates both a legacy and AFP 2.0 - directory under the tested parent and verifies the returned namespace-derived - Entry ID. AFP Delete is now used for server-side cleanup so the suite no - longer relies on local Unix `rmdir` permissions. -- Runtime status: the create-directory smoke has been verified with - `failures=0`. The latest run created `SYS:PUBLIC/afptst2` through legacy AFP - Create Directory (`0x01`) and `SYS:PUBLIC/afptst22` through AFP 2.0 Create - Directory (`0x0d`), with both probes returning and re-verifying Entry ID - `0x00000005`, then removed both objects through AFP Delete. -- AFP Create File (`0x02`) and AFP 2.0 Create File (`0x0e`) are now routed - through the existing NetWare file-create path for temporary smoke files. The - AFP smoke helper creates both legacy and AFP 2.0 files under the tested - parent, verifies the returned AFP file ID with Entry ID From Path Name, and - removes them through AFP Delete. -- Runtime status: the create-file smoke has been verified with AFP Delete - cleanup. The latest run created `SYS:PUBLIC/atst2` through legacy AFP Create - File (`0x02`) and `SYS:PUBLIC/atst22` through AFP 2.0 Create File (`0x0e`); - both returned nwatalk/fallback AFP file IDs (`0x53c18b6e` and `0x755cda24`), - were re-verified with AFP Entry ID From Path Name, and were removed through - AFP Delete. -- AFP Delete (`0x03`) is implemented through the existing NetWare delete/erase - policy path. It is used by the smoke suite for pre-test cleanup and - post-test cleanup of Create Directory, Create File, and Rename paths. -- AFP Rename (`0x07`) is implemented through the existing NetWare rename/move - paths. Directory rename uses the directory-aware move helper, while file - rename uses the NetWare file move path with file-only search attributes so - regular files are not filtered out by the directory attribute bit. -- Runtime status: the rename smoke has been verified with `failures=0`. The - run created and renamed `SYS:PUBLIC/d22240` to `SYS:PUBLIC/d22240r`, preserving the - namespace-derived directory Entry ID `0x00000005`; it also created and - renamed `SYS:PUBLIC/m22248` to `SYS:PUBLIC/m22248r`, preserving the - nwatalk/fallback AFP file Entry ID `0x78da3728`. Both renamed objects were - cleaned up through AFP Delete. -- Keep Get Macintosh Info On Deleted File (`0x13`) for last. +- Implement or verify the normal NetWare salvage family first: + - `NCP 0x2222 / 87 / 16` - Scan Salvageable Files + - `NCP 0x2222 / 87 / 17` - Recover Salvageable File + - `NCP 0x2222 / 87 / 18` - Purge Salvageable File + - optional legacy `NCP 0x2222 / 22 / 27` - Scan Salvageable File (old) +- After that backend exists, implement AFP `0x13` as an adapter over the + mars_nwe salvage/deleted-entry record. +- Keep the detailed AFP TODO, inventory, and audit notes in `tests/afp/`. ## Deferred / optional protocol work @@ -505,223 +218,3 @@ Endpoint order: by `nwserv.conf`. * Packet Burst/NDS fragmentation support remains out of scope unless a concrete client requires it. - -### AFP attribute convergence correction - -AFP Set/Get File Information attribute handling must follow the WebSDK attribute -word rather than the earlier low-bit smoke placeholders. The documented SetInfo -request bitmap uses `0x0100` for Attributes, `0x1000` for Modify Date/Time, and -`0x4000` for FinderInfo. The returned/set Attributes word uses `0x0200` -Hidden, `0x0400` System, and `0x2000` Archive. These are mapped through the -existing NetWare attribute store (`FILE_ATTR_H`, `FILE_ATTR_S`, `FILE_ATTR_A`) -so AFP does not keep parallel xattr-only copies for those NetWare attributes. -`--invisible` remains only a smoke-helper compatibility alias for Hidden. - -Runtime status: the WebSDK attribute-bit smoke run is verified with `failures=0`. -The suite confirmed `Hidden` set/clear as `0x0200`/`0x0000`, `System` -set/clear as `0x0400`/`0x0000`, and `Archive` set/clear as -`0x2000`/`0x0000`. The same run confirmed the WebSDK SetInfo bitmaps -`0x0100` for Attributes, `0x1000` for Modify Date/Time, and `0x4000` for -FinderInfo. Because all tested attribute bits are now stored through the -NetWare attribute path, `user.org.mars-nwe.afp.attributes` may be absent in the -final xattr dump; this is expected and no longer counts as a smoke failure. - -### AFP Backup Date/Time convergence - -AFP Set File Information now treats the WebSDK `0x2000` request bitmap as the -Backup Date/Time field, distinct from the `0x2000` Archive attribute bit inside -the Attributes word. The timestamp payload is routed through the existing -`mars_nwe_set_archive_info()` helper in `nwarchive.c`, so the data is stored in -`org.mars-nwe.netware.archive` together with the NetWare archive date/time -metadata rather than in an AFP-specific xattr. AFP Get/Scan File Information -merge the stored archive date/time back into the 120-byte AFP information record. - -This keeps the split explicit: Archive as an attribute is `FILE_ATTR_A` in the -NetWare attribute store; Backup Date/Time is archive metadata in -`nwarchive.c`; FinderInfo remains AFP metadata in `org.mars-nwe.afp.finder-info`. -The Linux smoke suite covers `--backup-time-only --backup-time-epoch` and dumps -`user.org.mars-nwe.netware.archive` so runtime reports show the underlying -mars_nwe storage path. - -Runtime status: the Backup Date/Time smoke run is verified with `failures=0`. -The suite confirmed `AFP Set File Information Backup Timestamp` using bitmap -`0x2000` and reported `backup=0x576eb9aa` for epoch `1700000000`. The same -run confirmed the backing mars_nwe metadata xattr: -`user.org.mars-nwe.netware.archive=0x01036e57aab900000000`. That confirms the -intended split: Archive as a file attribute stays on the NetWare attribute path, -while Backup Date/Time is stored by `nwarchive.c`. - -### AFP Create and Access Date/Time convergence - -AFP Set File Information now accepts the WebSDK `0x0800` Create Date/Time -request bitmap and routes the payload through the existing -`mars_nwe_set_file_info()` helper in `nwarchive.c`. AFP Get/Scan File -Information read the same `mars_nwe_get_file_info()` metadata and fall back to -the historical Unix timestamp source when no NetWare file-info metadata is -stored. The backing xattr is `user.org.mars-nwe.netware.fileinfo`; no -AFP-specific xattr is introduced for this NetWare-semantic field. - -AFP Set File Information also accepts the WebSDK `0x0400` Access Date/Time -request bitmap. Access timestamps are routed through the existing POSIX -`st_atime`/`utime()` path, preserving `st_mtime` and enforcing trustee Modify -rights before updating the file. This keeps Access Date/Time out of -`nwarchive.c` and out of AFP-only xattrs, matching the existing mars_nwe -NetWare file-info model. - -Runtime status: the combined AFP timestamp smoke run is verified with -`failures=0`. The suite confirmed `AFP Set File Information Access Timestamp` -using bitmap `0x0400` and `AFP Set File Information Create Timestamp` using -bitmap `0x0800`, both for epoch `1700000000` with the returned AFP date -`0x576e`. The same run confirmed the Create Date/Time backing metadata xattr -`user.org.mars-nwe.netware.fileinfo=0x01036e57aab90000000000000000`, while -Access Date/Time remained on the normal file `atime` path and did not create an -AFP metadata xattr. - - - -### AFP metadata entry-id resolver convergence - -AFP Get File Information and AFP Set File Information now accept entry-id-only -requests for regular files whose AFP ID is present in the mars_nwe AFP entry-id -xattr metadata. The shared resolver converts the AFP file Entry ID back to a -normal `VOL:PATH` string and then routes the operation through the existing -NetWare metadata paths. Regular file Entry IDs are not treated as DOS namespace -directory numbers. - -Runtime status: the full AFP smoke suite is verified with `failures=0` after -adding entry-id-only coverage for Get File Information, Set File Information -FinderInfo, and Set File Information Hidden. The verified run used AFP Entry ID -`0x05aaace0` for `SYS:PUBLIC/pmdflts.ini`; the server log shows the resolver -feeding `SYS:PUBLIC/PMDFLTS.INI` into Get/Set File Information before applying -the normal FinderInfo and NetWare attribute paths. - -### AFP Set File Information WebSDK layout convergence - -AFP Set File Information now requires the fixed WebSDK/NWAFP packet layouts for -both legacy `0x09` and AFP 2.0 `0x10`. The earlier compact mars_nwe smoke -layout was removed because it was not wire-compatible. Legacy requests carry -Attributes at offset 8, Create Date at 10, Access Date at 12, Modify Date/Time -at 14/16, Backup Date/Time at 18/20, FinderInfo at 22, and `path_len` at 54. -AFP 2.0 requests use the same fixed metadata fields, include ProDOSInfo at -54..59, and carry `path_len` at 60. - -Runtime status: the WebSDK-layout-only Set File Information smoke run is -verified with `failures=0`. The suite covered both AFP -2.0 `0x10` and legacy `0x09` FinderInfo writes, Hidden set/clear, System -set/clear, Archive set/clear, and Access/Create/Modify/Backup timestamp probes -against `SYS:PUBLIC/pmdflts.ini`. The verified run used AFP Entry ID -`0x42ede1c8`, kept FinderInfo as `TEXTMARS`, confirmed the final AFP-only -attributes xattr may be absent when no AFP-only bits remain set, and confirmed -NetWare file-info/archive metadata through the existing -`user.org.mars-nwe.netware.fileinfo` and `user.org.mars-nwe.netware.archive` -xattrs. - -AFP Get/Scan AccessPrivileges convergence: - -- AFP Get File Information and AFP Scan File Information now use the same - trustee/effective-rights source when filling the WebSDK AccessPrivileges - word. The old static file/directory masks have been replaced with mapping - from `tru_get_eff_rights()` to Read, Write, Open, Create, Delete, Parental, - Search, and Modify File Status Flags. -- File-level readonly attributes still suppress write/delete style AFP - privileges for file replies, while directories expose directory-appropriate - parental/search/status bits based on the effective trustee rights. -- Runtime status: the AFP smoke suite verified the mapping with - `--readonly-user NOPASSUSER --readonly-no-password --prepare-readonly-rights`. - The suite granted `[RF]` on `SYS:PUBLIC/pmdflts.ini`, confirmed the readonly - Get File Information probe reported `rights=0x0500`, checked that Read was - set and Write/Modify Status were clear, then revoked the temporary trustee - assignment. The same run ended with `failures=0`. - -- Follow-up from AFP namespace entry ID smoke: directory AFP entry IDs may use - NetWare namespace/basehandles, but regular files currently keep nwatalk or - fallback AFP IDs because the existing directory-number reverse mapper is not - a reliable file-entry reverse mapper on DOS namespace volumes. - - -### AFP file fork handle lifecycle - -AFP Open File Fork returns a normal mars_nwe/NetWare file handle for the data -fork. File I/O uses the existing NetWare read/write handlers, and handle -lifetime is closed through the normal `NCP 0x42 Close File` path backed by -`nw_close_file()`. There is no separate AFP-private close operation and no -parallel POSIX close path in the AFP frontend. - -Runtime status: the full AFP smoke suite is verified with `failures=0` after -adding close-lifecycle probes. The suite opens the AFP data fork, performs a -read or write through the returned NetWare handle, closes that handle through -`NCP 0x42`, and verifies that later I/O on the old handle is rejected. The -same run keeps Resource Fork opens unsupported with the existing completion -code. - - -### AFP temporary directory handle entry-id resolver coverage - -AFP Alloc Temporary Directory Handle now has smoke coverage for both path-backed -and entry-id-only directory requests. The entry-id-only probe resolves -`SYS:PUBLIC` to directory Entry ID `0x00000004`, sends the allocation request -with `path_len=0`, receives a temporary directory handle, and deallocates it -through the normal NetWare handle cleanup path. - -Runtime status: the full AFP smoke suite is verified with `failures=0` after -adding the entry-id-only temporary directory handle probe. Directories continue -to use the mars_nwe namespace/basehandle path; file AFP xattr entry IDs are not -used for directory-handle allocation. - -### AFP entry-id-relative name lookup coverage - -AFP Get Entry ID From Name now has smoke coverage for the WebSDK entry-id-relative -form. The smoke resolves `SYS:PUBLIC` to directory Entry ID `0x00000004`, -sends the leaf name `pmdflts.ini` relative to that directory Entry ID, and -verifies that the reply returns the same file Entry ID as the path-backed and -NetWare-handle entry-id lookups. - -Runtime status: the full AFP smoke suite is verified with `failures=0` after -adding the entry-id-relative `AFP Get Entry ID From Name` probe. The server -log shows the request routed through the directory namespace/basehandle -resolver and then back into the normal mars_nwe path resolver; file Entry IDs -are still not used as directory bases. - - -### AFP timestamp plausibility smoke coverage - -AFP Set File Information timestamp handling now has smoke coverage for the -individual WebSDK timestamp bitmap bits. The smoke exercises access, create, -modify, and backup timestamp updates and verifies the returned AFP information -record for sane timestamp fields. Timestamp fields that were not selected by -the request may still be logged internally as `-1`; that value only means -"not supplied by this request" and is valid for non-timestamp operations such -as FinderInfo or attribute updates. - -Runtime status: the full AFP smoke suite is verified with `failures=0` after -adding the timestamp plausibility checks. The run confirms the exact Linux -`stat` mtime epoch remains `1700000000` after the AFP modify-time update and -continues to show AFP-only attributes absent when Hidden/System/Archive use the -NetWare attribute path. - -### Final AFP endpoint audit before declaring compatibility slice complete - -After the current AFP smoke-covered endpoint set is otherwise complete, perform -one final endpoint-by-endpoint audit against the WebSDK archive and the Novell -NWAFP headers. The goal is not to add new semantics, but to verify that every -implemented AFP call number, request layout, reply layout, bitmap, completion -code, and unsupported-operation response still matches the published wire -interfaces. - -Checklist for that final audit: - -- compare the `nwconn.c` AFP dispatch table with the WebSDK/NWAFP endpoint list; -- verify legacy and AFP 2.0 variants separately; -- re-check Get/Set/Scan File Information record offsets, lengths, and bitmaps; -- re-check Create, Delete, Rename, Open Fork, and Entry-ID resolver request - layouts; -- confirm Resource Fork behaviour remains intentionally unsupported and returns - the documented completion code used by the smoke tests; -- confirm all NetWare-semantic data still routes through mars_nwe paths - (trustees, attributes, timestamps, namespace, directory handles, - create/open/read/write/close/rename/delete), and only AFP-only metadata stays - in `org.mars-nwe.afp.*` xattrs; -- inspect every implemented AFP handler for AFP-local shortcuts and replace any - remaining NetWare-semantic direct POSIX/xattr logic with existing mars_nwe - functions or wrappers before declaring the slice complete; -- keep the result as the final AFP compatibility report in `tests/afp/README.md`. diff --git a/tests/afp/TODO.md b/tests/afp/TODO.md new file mode 100644 index 0000000..6e478ba --- /dev/null +++ b/tests/afp/TODO.md @@ -0,0 +1,37 @@ +# AFP TODO + +This file contains only AFP follow-up work that is still open. Smoke results, +endpoint inventory, WebSDK audit notes, and implementation history belong in the +neighboring AFP documentation files, not in the root `TODO.md`. + +## Remaining AFP work + +### `0x13 AFP Get Macintosh Info On Deleted Files` + +Current status: + +- Unsupported in the current AFP compatibility slice. +- Documented as salvage/deleted-entry-backend dependent. +- Must not be implemented as an AFP-local deleted-file scan. + +Required backend first: + +- `NCP 0x2222 / 87 / 16` - Scan Salvageable Files +- `NCP 0x2222 / 87 / 17` - Recover Salvageable File +- `NCP 0x2222 / 87 / 18` - Purge Salvageable File +- Optional legacy `NCP 0x2222 / 22 / 27` - Scan Salvageable File (old) + +Future AFP mapping: + +1. Resolve the deleted DOS directory entry through the mars_nwe salvage backend. +2. Return FinderInfo from AFP metadata when available, otherwise zeroes. +3. Return ProDOS information as zeroes unless mars_nwe gains a real ProDOS store. +4. Return resource fork size as zero while resource forks remain unsupported. +5. Return the deleted filename from the salvage/deleted-entry record. + +References: + +- `tests/afp/AFP_DELETED_FILE_INFO.md` +- `tests/afp/AFP_ENDPOINT_INVENTORY.md` +- `tests/afp/AFP_FINAL_AUDIT.md` +- `tests/afp/AFP_WEBSK_AUDIT_FINDINGS.md`