nwconn: derive AFP entry ids from NetWare handles
All checks were successful
Source release / source-package (push) Successful in 45s

This commit is contained in:
Mario Fetka
2026-05-30 18:14:32 +00:00
parent a4dd5c3678
commit faa44d060b

View File

@@ -485,11 +485,35 @@ static int afp_resolve_path_volume(uint8 *path, int path_len, char *unixname, in
}
static uint32 afp_namespace_entry_id(int volume, const struct stat *stb)
/*
* AFP entry IDs should follow the same object identity mars_nwe already uses
* for namespace/basehandle calls whenever possible. That keeps AFP
* entry-id-based lookups on the existing NetWare object resolver instead of
* maintaining a parallel AFP path database.
*/
{
DEV_NAMESPACE_MAP dnm;
uint32 entry_id;
if (!stb) return(0);
dnm.dev = stb->st_dev;
dnm.namespace = NAME_DOS;
entry_id = nw_vol_inode_to_handle(volume, stb->st_ino, &dnm);
/* Keep the old AFP fallback range and reserve zero as invalid. */
if (!entry_id || (entry_id & 0x80000000U))
return(0);
return(entry_id);
}
static uint32 afp_fallback_entry_id(int volume, const struct stat *stb)
/*
* Build a stable local AFP entry id from Unix identity data when libatalk has
* no stored CNID/AppleDouble id yet. This is not a NetWare-internal directory
* base number; it is only the AFP id returned by the path-name probe.
* Build a stable local AFP entry id from Unix identity data when the NetWare
* namespace handle cannot represent the object and libatalk has no stored
* CNID/AppleDouble id yet. This is only a legacy compatibility fallback.
*/
{
uint32 hash = 2166136261U;
@@ -518,17 +542,21 @@ static uint32 afp_get_or_create_entry_id(const char *unixname, int volume,
const struct stat *stb,
int *fallback_out)
/*
* Return a persistent mars_nwe AFP entry id when available. If neither the
* mars_nwe xattr nor Netatalk/libatalk metadata contains an id yet, derive the
* existing stat-backed compatibility id and cache that id in mars_nwe's private
* AFP xattr namespace. The first caller still records fallback diagnostics so
* the log remains honest about the id origin; follow-up requests should read the
* xattr directly and no longer need the temporary stat derivation path.
* Return the mars_nwe namespace basehandle as AFP entry id whenever it can be
* represented. nwatalk/libatalk metadata remains a cache/legacy fallback for
* entries that cannot be mapped by the NetWare namespace table.
*/
{
uint32 entry_id = 0;
int result;
entry_id = afp_namespace_entry_id(volume, stb);
if (entry_id) {
if (fallback_out) *fallback_out = 0;
(void)nwatalk_set_entry_id(unixname, entry_id);
return(entry_id);
}
result = nwatalk_get_entry_id(unixname, &entry_id);
if (!result && entry_id) {
if (fallback_out) *fallback_out = 0;
@@ -988,6 +1016,46 @@ static int afp_find_dos_name_from_entry_id_rec(int volume,
return(-0xff); /* Failure, no files found */
}
static int afp_namespace_path_from_entry_id(int volume, uint32 entry_id,
char *path, int path_len)
/*
* First try the existing NetWare namespace reverse mapper. It returns
* length-prefixed DOS path components; AFP 0x12 wants a single DOSPathString,
* so join those components with '/'.
*/
{
uint8 raw[512];
int raw_len;
int in = 0;
int out = 0;
if (!path || path_len < 1) return(-0xff);
*path = '\0';
raw_len = map_directory_number_to_path(volume, entry_id, NAME_DOS,
raw, sizeof(raw));
if (raw_len < 0)
return(raw_len);
if (!raw_len)
return(0);
while (in < raw_len) {
int len = raw[in++];
if (len < 0 || in + len > raw_len) return(-0xff);
if (out) {
if (out + 1 >= path_len) return(-0x96);
path[out++] = '/';
}
if (out + len >= path_len) return(-0x96);
memcpy(path + out, raw + in, len);
out += len;
in += len;
}
path[out] = '\0';
return(0);
}
static int afp_find_dos_name_from_entry_id(int volume, uint32 entry_id,
char *path, int path_len)
{
@@ -1041,12 +1109,19 @@ static int afp_get_dos_name_from_entry_id(uint8 *afp_req, int afp_len,
return(-0xbf); /* Invalid Namespace */
}
result = afp_find_dos_name_from_entry_id((int)volume_number, entry_id,
path, sizeof(path));
result = afp_namespace_path_from_entry_id((int)volume_number, entry_id,
path, sizeof(path));
if (result) {
XDPRINTF((2,0, "AFP Get DOS Name From Entry ID lookup failed: vol=%d entry=0x%08x result=-0x%x",
(int)volume_number, entry_id, -result));
return(result);
int legacy_result;
legacy_result = afp_find_dos_name_from_entry_id((int)volume_number,
entry_id, path,
sizeof(path));
if (legacy_result) {
XDPRINTF((2,0, "AFP Get DOS Name From Entry ID lookup failed: vol=%d entry=0x%08x namespace=-0x%x legacy=-0x%x",
(int)volume_number, entry_id, -result, -legacy_result));
return(legacy_result);
}
}
len = strlen(path);