nwconn: implement AFP rename through NetWare move paths

This commit is contained in:
a
2026-05-30 20:09:23 +00:00
committed by Mario Fetka
parent cd4ca7c4d9
commit 02e247b133

View File

@@ -1225,6 +1225,114 @@ static int afp_delete_object(uint8 *afp_req, int afp_len,
}
static int afp_rename_object(uint8 *afp_req, int afp_len,
const char *call_name)
/*
* WebSDK / nwafp.h call 0x07 renames or moves an AFP file or directory.
* Keep the operation on existing mars_nwe paths: resolve source and
* destination volume/base-id/path tuples to normal NetWare path strings, then
* delegate to nw_mv_files() for files or nw_mv_dir_between_handles() for
* directories. Do not introduce a direct POSIX rename(2) AFP side path.
*/
{
uint8 volume_number;
uint32 source_entry_id;
uint32 dest_entry_id;
int source_len;
int dest_len_off;
int dest_len;
uint8 source_path[512];
uint8 dest_path[512];
char source_unixname[PATH_MAX];
int volume;
int result;
struct stat stbuff;
if (afp_len < 12) {
XDPRINTF((2,0, "%s rejected: short request len=%d",
call_name, afp_len));
return(-0x7e);
}
volume_number = afp_req[1];
source_entry_id = GET_BE32(afp_req + 2);
dest_entry_id = GET_BE32(afp_req + 6);
source_len = (int)afp_req[10];
if (source_len < 0 || afp_len < 11 + source_len + 1) {
XDPRINTF((2,0, "%s rejected: source boundary check len=%d source_len=%d",
call_name, afp_len, source_len));
return(-0x7e);
}
dest_len_off = 11 + source_len;
dest_len = (int)afp_req[dest_len_off];
if (dest_len < 0 || afp_len < dest_len_off + 1 + dest_len) {
XDPRINTF((2,0, "%s rejected: dest boundary check len=%d dest_len=%d",
call_name, afp_len, dest_len));
return(-0x7e);
}
if (!source_len || !dest_len) {
XDPRINTF((2,0, "%s rejected: empty source/dest source_len=%d dest_len=%d",
call_name, source_len, dest_len));
return(-0x9c);
}
result = afp_build_base_relative_path((int)volume_number, source_entry_id,
afp_req + 11, source_len,
source_path, sizeof(source_path));
if (result < 0) {
XDPRINTF((2,0, "%s source path build failed: vol=%d base=0x%08x path='%s' result=-0x%x",
call_name, (int)volume_number, source_entry_id,
visable_data(afp_req + 11, source_len), -result));
return(result);
}
result = afp_build_base_relative_path((int)volume_number, dest_entry_id,
afp_req + dest_len_off + 1, dest_len,
dest_path, sizeof(dest_path));
if (result < 0) {
XDPRINTF((2,0, "%s dest path build failed: vol=%d base=0x%08x path='%s' result=-0x%x",
call_name, (int)volume_number, dest_entry_id,
visable_data(afp_req + dest_len_off + 1, dest_len), -result));
return(result);
}
volume = conn_get_kpl_unxname(source_unixname, sizeof(source_unixname), 0,
source_path, strlen((char *)source_path));
if (volume < 0) return(volume);
if (stat(source_unixname, &stbuff)) {
XDPRINTF((2,0, "%s source stat failed: vol=%d source_base=0x%08x path='%s' mars_path='%s' unix='%s' errno=%d",
call_name, (int)volume_number, source_entry_id,
visable_data(afp_req + 11, source_len), source_path,
source_unixname, errno));
return(-0x9c);
}
if (S_ISDIR(stbuff.st_mode)) {
result = nw_mv_dir_between_handles(0, source_path, strlen((char *)source_path),
0, dest_path, strlen((char *)dest_path));
} else {
result = nw_mv_files(0x37,
0, source_path, strlen((char *)source_path),
0, dest_path, strlen((char *)dest_path));
}
if (result < 0) {
XDPRINTF((2,0, "%s rename failed: vol=%d source_base=0x%08x dest_base=0x%08x source='%s' dest='%s' result=-0x%x",
call_name, (int)volume_number, source_entry_id, dest_entry_id,
source_path, dest_path, -result));
return(result);
}
XDPRINTF((3,0, "%s: request_vol=%d resolved_vol=%d source_base=0x%08x dest_base=0x%08x source='%s' dest='%s' directory=%d",
call_name, (int)volume_number, volume, source_entry_id, dest_entry_id,
visable_data(afp_req + 11, source_len),
visable_data(afp_req + dest_len_off + 1, dest_len),
S_ISDIR(stbuff.st_mode) ? 1 : 0));
return(0);
}
static int afp_get_entry_id_from_path_name(uint8 *afp_req, int afp_len,
uint8 *response)
{
@@ -4276,6 +4384,11 @@ static int handle_ncp_serv(void)
afp_len, afp_call_name(ufunc));
if (result > -1) data_len = result;
else completition = (uint8)-result;
} else if (ufunc == 0x07) {
int result = afp_rename_object(afp_req,
afp_len, afp_call_name(ufunc));
if (result > -1) data_len = result;
else completition = (uint8)-result;
} else if (ufunc == 0x04) {
int result = afp_get_entry_id_from_name(afp_req,
afp_len, responsedata);