# AFP integration smoke tests Status: finished for the current AFP compatibility slice. This directory contains the AFP endpoint smoke tests and the single remaining AFP documentation file for this test group. Earlier endpoint-inventory, WebSDK-audit, deleted-file-info, and TODO notes have been folded into this README so the AFP test directory has one Markdown entry point. ## Scope The AFP endpoints are backed by mars_nwe itself rather than Netatalk/libatalk. AFP handlers must keep NetWare semantics on mars_nwe core paths: - path, namespace, create, delete, rename, and directory operations use the existing mars_nwe path/namespace and object-lifecycle helpers; - file I/O uses normal mars_nwe NetWare file handles; - rights checks use mars_nwe trustee/effective-rights logic; - Hidden, System, Archive, timestamps, creator/modifier, backup/archive, and related metadata use mars_nwe attribute/archive/fileinfo paths; - AFP-only xattrs are limited to `user.org.mars-nwe.afp.entry-id`, `user.org.mars-nwe.afp.finder-info`, `user.org.mars-nwe.afp.prodos-info`, and future AFP-only bits in `user.org.mars-nwe.afp.attributes`. Resource forks remain unsupported. AFP resource-fork requests should return the documented completion code instead of inventing a parallel storage backend. ## Endpoint inventory The generated helper remains the source of truth for fresh checks: ```sh tests/afp/afp_endpoint_inventory.py tests/afp/afp_endpoint_inventory.py --json ``` Current coverage: | Subfn | Name | Status | Backend discipline | | --- | --- | --- | --- | | `0x01` | AFP Create Directory | implemented | mars_nwe namespace/object lifecycle | | `0x02` | AFP Create File | implemented | mars_nwe namespace/object lifecycle; AFP xattr only for file entry-id metadata | | `0x03` | AFP Delete | implemented | mars_nwe namespace/object lifecycle | | `0x04` | AFP Get Entry ID From Name | implemented | mars_nwe namespace/basehandle; directory bases only | | `0x05` | AFP Get File Information | implemented | mars_nwe attributes/rights plus AFP metadata xattrs | | `0x06` | AFP Get Entry ID From NetWare Handle | implemented | mars_nwe file-handle lookup, then AFP entry-id metadata | | `0x07` | AFP Rename | implemented | mars_nwe namespace/object lifecycle; AFP entry-id metadata follows renamed files | | `0x08` | AFP Open File Fork | implemented for data fork | mars_nwe file handles; resource fork unsupported | | `0x09` | AFP Set File Information | implemented | mars_nwe attributes/archive/fileinfo/trustee; AFP xattrs only for AFP metadata | | `0x0a` | AFP Scan File Information | implemented | mars_nwe directory scan; entry-id-only bases must resolve to directories | | `0x0b` | AFP Alloc Temporary Dir Handle | implemented | mars_nwe namespace and directory handles | | `0x0c` | AFP Get Entry ID From Path Name | implemented | mars_nwe namespace plus AFP entry-id metadata | | `0x0d` | AFP 2.0 Create Directory | implemented | same discipline as `0x01` | | `0x0e` | AFP 2.0 Create File | implemented | same discipline as `0x02` | | `0x0f` | AFP 2.0 Get File Information | implemented | same discipline as `0x05` | | `0x10` | AFP 2.0 Set File Information | implemented | same discipline as `0x09` | | `0x11` | AFP 2.0 Scan File Information | implemented | same discipline as `0x0a` | | `0x12` | AFP Get DOS Name From Entry ID | implemented | mars_nwe namespace and AFP entry-id reverse lookup | | `0x13` | AFP Get Macintosh Info On Deleted Files | implemented | adapter over the shared salvage backend | ## WebSDK / Novell audit result The AFP WebSDK pass confirmed the `NCP 0x2222 / function 35` map above. The uploaded reference tree contained AFP HTML reference pages rather than a single `nwafp.h`; the checked pages were under: ```text /mnt/data/websdk_full/websdk/htmldoc/nwhtm/redleg14/a_apiref/0002R001.htm ... /mnt/data/websdk_full/websdk/htmldoc/nwhtm/redleg14/a_apiref/0002R018.htm ``` The deleted-file dependency check also used the normal salvage reference pages for Scan, Recover, Purge, and old Scan Salvageable File. No AFP subfunction beyond `0x13` appeared in the WebSDK AFP reference TOC. Important audit decisions now considered closed for this slice: - entry-id-only `0x0a` / `0x11` scans are supported only when the AFP entry ID resolves to a directory through mars_nwe namespace/basehandle logic; - file AFP xattr entry IDs are not valid scan bases; - `0x13` is salvage-backed and must not scan live paths, `.recycle`, or `.salvage` directly from AFP code. ## AFP `0x13` deleted-file metadata `AFP Get Macintosh Info On Deleted Files` is NCP `0x2222 / 35 / 19` and WebSDK subfunction byte `0x13`. Its request is `VolumeNumber` plus `DOSDirectoryNumber`; the reply contains FinderInfo[32], ProDOSInfo[6], resource fork size, and the deleted file name. The implementation is finished for the current slice and remains a thin adapter over the shared mars_nwe salvage/deleted-entry backend: 1. resolve the deleted DOS directory entry through the salvage backend; 2. return FinderInfo from the salvage JSON snapshot; 3. return ProDOS information from the nwatalk xattr-backed salvage JSON snapshot field `prodos_info_hex`; 4. return resource fork size from the salvage JSON snapshot; 5. return the deleted original filename from the salvage record. The AFP code must not create a second deleted-file store and must not expose the backend `.recycle` / `.salvage` repositories as AFP-visible paths. ## Build The helpers require ncpfs/libncp headers and library, so they are optional and not built by default. Enable the test build and build individual helpers or the suite target: ```sh cmake -DMARS_NWE_BUILD_TESTS=ON ... cmake --build . --target afp_entry_id_smoke cmake --build . --target afp_file_info_smoke cmake --build . --target afp_scan_info_smoke cmake --build . --target afp_set_file_info_smoke cmake --build . --target afp_deleted_info_smoke cmake --build . --target afp_smoke_suite ``` ## Smoke suite `afp_smoke_suite.sh` is the single AFP integration entry point. CMake copies it into the build-tree `tests/afp` directory through the `afp_smoke_suite` target so the runtime helper stays in sync with source changes. Example from the build `tests/afp` directory: ```sh ./afp_smoke_suite.sh \ -S MARS -U SUPERVISOR -P secret \ --path SYS:PUBLIC/pmdflts.ini \ --unix-path /var/mars_nwe/SYS/public/pmdflts.ini \ --log /var/log/mars_nwe/nw.log \ --out /tmp/mars-afp-smoke.txt ``` The suite covers Entry ID lookup, Entry ID from NetWare handle, Get File Information, Scan File Information, Alloc Temporary Directory Handle, Create Directory, Create File, Delete, Rename, Open File Fork, Set File Information, DOS name lookup, and AFP `0x13` deleted-file metadata. It also checks the AFP xattrs on the tested Unix file: ```text user.org.mars-nwe.afp.finder-info user.org.mars-nwe.afp.prodos-info user.org.mars-nwe.afp.attributes user.org.mars-nwe.afp.entry-id ``` Use `--no-log` when the server log is unavailable or collected separately. Use `--stop-on-failure` for strict bisect-style runs; by default the script keeps going so one failing endpoint does not hide later AFP output. ## Rights-negative coverage The suite can optionally exercise Modify-rights failures with a second user: ```sh ./afp_smoke_suite.sh \ -S MARS -U SUPERVISOR -P secret \ --path SYS:PUBLIC/pmdflts.ini \ --unix-path /var/mars_nwe/SYS/public/pmdflts.ini \ --readonly-user NOPASSUSER --readonly-no-password \ --prepare-readonly-rights \ --out /tmp/mars-afp-smoke.txt ``` `--prepare-readonly-rights` uses `nwrevoke` and `nwgrant -r '[RF]'` to grant read and file-scan rights without Modify. The negative probes verify that FinderInfo, Hidden, and System metadata writes are rejected while the SUPERVISOR positive path still succeeds. Use this only on smoke files or paths where removing an explicit trustee assignment for the readonly test user is acceptable. ## Completion status The AFP test group is complete for the current compatibility slice. Verified runs have completed with `failures=0`, including FinderInfo/ProDOSInfo xattr checks, AFP 35/19 deleted-file metadata, legacy and AFP 2.0 Set File Information, Hidden/System/Archive mapping through the NetWare attribute path, and Modify-rights negative coverage. Future AFP work should keep using this README as the single documentation entry point for the test directory and should add new runtime checks to `afp_smoke_suite.sh` rather than creating unrelated top-level smoke scripts.