From b95a774becb2ba1d77439fcd024427a26cd6811e Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Tue, 2 Jun 2026 15:18:49 +0000 Subject: [PATCH] docs: audit AFP endpoint coverage --- AI.md | 27 ++++++++----- TODO.md | 18 ++++++--- src/nwconn.c | 112 +++++++++++++++++++++++++++++++-------------------- 3 files changed, 99 insertions(+), 58 deletions(-) diff --git a/AI.md b/AI.md index efa5bf3..609eeca 100644 --- a/AI.md +++ b/AI.md @@ -198,15 +198,24 @@ Schema/import direction: Latest endpoint audit note: -- Patch `0213` closes the high-number `NCP 0x2222/87` / wire `0x57` - namespace/file selectors for the current audit scope. `87/44` Update File - Handle Rights and `87/64`..`87/69` Read/Write/Size/Physical-Record variants - are documented as later-generation NDK additions, so no source stubs are added - under the current 1.x/2.x/3.x plus planned-4.x rule. The in-scope `87` work - now ends with the documented `87/43` stubs from patch `0212`. Next patch - should be `0214`; likely next blocks are the `89` Enhanced Name Space family - as out-of-current-scope documentation, AFP `35`, or another user-selected - endpoint family. +- Patch `0214` audits `NCP 0x2222/35` / wire `0x23` AFP / Mac namespace calls. + The dispatcher uses `afp_request_offset()`, treats `afp_req[0]` as the AFP + SubFunctionCode, maps helper returns `>= 0` to reply `data_len`, and maps + negative helper returns to Completion Code. AFP 35/01 through 35/19 are all + represented in the current source: 35/01+35/13 create directory, 35/02+35/14 + create file, 35/03 delete, 35/04 get entry ID from name, 35/05+35/15 get file + information, 35/06 get entry ID from NetWare handle, 35/07 rename, 35/08 open + file fork, 35/09+35/16 set file information, 35/10+35/17 scan file + information, 35/11 allocate temporary directory handle, 35/12 get entry ID + from path name, 35/18 get DOS name from entry ID, and 35/19 get Macintosh info + on deleted file. No new missing-endpoint source stubs were needed. AFP is a + filesystem/Mac namespace provider area, not NDS; keep metadata on the existing + nwatalk/xattr and shared Salvage paths. + +The next patch number should be `0215` if `0214` was applied. Likely next +blocks are the `89` Enhanced Name Space family as generation-bucketed scope +work, packet burst `0x2222/97`/`101`, deeper `0x2222/23` bindery/property/admin +subfunction coverage, or another user-selected endpoint family. ## Patch workflow diff --git a/TODO.md b/TODO.md index 4cd2069..4afc140 100644 --- a/TODO.md +++ b/TODO.md @@ -179,9 +179,11 @@ Present in the code but not yet fully endpoint-audited: queue prehandlers. - SDK `0x2222/34` / wire `0x22` TTS calls are present in `src/nwconn.c` and have been endpoint-audited as an unsupported/no-rollback compatibility group. -- SDK `0x2222/35` / wire `0x23` AFP calls are present in `src/nwconn.c`; AFP has - separate compatibility tests, but the NCP request-layout audit should still - be completed endpoint by endpoint. +- SDK `0x2222/35` / wire `0x23` AFP calls are present in `src/nwconn.c` and + have been endpoint-audited as the AFP/Mac namespace compatibility block. + AFP has separate smoke coverage under `tests/afp/`; future fixes should be + driven by those tests and client traces rather than a new parallel metadata + store. - SDK `0x2222/65` through `77` / wire `0x41` through `0x4d` are old direct file open/create/read/write/rename/time/copy calls present in `src/nwconn.c`; they have been endpoint-audited as the old direct file-I/O @@ -1214,12 +1216,16 @@ Current status: - Keep AFP metadata restore/lookup paths tied to the existing mars_nwe AFP and nwatalk mechanisms, not a new side database. - Keep the detailed AFP inventory and audit notes in `tests/afp/`. +- Patch `0214` also records the NCP-level AFP 35/01..35/19 coverage inline in + `src/nwconn.c`: all documented NDK/Core-Protocols AFP subfunctions in that + range are represented by the current dispatcher, so no new missing-endpoint + source stubs are needed for the current 1.x/2.x/3.x plus planned-4.x scope. Follow-up: -- Continue the final AFP WebSDK audit only where inventory files still mark an - endpoint as needing layout verification. AFP 0x13 and ProDOSInfo storage are - no longer open TODO items. +- AFP endpoint coverage is now documented at the NCP dispatcher level. Continue + any remaining WebSDK/client-trace cleanup only where `tests/afp/` inventory + files still mark a behavioral or metadata-layout issue. ## Deferred / optional protocol work diff --git a/src/nwconn.c b/src/nwconn.c index 27bff6e..1a382f0 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -5889,121 +5889,147 @@ static int handle_ncp_serv(void) int afp_len = requestlen - afp_off; int ufunc = (afp_len > 0) ? (int)*afp_req : -1; /* - * NetWare AFP calls are server-side NCP entry points for - * Mac namespace semantics: AFP entry IDs, Finder Info, - * AppleDouble metadata, resource forks, and per-volume Mac - * namespace state. + * NCP 0x2222/35 AFP / Mac namespace group. * - * WebSDK / headers identify the old NCP 0x2222/35 AFP - * subfunctions used by nwafp.h, including Create Directory - * (0x01), Create File (0x02), AFP Delete (0x03), Get Entry - * ID From Name (0x04), Get File Information (0x05), Get - * Entry ID From NetWare Handle (0x06), Rename (0x07), Open - * File Fork (0x08), Alloc Temporary Dir Handle (0x0b), Get - * Entry ID From Path Name (0x0c), Get DOS Name From Entry - * ID (0x12), Get Macintosh Info On Deleted Files (0x13), - * the AFP Set File Information write call (0x09), the AFP - * 2.0 create calls (0x0d/0x0e), Get/Set File Information - * (0x0f/0x10), and Scan File Information (0x11). + * Transport handoff: afp_request_offset() selects the AFP + * subfunction byte. afp_req[0] is the AFP SubFunctionCode + * and afp_req[1..] is the subfunction payload. Helper + * return >= 0 becomes reply data_len; helper return < 0 is + * mapped to the NCP Completion Code. * - * Implement the path-name entry-id probe first because the - * SDK helpers use it to test AFP support. The related AFP - * Get Entry ID From Name call accepts a volume/base AFP ID - * plus a modifying path string; until persistent CNID/base - * lookup exists, support the same path-backed SYS:-style - * smoke-test subset. Get Entry ID From NetWare Handle - * maps an already-open mars_nwe file handle back to its - * Unix path and returns the corresponding AFP ID. Open - * File Fork opens the same path-backed subset as a read-only - * data fork and returns a normal NetWare file handle. The - * older AFP Scan File Information (0x0a) now shares the - * same conservative directory-scan helper as the AFP 2.0 - * scan call. Alloc - * Temporary Dir Handle uses the same path-backed subset and - * returns a connection-local NetWare directory handle plus - * effective rights. Then expose - * the read-only AFP Get File Information query for the same - * SYS:-style path inputs. AFP Set File Information (0x09) - * and AFP 2.0 Set File Information (0x10) accept only - * FinderInfo plus the - * metadata-only Invisible/System/Archive file attributes as - * xattr write smoke paths. AFP 2.0 Get File Information - * uses the same request/reply layout for this read-only - * path-backed subset, so route it through the same helper - * until persistent entry-id lookup and richer AFP 2.0 - * metadata are implemented. These calls still require - * the optional AFP xattr metadata backend to be present; without a Mac - * namespace backend, keep returning invalid namespace. + * Provider owner: AFP/Mac namespace filesystem provider. + * These are file/namespace metadata calls, not NDS calls. + * They still depend on the optional nwatalk/xattr metadata + * backend; without that backend the group keeps returning + * invalid namespace / invalid response for unsupported paths. + * + * Coverage result: the NDK/Core-Protocols AFP subfunctions + * 35/01 through 35/19 are all represented below. No new + * missing-endpoint source stubs are needed for the current + * 1.x/2.x/3.x plus planned-4.x scope. */ if (ufunc == 0x01 || ufunc == 0x0d) { + /* 35/01 AFP Create Directory and 35/13 AFP 2.0 Create + * Directory. Request carries volume/base/path and + * creation metadata; reply has no extra payload. + * MARS-NWE routes both through the same path-backed + * directory creation helper. */ int result = afp_create_directory(afp_req, afp_len, responsedata, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x02 || ufunc == 0x0e) { + /* 35/02 AFP Create File and 35/14 AFP 2.0 Create File. + * Request carries volume/base/path, attributes and AFP + * metadata fields; reply has no extra payload. Current + * compatibility path creates the data fork/file and AFP + * metadata through the shared helper. */ int result = afp_create_file(afp_req, afp_len, responsedata, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x03) { + /* 35/03 AFP Delete. Request selects the AFP entry/path; + * reply has no payload. Current helper maps the AFP + * selector to the shared filesystem delete path. */ int result = afp_delete_object(afp_req, afp_len, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x07) { + /* 35/07 AFP Rename. Request carries source and target + * AFP path/name data; reply has no payload. */ int result = afp_rename_object(afp_req, afp_len, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x04) { + /* 35/04 AFP Get Entry ID From Name. Request supplies + * volume/base AFP ID and a modifying path string; reply + * returns AFP entry information. Until persistent CNID + * lookup exists this is the SYS:-style path-backed + * compatibility subset. */ int result = afp_get_entry_id_from_name(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x06) { + /* 35/06 AFP Get Entry ID From NetWare Handle. Request + * contains an open NetWare file handle; reply returns the + * corresponding AFP entry ID for the mapped Unix path. */ int result = afp_get_entry_id_from_netware_handle(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x08) { + /* 35/08 AFP Open File Fork. Request selects AFP entry + * and fork; reply returns a normal NetWare file handle. + * Current compatibility opens the data fork read-only for + * the path-backed subset. */ int result = afp_open_file_fork(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x0b) { + /* 35/11 AFP Alloc Temporary Directory Handle. Request + * carries AFP path selection; reply returns a temporary + * NetWare directory handle plus effective rights. */ int result = afp_alloc_temporary_dir_handle(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x0c) { + /* 35/12 AFP Get Entry ID From Path Name. Request uses a + * path-name selector; reply returns AFP entry ID data. + * SDK helpers use this as an AFP-support probe. */ int result = afp_get_entry_id_from_path_name(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x12) { + /* 35/18 AFP Get DOS Name From Entry ID. Request carries + * an AFP entry ID; reply returns the DOS/NetWare name. */ int result = afp_get_dos_name_from_entry_id(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x13) { + /* 35/19 AFP Get Macintosh Info On Deleted File. Request + * selects a deleted AFP entry; reply returns FinderInfo, + * ProDOSInfo, resource fork size, and deleted filename + * from the shared Salvage snapshot. */ int result = afp_get_macintosh_info_on_deleted_file(afp_req, afp_len, responsedata); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x05 || ufunc == 0x0f) { + /* 35/05 AFP Get File Information and 35/15 AFP 2.0 Get + * File Or Directory Information. Request selects AFP + * entry/path; reply returns AFP metadata and filesystem + * information. Both use the same read-only helper until + * richer persistent entry-id lookup exists. */ int result = afp_get_file_information(afp_req, afp_len, responsedata, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x09 || ufunc == 0x10) { + /* 35/09 AFP Set File Information and 35/16 AFP 2.0 Set + * File Information. Request carries AFP metadata update + * fields; reply has no payload. Current compatibility + * accepts FinderInfo plus metadata-only DOS attribute + * writes through the xattr-backed AFP metadata path. */ int result = afp_set_file_information(afp_req, afp_len, afp_call_name(ufunc)); if (result > -1) data_len = result; else completition = (uint8)-result; } else if (ufunc == 0x0a || ufunc == 0x11) { + /* 35/10 AFP Scan File Information and 35/17 AFP 2.0 Scan + * File Information. Request carries search sequence and + * AFP path/attribute filters; reply returns one scanned + * AFP file-information record in the conservative helper. */ int result = afp_scan_file_information(afp_req, afp_len, responsedata, afp_call_name(ufunc));