From f0864c115039a66c2bdf17c7c32c23c7ec1df6fa Mon Sep 17 00:00:00 2001 From: Mario Fetka Date: Sat, 30 May 2026 20:55:53 +0000 Subject: [PATCH] nwconn: align AFP get and scan info layouts with WebSDK --- src/nwconn.c | 48 +++++++++++++++++++++--------------------------- 1 file changed, 21 insertions(+), 27 deletions(-) diff --git a/src/nwconn.c b/src/nwconn.c index 612616c..9f7c8e1 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -1784,6 +1784,7 @@ static int afp_fill_file_info_response(const char *unixname, const uint8 *display_path, int display_path_len, int volume, + int include_prodos_info, uint8 *response, uint32 *entry_id_out, int *fallback_out) @@ -1799,7 +1800,7 @@ static int afp_fill_file_info_response(const char *unixname, entry_id = afp_get_or_create_entry_id(unixname, volume, &stbuff, fallback_out); - memset(response, 0, 120); + memset(response, 0, include_prodos_info ? 120 : 114); U32_TO_BE32(entry_id, response + 0); U32_TO_BE32(parent_id, response + 4); U16_TO_BE16(afp_basic_attributes(volume, unixname, &stbuff), response + 8); @@ -1854,7 +1855,7 @@ static int afp_fill_file_info_response(const char *unixname, /* ProDOS info at offset 114 stays zero until a real Mac namespace maps it. */ if (entry_id_out) *entry_id_out = entry_id; - return(120); + return(include_prodos_info ? 120 : 114); } static int afp_get_file_information(uint8 *afp_req, int afp_len, @@ -1909,7 +1910,8 @@ static int afp_get_file_information(uint8 *afp_req, int afp_len, } result = afp_fill_file_info_response(unixname, afp_req + 9, path_len, - volume, response, &entry_id, &fallback); + volume, afp_req[0] == 0x0f, + response, &entry_id, &fallback); if (result < 0) { XDPRINTF((2,0, "%s stat failed: vol=%d entry=0x%08x path='%s' unix='%s' result=-0x%x errno=%d", call_name, (int)volume_number, request_entry_id, @@ -2251,7 +2253,7 @@ static int afp_scan_file_information(uint8 *afp_req, int afp_len, int seen = 0; int result; - if (afp_len < 15) { + if (afp_len < 17) { XDPRINTF((2,0, "%s rejected: short request len=%d", call_name, afp_len)); return(-0x7e); /* NCP Boundary Check Failed */ @@ -2262,25 +2264,16 @@ static int afp_scan_file_information(uint8 *afp_req, int afp_len, last_seen_id = GET_BE32(afp_req + 6); /* - * WebSDK documents AFP Scan File Information (0x0a) and AFP 2.0 Scan - * File Information (0x11) with a DesiredResponseCount word between - * MacLastSeenID and SearchBitMap. Earlier smoke coverage used a compact - * internal layout without that word. Accept both so existing probes keep - * working, while new tests exercise the documented header layout. + * WebSDK / nwafp.h layout only. AFP has no mars_nwe compact request + * variant here: after the subfunction byte the packet contains volume, + * base entry ID, last-seen ID, desired response count, search bitmap, + * request bitmap, path length, then the AFP path string. */ - if (afp_len >= 17 && afp_len >= 17 + (int)afp_req[16]) { - desired_count = GET_BE16(afp_req + 10); - search_mask = GET_BE16(afp_req + 12); - request_mask = GET_BE16(afp_req + 14); - path_len = (int)afp_req[16]; - path_off = 17; - } else { - desired_count = 1; - search_mask = GET_BE16(afp_req + 10); - request_mask = GET_BE16(afp_req + 12); - path_len = (int)afp_req[14]; - path_off = 15; - } + desired_count = GET_BE16(afp_req + 10); + search_mask = GET_BE16(afp_req + 12); + request_mask = GET_BE16(afp_req + 14); + path_len = (int)afp_req[16]; + path_off = 17; if (path_len < 0 || afp_len < path_off + path_len) { XDPRINTF((2,0, "%s rejected: boundary check len=%d path_len=%d path_off=%d", @@ -2332,7 +2325,7 @@ static int afp_scan_file_information(uint8 *afp_req, int afp_len, child_entry_id = afp_get_or_create_entry_id(childname, volume, &stbuff, &child_fallback); - if (last_seen_id && !seen) { + if (last_seen_id && last_seen_id != 0xffffffffU && !seen) { if (child_entry_id == last_seen_id) seen = 1; continue; @@ -2349,19 +2342,20 @@ static int afp_scan_file_information(uint8 *afp_req, int afp_len, } result = afp_fill_file_info_response(childname, display_path, display_path_len, - volume, response + 4, + volume, afp_req[0] == 0x11, + response + 2, &entry_id, &fallback); if (result < 0) continue; - U32_TO_BE32(entry_id ? entry_id : child_entry_id, response); + U16_TO_BE16(1, response); closedir(dir); - XDPRINTF((3,0, "%s: vol=%d entry=0x%08x last=0x%08x desired=%u mask=0x%04x req=0x%04x path='%s' reply_entry=0x%08x%s", + XDPRINTF((3,0, "%s: vol=%d entry=0x%08x last=0x%08x desired=%u mask=0x%04x req=0x%04x path='%s' count=1 reply_entry=0x%08x%s", call_name, (int)volume_number, request_entry_id, last_seen_id, (unsigned)desired_count, search_mask, request_mask, visable_data(afp_req + path_off, path_len), entry_id ? entry_id : child_entry_id, (fallback || child_fallback) ? " fallback" : "")); - return(4 + 120); + return(2 + result); } closedir(dir);