docs: audit AFP endpoint coverage

This commit is contained in:
Mario Fetka
2026-06-02 15:18:49 +00:00
parent 6865a42555
commit b95a774bec
3 changed files with 99 additions and 58 deletions

27
AI.md
View File

@@ -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

18
TODO.md
View File

@@ -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

View File

@@ -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));