nwconn: derive AFP entry ids from NetWare handles
All checks were successful
Source release / source-package (push) Successful in 45s
All checks were successful
Source release / source-package (push) Successful in 45s
This commit is contained in:
103
src/nwconn.c
103
src/nwconn.c
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user