nwconn: share AFP entry-id resolver with metadata paths
This commit is contained in:
196
src/nwconn.c
196
src/nwconn.c
@@ -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)) {
|
||||
|
||||
Reference in New Issue
Block a user