nwconn: implement AFP temporary directory handles
All checks were successful
Source release / source-package (push) Successful in 49s

Implement the WebSDK/nwafp.h NCP 0x2222/35 AFP subfunction 0x0b, Alloc Temporary Directory Handle, for the same conservative path-backed subset used by the current AFP Entry ID and File Information probes.\n\nThe documented request carries an AFP volume number, a base AFP Entry ID, and an optional AFP-style path.  mars_nwe still has no persistent CNID/base-ID lookup, so this patch deliberately accepts only requests with a path component and rejects entry-id-only allocation as Invalid Path.  For the supported smoke-test path, raw SYS:-style paths are resolved through the existing NetWare path machinery and the final handle is allocated with nw_alloc_dir_handle() as a temporary, task-scoped NetWare directory handle.\n\nThe implementation keeps the AFP namespace gate intact: without the optional Netatalk/libatalk backend, the endpoint continues to return Invalid Namespace rather than pretending that the Mac namespace exists.  With the backend enabled, successful replies contain the allocated temporary directory handle and the effective-rights mask returned by the existing directory-handle table.  Diagnostics include the AFP volume/base Entry ID input, path, returned handle, and rights so smoke-test output can be matched to server logs.\n\nAdd a Linux ncpfs/libncp smoke helper for the new endpoint.  The helper sends the AFP 0x0b request through NWRequestSimple(), prints the returned handle and rights mask, and immediately deallocates the handle in the same connection via the normal NetWare Deallocate Directory Handle call.  The README documents that these handles are connection/task-local and must not be copied into later tests or reused from server logs.\n\nTests:\n- git diff --check\n- gcc -fsyntax-only tests/linux/afp_temp_dir_handle_smoke.c with temporary local ncpfs header stubs\n\nNot run:\n- Full CMake build in this container: missing gdbm/ncpfs development headers/libraries.\n\nTODO:\n- Replace the path-backed subset with persistent CNID/base-ID lookup once the AFP metadata backend grows durable directory identity support.\n- Verify live Linux smoke cases against SYS:, SYS:PUBLIC, SYS:SYSTEM, and SYS:BURST on a mars_nwe host with ENABLE_NETATALK_LIBATALK=ON.
This commit is contained in:
Mario Fetka
2026-05-30 07:25:15 +00:00
parent 776c7e7510
commit 162ff2b10f
5 changed files with 331 additions and 1 deletions

View File

@@ -611,6 +611,68 @@ static int afp_get_entry_id_from_netware_handle(uint8 *afp_req, int afp_len,
return(6);
}
static int afp_alloc_temporary_dir_handle(uint8 *afp_req, int afp_len,
uint8 *response)
/*
* WebSDK / nwafp.h call 0x0b allocates a temporary NetWare directory handle
* from AFP namespace input: volume number, AFP Entry ID, and optional AFP-style
* path. Until a persistent CNID/base-ID map exists, accept the same raw
* SYS:-style path-backed subset used by the other implemented AFP probes and
* delegate the final handle allocation to the existing NetWare directory-handle
* table.
*/
{
uint8 volume_number;
uint32 request_entry_id;
int path_len;
int eff_rights = 0;
int dirhandle;
if (afp_len < 7) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle rejected: short request len=%d",
afp_len));
return(-0x7e); /* NCP Boundary Check Failed */
}
volume_number = afp_req[1];
request_entry_id = GET_BE32(afp_req + 2);
path_len = (int)afp_req[6];
if (path_len < 0 || afp_len < 7 + path_len) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle rejected: boundary check len=%d path_len=%d",
afp_len, path_len));
return(-0x7e);
}
if (!nwatalk_backend_available()) {
XDPRINTF((3,0, "AFP Alloc Temporary Dir Handle rejected: libatalk backend unavailable"));
return(-0xbf); /* invalid namespace */
}
if (!path_len) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle rejected: entry-id-only lookup unsupported vol=%d entry=0x%08x",
(int)volume_number, request_entry_id));
return(-0x9c); /* Invalid Path until persistent entry-id lookup exists */
}
dirhandle = nw_alloc_dir_handle(0, afp_req + 7, path_len, 0, 1,
(int)(ncprequest->task), &eff_rights);
if (dirhandle < 0) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle path resolve failed: vol=%d entry=0x%08x path='%s' result=-0x%x",
(int)volume_number, request_entry_id,
visable_data(afp_req + 7, path_len), -dirhandle));
return(dirhandle);
}
response[0] = (uint8)dirhandle;
response[1] = (uint8)eff_rights;
XDPRINTF((3,0, "AFP Alloc Temporary Dir Handle: vol=%d entry=0x%08x path='%s' dir_handle=%d rights=0x%02x",
(int)volume_number, request_entry_id,
visable_data(afp_req + 7, path_len), dirhandle, eff_rights));
return(2);
}
static int afp_get_entry_id_from_path_name(uint8 *afp_req, int afp_len,
uint8 *response)
{
@@ -2969,7 +3031,10 @@ static int handle_ncp_serv(void)
* 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. Then expose
* Unix path and returns the corresponding AFP ID. 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 2.0 Get File Information
* uses the same request/reply layout for this read-only
@@ -2989,6 +3054,11 @@ static int handle_ncp_serv(void)
afp_len, responsedata);
if (result > -1) data_len = result;
else completition = (uint8)-result;
} else if (ufunc == 0x0b) {
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) {
int result = afp_get_entry_id_from_path_name(afp_req,
afp_len, responsedata);