diff --git a/src/nwconn.c b/src/nwconn.c index 4491a7f..7218dfc 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -489,6 +489,8 @@ static int afp_resolve_path_volume(uint8 *path, int path_len, char *unixname, in static int afp_namespace_path_from_entry_id(int volume, uint32 entry_id, char *path, int path_len); +static int afp_find_dos_name_from_entry_id(int volume, uint32 entry_id, + char *path, int path_len); static int afp_build_base_relative_path(int volume, uint32 base_entry_id, uint8 *path, int path_len, @@ -800,10 +802,67 @@ static int afp_open_file_fork(uint8 *afp_req, int afp_len, } if (!path_len) { - XDPRINTF((2,0, "AFP Open File Fork rejected: entry-id-only lookup unsupported vol=%d entry=0x%08x fork=%d access=0x%02x", - (int)volume_number, request_entry_id, (int)fork_indicator, - (int)access_mode)); - return(-0x9c); /* Invalid Path until persistent entry-id lookup exists */ + char dos_path[256]; + char entry_path[512]; + int dos_result; + int used; + + if (!request_entry_id) { + XDPRINTF((2,0, "AFP Open File Fork rejected: missing path and entry id vol=%d fork=%d access=0x%02x", + (int)volume_number, (int)fork_indicator, (int)access_mode)); + return(-0x9c); + } + + dos_result = afp_find_dos_name_from_entry_id((int)volume_number, + request_entry_id, + dos_path, sizeof(dos_path)); + if (dos_result) { + XDPRINTF((2,0, "AFP Open File Fork entry-id lookup failed: vol=%d entry=0x%08x fork=%d access=0x%02x result=-0x%x", + (int)volume_number, request_entry_id, (int)fork_indicator, + (int)access_mode, -dos_result)); + return(dos_result); + } + if (volume_number >= used_nw_volumes || !nw_volumes[volume_number].sysname) + return(-0x98); + + used = slprintf(entry_path, sizeof(entry_path), "%s:%s", + nw_volumes[volume_number].sysname, dos_path); + if (used < 0 || used >= (int)sizeof(entry_path)) return(-0x96); + + path_volume = afp_resolve_path_volume((uint8 *)entry_path, used, + unixname, sizeof(unixname)); + if (path_volume < 0) { + XDPRINTF((2,0, "AFP Open File Fork entry-id path resolve failed: request_vol=%d entry=0x%08x fork=%d access=0x%02x path='%s' result=-0x%x", + (int)volume_number, request_entry_id, (int)fork_indicator, + (int)access_mode, entry_path, -path_volume)); + return(path_volume); + } + + memset(&fileinfo, 0, sizeof(fileinfo)); + if (!(access_mode & 0x03)) + access_mode |= 0x01; + + fhandle = nw_creat_open_file(0, (uint8 *)entry_path, used, &fileinfo, + 0, (int)(access_mode & 0x0f), 0, + (int)(ncprequest->task)); + if (fhandle < 0) { + XDPRINTF((2,0, "AFP Open File Fork entry-id open failed: request_vol=%d resolved_vol=%d entry=0x%08x fork=%d access=0x%02x path='%s' result=-0x%x", + (int)volume_number, path_volume, request_entry_id, + (int)fork_indicator, (int)access_mode, entry_path, -fhandle)); + return(fhandle); + } + + fork_len = GET_BE32(fileinfo.size); + response[0] = 0; + response[1] = 0; + U32_TO_32(fhandle, response + 2); + U32_TO_BE32(fork_len, response + 6); + + XDPRINTF((3,0, "AFP Open File Fork: vol=%d request_vol=%d entry=0x%08x fork=%d access=0x%02x path='%s' handle=%d fork_len=%u entry-id", + path_volume, (int)volume_number, request_entry_id, + (int)fork_indicator, (int)access_mode, entry_path, + fhandle, fork_len)); + return(10); } path_volume = afp_resolve_path_volume(afp_req + 9, path_len,