nwconn: share AFP entry-id resolver with metadata paths

This commit is contained in:
Mario Fetka
2026-05-31 04:40:27 +00:00
parent 711dceb42a
commit 77a40f9ed2

View File

@@ -491,6 +491,10 @@ 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_resolve_entry_id_path(int volume, uint32 entry_id,
char *entry_path, int entry_path_len,
char *unixname, int unixname_len,
int *resolved_volume, int *used_len);
static int afp_build_base_relative_path(int volume, uint32 base_entry_id,
uint8 *path, int path_len,
@@ -802,40 +806,20 @@ static int afp_open_file_fork(uint8 *afp_req, int afp_len,
}
if (!path_len) {
char dos_path[256];
char entry_path[512];
int dos_result;
int used;
int entry_result;
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) {
entry_result = afp_resolve_entry_id_path((int)volume_number,
request_entry_id,
entry_path, sizeof(entry_path),
unixname, sizeof(unixname),
&path_volume, &used);
if (entry_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);
(int)access_mode, -entry_result));
return(entry_result);
}
memset(&fileinfo, 0, sizeof(fileinfo));
@@ -943,9 +927,34 @@ static int afp_alloc_temporary_dir_handle(uint8 *afp_req, int afp_len,
}
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 */
char entry_path[512];
int entry_len;
int entry_result;
entry_result = afp_resolve_entry_id_path((int)volume_number,
request_entry_id,
entry_path, sizeof(entry_path),
unixname, sizeof(unixname),
&path_volume, &entry_len);
if (entry_result) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle entry-id lookup failed: vol=%d entry=0x%08x result=-0x%x",
(int)volume_number, request_entry_id, -entry_result));
return(entry_result);
}
dirhandle = nw_alloc_dir_handle(0, (uint8 *)entry_path, entry_len, 0, 1,
(int)(ncprequest->task), &eff_rights);
if (dirhandle < 0) {
XDPRINTF((2,0, "AFP Alloc Temporary Dir Handle entry-id allocation failed: request_vol=%d resolved_vol=%d entry=0x%08x path='%s' result=-0x%x",
(int)volume_number, path_volume, request_entry_id,
entry_path, -dirhandle));
return(dirhandle);
}
response[0] = (uint8)dirhandle;
response[1] = (uint8)eff_rights;
XDPRINTF((3,0, "AFP Alloc Temporary Dir Handle: vol=%d request_vol=%d entry=0x%08x path='%s' dir_handle=%d rights=0x%x entry-id",
path_volume, (int)volume_number, request_entry_id,
entry_path, dirhandle, eff_rights));
return(2);
}
path_volume = afp_resolve_path_volume(afp_req + 7, path_len,
@@ -1625,6 +1634,49 @@ static int afp_find_dos_name_from_entry_id(int volume, uint32 entry_id,
return(-0xff);
}
static int afp_resolve_entry_id_path(int volume, uint32 entry_id,
char *entry_path, int entry_path_len,
char *unixname, int unixname_len,
int *resolved_volume, int *used_len)
/*
* Resolve a documented AFP entry-id-only request to a normal VOL:PATH string
* and Unix path. The reverse lookup is deliberately based on mars_nwe's AFP
* xattr entry-id cache rather than treating regular file IDs as DOS namespace
* directory numbers. Callers can then reuse the normal mars_nwe wrappers for
* rights, attributes, open/share and timestamp semantics.
*/
{
char dos_path[256];
int result;
int used;
if (!entry_path || entry_path_len < 1 || !unixname || unixname_len < 1)
return(-0x7e);
if (volume < 0 || volume >= used_nw_volumes || !nw_volumes[volume].sysname)
return(-0x98);
if (!entry_id)
return(-0x9c);
result = afp_find_dos_name_from_entry_id(volume, entry_id,
dos_path, sizeof(dos_path));
if (result)
return(result);
used = slprintf(entry_path, entry_path_len, "%s:%s",
nw_volumes[volume].sysname, dos_path);
if (used < 0 || used >= entry_path_len)
return(-0x96);
result = afp_resolve_path_volume((uint8 *)entry_path, used,
unixname, unixname_len);
if (result < 0)
return(result);
if (resolved_volume) *resolved_volume = result;
if (used_len) *used_len = used;
return(0);
}
static int afp_get_dos_name_from_entry_id(uint8 *afp_req, int afp_len,
uint8 *response)
{
@@ -1922,7 +1974,9 @@ static int afp_get_file_information(uint8 *afp_req, int afp_len,
int path_len;
int volume;
char unixname[PATH_MAX];
uint8 empty_path = 0;
char entry_path[512];
uint8 *path_data;
int path_data_len;
uint32 entry_id = 0;
int fallback = 0;
int result;
@@ -1949,34 +2003,43 @@ static int afp_get_file_information(uint8 *afp_req, int afp_len,
}
if (!path_len) {
XDPRINTF((2,0, "%s rejected: entry-id-only lookup unsupported vol=%d entry=0x%08x mask=0x%04x",
call_name, (int)volume_number, request_entry_id, request_mask));
return(-0x9c); /* Invalid Path until persistent entry-id lookup exists */
result = afp_resolve_entry_id_path((int)volume_number, request_entry_id,
entry_path, sizeof(entry_path),
unixname, sizeof(unixname),
&volume, &path_data_len);
if (result) {
XDPRINTF((2,0, "%s entry-id lookup failed: vol=%d entry=0x%08x mask=0x%04x result=-0x%x",
call_name, (int)volume_number, request_entry_id,
request_mask, -result));
return(result);
}
path_data = (uint8 *)entry_path;
} else {
path_data = afp_req + 9;
path_data_len = path_len;
volume = conn_get_kpl_unxname(unixname, sizeof(unixname), 0,
path_data, path_data_len);
if (volume < 0) {
XDPRINTF((2,0, "%s path resolve failed: vol=%d entry=0x%08x path='%s' result=-0x%x",
call_name, (int)volume_number, request_entry_id,
visable_data(path_data, path_data_len), -volume));
return(volume);
}
}
volume = conn_get_kpl_unxname(unixname, sizeof(unixname), 0,
path_len ? afp_req + 9 : &empty_path,
path_len);
if (volume < 0) {
XDPRINTF((2,0, "%s path resolve failed: vol=%d entry=0x%08x path='%s' result=-0x%x",
call_name, (int)volume_number, request_entry_id,
visable_data(afp_req + 9, path_len), -volume));
return(volume);
}
result = afp_fill_file_info_response(unixname, afp_req + 9, path_len,
result = afp_fill_file_info_response(unixname, path_data, path_data_len,
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,
visable_data(afp_req + 9, path_len), unixname, -result, errno));
visable_data(path_data, path_data_len), unixname, -result, errno));
return(result);
}
XDPRINTF((3,0, "%s: vol=%d entry=0x%08x mask=0x%04x path='%s' reply_entry=0x%08x%s",
call_name, (int)volume_number, request_entry_id, request_mask,
visable_data(afp_req + 9, path_len), entry_id,
visable_data(path_data, path_data_len), entry_id,
fallback ? " fallback" : ""));
return(result);
}
@@ -2064,6 +2127,9 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
int path_off;
int path_volume;
char unixname[PATH_MAX];
char entry_path[512];
int entry_path_len = 0;
int resolved_by_entry_id = 0;
struct stat stbuff;
int result;
uint16 log_attrs = 0;
@@ -2128,9 +2194,19 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
}
if (!path_len) {
XDPRINTF((2,0, "%s rejected: entry-id-only lookup unsupported vol=%d entry=0x%08x mask=0x%04x",
call_name, (int)volume_number, request_entry_id, request_mask));
return(-0x9c); /* Invalid Path until persistent entry-id lookup exists */
result = afp_resolve_entry_id_path((int)volume_number, request_entry_id,
entry_path, sizeof(entry_path),
unixname, sizeof(unixname),
&path_volume, &entry_path_len);
if (result) {
XDPRINTF((2,0, "%s entry-id lookup failed: vol=%d entry=0x%08x mask=0x%04x result=-0x%x",
call_name, (int)volume_number, request_entry_id,
request_mask, -result));
return(result);
}
path_data = (uint8 *)entry_path;
path_len = entry_path_len;
resolved_by_entry_id = 1;
}
if (request_mask & ~(AFP_FILE_BITMAP_ATTRIBUTES | AFP_FILE_BITMAP_ACCESS_DATE |
@@ -2165,13 +2241,15 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
if (request_mask & AFP_FILE_BITMAP_FINDER_INFO)
needs_afp_metadata_modify = 1;
path_volume = afp_resolve_path_volume(path_data, path_len,
unixname, sizeof(unixname));
if (path_volume < 0) {
XDPRINTF((2,0, "%s path resolve failed: request_vol=%d entry=0x%08x mask=0x%04x path='%s' result=-0x%x",
call_name, (int)volume_number, request_entry_id, request_mask,
visable_data(path_data, path_len), -path_volume));
return(path_volume);
if (!resolved_by_entry_id) {
path_volume = afp_resolve_path_volume(path_data, path_len,
unixname, sizeof(unixname));
if (path_volume < 0) {
XDPRINTF((2,0, "%s path resolve failed: request_vol=%d entry=0x%08x mask=0x%04x path='%s' result=-0x%x",
call_name, (int)volume_number, request_entry_id, request_mask,
visable_data(path_data, path_len), -path_volume));
return(path_volume);
}
}
if (stat(unixname, &stbuff)) {