nwconn: implement AFP create file through NetWare file creation
All checks were successful
Source release / source-package (push) Successful in 49s

This commit is contained in:
Mario Fetka
2026-05-30 19:35:27 +00:00
parent 0a60e0ce7a
commit 37039a773f

View File

@@ -921,6 +921,130 @@ static int afp_alloc_temporary_dir_handle(uint8 *afp_req, int afp_len,
}
static int afp_create_file(uint8 *afp_req, int afp_len,
uint8 *response, const char *call_name)
/*
* WebSDK / nwafp.h calls 0x02 and 0x0e create an AFP file and return the
* new AFP file ID. AFP Create File creates the file but does not leave it
* open, so route creation through the existing mars_nwe node helpers rather
* than open(2) directly. FinderInfo remains AFP-only metadata and is written
* after the file exists.
*/
{
uint8 volume_number;
uint32 base_entry_id;
int delete_existing;
uint8 *finder_info;
int is_afp20;
int path_len_off;
int path_off;
int path_len;
uint8 create_path[512];
char unixname[PATH_MAX];
int volume;
int result;
struct stat stbuff;
uint32 entry_id = 0;
int fallback = 0;
if (afp_len < 40) {
XDPRINTF((2,0, "%s rejected: short request len=%d",
call_name, afp_len));
return(-0x7e);
}
is_afp20 = (afp_req[0] == 0x0e);
path_len_off = is_afp20 ? 45 : 39;
path_off = is_afp20 ? 46 : 40;
if (afp_len <= path_len_off) {
XDPRINTF((2,0, "%s rejected: short request len=%d",
call_name, afp_len));
return(-0x7e);
}
volume_number = afp_req[1];
base_entry_id = GET_BE32(afp_req + 2);
delete_existing = afp_req[6] ? 1 : 0;
finder_info = afp_req + 7;
path_len = (int)afp_req[path_len_off];
if (path_len < 0 || afp_len < path_off + path_len) {
XDPRINTF((2,0, "%s rejected: boundary check len=%d path_len=%d",
call_name, afp_len, path_len));
return(-0x7e);
}
if (!nwatalk_backend_available()) {
XDPRINTF((3,0, "%s rejected: libatalk backend unavailable", call_name));
return(-0xbf);
}
if (!path_len) {
XDPRINTF((2,0, "%s rejected: empty path vol=%d base=0x%08x",
call_name, (int)volume_number, base_entry_id));
return(-0x9c);
}
result = afp_build_base_relative_path((int)volume_number, base_entry_id,
afp_req + path_off, path_len,
create_path, sizeof(create_path));
if (result < 0) {
XDPRINTF((2,0, "%s path build failed: vol=%d base=0x%08x path='%s' result=-0x%x",
call_name, (int)volume_number, base_entry_id,
visable_data(afp_req + path_off, path_len), -result));
return(result);
}
volume = conn_get_kpl_unxname(unixname, sizeof(unixname), 0,
create_path, strlen((char *)create_path));
if (volume < 0) return(volume);
if (!stat(unixname, &stbuff)) {
if (S_ISDIR(stbuff.st_mode)) {
XDPRINTF((2,0, "%s rejected: existing directory vol=%d base=0x%08x path='%s' unix='%s'",
call_name, (int)volume_number, base_entry_id,
visable_data(afp_req + path_off, path_len), unixname));
return(-0xff);
}
if (!delete_existing) {
XDPRINTF((2,0, "%s rejected: file exists vol=%d base=0x%08x path='%s' unix='%s'",
call_name, (int)volume_number, base_entry_id,
visable_data(afp_req + path_off, path_len), unixname));
return(-0xff);
}
result = nw_delete_files(0, 0, create_path, strlen((char *)create_path));
if (result < 0) {
XDPRINTF((2,0, "%s delete-existing failed: vol=%d base=0x%08x path='%s' mars_path='%s' result=-0x%x",
call_name, (int)volume_number, base_entry_id,
visable_data(afp_req + path_off, path_len), create_path,
-result));
return(result);
}
}
result = nw_creat_node(volume, (uint8 *)unixname, 0);
if (result < 0) {
XDPRINTF((2,0, "%s create failed: vol=%d base=0x%08x path='%s' mars_path='%s' unix='%s' result=-0x%x",
call_name, (int)volume_number, base_entry_id,
visable_data(afp_req + path_off, path_len), create_path,
unixname, -result));
return(result);
}
if (stat(unixname, &stbuff)) return(-0x9c);
(void)nwatalk_set_finder_info(unixname, finder_info, 32);
entry_id = afp_get_or_create_entry_id(unixname, volume, &stbuff, &fallback);
U32_TO_BE32(entry_id, response);
XDPRINTF((3,0, "%s: request_vol=%d resolved_vol=%d base=0x%08x path='%s' entry=0x%08x%s",
call_name, (int)volume_number, volume, base_entry_id,
visable_data(afp_req + path_off, path_len), entry_id,
fallback ? " fallback" : ""));
return(4);
}
static int afp_create_directory(uint8 *afp_req, int afp_len,
uint8 *response, const char *call_name)
/*
@@ -4059,6 +4183,12 @@ static int handle_ncp_serv(void)
afp_call_name(ufunc));
if (result > -1) data_len = result;
else completition = (uint8)-result;
} else if (ufunc == 0x02 || ufunc == 0x0e) {
int result = afp_create_file(afp_req,
afp_len, responsedata,
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);