ncp: add legacy salvage endpoints

This commit is contained in:
OpenAI
2026-05-31 19:03:54 +00:00
committed by Mario Fetka
parent c441ff0f57
commit 4bfb1a46bd
5 changed files with 339 additions and 1 deletions

View File

@@ -2852,6 +2852,238 @@ int handle_func_0x57_salvage_scan(uint8 *q, int request_len,
}
static void nsp_salvage_datetime_lh(time_t t, uint8 *p)
{
uint8 b[2];
uint16 tmv;
uint16 dtv;
un_time_2_nw(t, b, 0);
tmv = GET_16(b);
un_date_2_nw(t, b, 0);
dtv = GET_16(b);
U32_TO_32(((uint32)dtv << 16) | tmv, p);
}
static int nsp_salvage_dbe_from_short_handle(int dir_handle, DIR_BASE_ENTRY **out)
{
NW_HPATH nwp;
int result;
if (!out)
return(-0x9c);
memset(&nwp, 0, sizeof(nwp));
nwp.base[0] = (uint8)dir_handle;
nwp.flag = 0;
nwp.components = 0;
result = build_base(NAME_DOS, &nwp, nwp.pathes, 0, NULL, 0);
if (result < 0)
return(result);
*out = dir_base[result];
nwp_stat(&((*out)->nwpath), "nsp_salvage_dbe_from_short_handle");
if (!S_ISDIR((*out)->nwpath.statb.st_mode))
return(-0x9c);
return(result);
}
static int nsp_salvage_scan_by_dbe(DIR_BASE_ENTRY *dbe,
unsigned long sequence,
struct nwsalvage_scan_result *scan)
{
int result;
if (!dbe || !scan)
return(-0x9c);
memset(scan, 0, sizeof(*scan));
result = nwsalvage_scan_directory(dbe->nwpath.volume,
(char *)dbe->nwpath.path,
dbe->basehandle, sequence, scan);
if (result < 0)
return(-0x98);
if (result == 0)
return(-0xff);
return(0);
}
static int nsp_salvage_find_current_by_dbe(DIR_BASE_ENTRY *dbe,
unsigned long sequence,
struct nwsalvage_scan_result *scan)
{
unsigned long previous_sequence;
int result;
previous_sequence = sequence ? sequence - 1 : 0xffffffffUL;
result = nsp_salvage_scan_by_dbe(dbe, previous_sequence, scan);
if (result)
return(result);
if (scan->scan_sequence != sequence ||
scan->scan_directory_base != dbe->basehandle)
return(-0xff);
return(0);
}
static int nsp_salvage_build_old_info(const struct nwsalvage_scan_result *scan,
uint8 *p)
{
const struct nwsalvage_metadata_entry *entry = &scan->metadata;
const char *name = entry->original_name[0] ? entry->original_name : "";
int namelen = min((int)strlen(name), 12);
memset(p, 0, 130);
U32_TO_32((uint32)scan->scan_sequence, p + 0);
U16_TO_16((uint16)scan->scan_directory_base, p + 4);
U32_TO_32((uint32)entry->attributes, p + 6);
p[10] = 0;
p[11] = 0;
p[12] = NAME_DOS;
p[13] = (uint8)namelen;
memcpy(p + 14, name, namelen);
nsp_salvage_datetime_lh((time_t)entry->mtime, p + 26);
U32_TO_BE32(0, p + 30);
nsp_salvage_datetime_lh((time_t)entry->mtime, p + 34);
U32_TO_BE32((uint32)entry->netware_archiver_id, p + 38);
nsp_salvage_datetime_lh((time_t)entry->mtime, p + 42);
U32_TO_BE32((uint32)entry->netware_modifier_id, p + 46);
U32_TO_BE32((uint32)entry->size, p + 50);
U16_TO_16((uint16)entry->inherited_rights_mask, p + 98);
un_date_2_nw((time_t)entry->atime, p + 100, 0);
nsp_salvage_datetime_lh((time_t)entry->deleted_at, p + 102);
nsp_salvage_datetime_lh((time_t)entry->deleted_at, p + 106);
U32_TO_BE32(nsp_salvage_deletor_id(entry->deleted_by), p + 110);
return(130);
}
int handle_func_0x16_salvage_scan(uint8 *q, int request_len,
uint8 *responsedata, int task)
{
int dir_handle;
uint32 sequence;
DIR_BASE_ENTRY *dbe = NULL;
struct nwsalvage_scan_result scan;
int result;
(void)task;
if (!q || request_len < 6 || q[0] != 0x1b)
return(-0xfb);
dir_handle = (int)q[1];
sequence = GET_32(q + 2);
result = nsp_salvage_dbe_from_short_handle(dir_handle, &dbe);
if (result < 0)
return(result);
result = nsp_salvage_scan_by_dbe(dbe, sequence, &scan);
if (result)
return(result);
result = nsp_salvage_build_old_info(&scan, responsedata);
XDPRINTF((3, 0,
"INFO SALVAGE 22/27 DONE fn=0x16 sub=0x1b dh=0x%02x seq=0x%08lx next=0x%08lx name=\"%s\"",
dir_handle, (unsigned long)sequence,
(unsigned long)scan.scan_sequence, scan.metadata.original_name));
return(result);
}
int handle_func_0x16_salvage_recover(uint8 *q, int request_len,
uint8 *responsedata, int task)
{
int dir_handle;
uint32 sequence;
int file_len;
int new_len;
DIR_BASE_ENTRY *dbe = NULL;
struct nwsalvage_scan_result scan;
char *dest_unixname;
int result;
(void)responsedata;
if (!q || request_len < 8 || q[0] != 0x1c)
return(-0xfb);
dir_handle = (int)q[1];
sequence = GET_BE32(q + 2);
file_len = (int)q[6];
if (request_len < 8 + file_len)
return(-0xfb);
new_len = (int)q[7 + file_len];
if (request_len < 8 + file_len + new_len)
return(-0xfb);
result = nsp_salvage_dbe_from_short_handle(dir_handle, &dbe);
if (result < 0)
return(result);
result = nsp_salvage_find_current_by_dbe(dbe, sequence, &scan);
if (result)
return(result);
dest_unixname = alloc_nwpath2unix_extra(&(dbe->nwpath), 0,
scan.metadata.original_name);
if (!dest_unixname)
return(-0x96);
result = nwsalvage_recover_scan_result(dbe->nwpath.volume, &scan,
dest_unixname, task);
xfree(dest_unixname);
if (result < 0) {
if (errno == EEXIST)
return(-0xfe);
return(-0x98);
}
if (result == 0)
return(-0xff);
XDPRINTF((3, 0,
"INFO SALVAGE 22/28 DONE fn=0x16 sub=0x1c dh=0x%02x seq=0x%08lx name=\"%s\"",
dir_handle, (unsigned long)sequence, scan.metadata.original_name));
return(0);
}
int handle_func_0x16_salvage_purge(uint8 *q, int request_len,
uint8 *responsedata, int task)
{
int dir_handle;
uint32 sequence;
DIR_BASE_ENTRY *dbe = NULL;
struct nwsalvage_scan_result scan;
int result;
(void)responsedata;
(void)task;
if (!q || request_len < 6 || q[0] != 0x1d)
return(-0xfb);
dir_handle = (int)q[1];
sequence = GET_BE32(q + 2);
result = nsp_salvage_dbe_from_short_handle(dir_handle, &dbe);
if (result < 0)
return(result);
result = nsp_salvage_find_current_by_dbe(dbe, sequence, &scan);
if (result)
return(result);
result = nwsalvage_purge_scan_result(&scan);
if (result < 0)
return(-0x98);
if (result == 0)
return(-0xff);
XDPRINTF((3, 0,
"INFO SALVAGE 22/29 DONE fn=0x16 sub=0x1d dh=0x%02x seq=0x%08lx name=\"%s\"",
dir_handle, (unsigned long)sequence, scan.metadata.original_name));
return(0);
}
int handle_func_0x57_salvage_recover(uint8 *q, int request_len,
uint8 *responsedata, int task)
{
@@ -2932,6 +3164,57 @@ int handle_func_0x57_salvage_recover(uint8 *q, int request_len,
return(0);
}
int handle_func_0x57_salvage_purge(uint8 *q, int request_len,
uint8 *responsedata, int task)
{
int namespace;
uint32 scan_sequence;
uint32 volume;
uint32 directory_base;
DIR_BASE_ENTRY *dbe;
struct nwsalvage_scan_result scan;
int result;
(void)responsedata;
(void)task;
if (!q || request_len < 15 || q[0] != 0x12)
return(-0xfb);
namespace = (int)q[1];
scan_sequence = GET_32(q + 3);
volume = GET_32(q + 7);
directory_base = GET_32(q + 11);
if (volume >= (uint32)used_nw_volumes)
return(-0x98);
result = find_base_entry((int)volume, directory_base);
if (result < 0)
return(result);
dbe = dir_base[result];
nwp_stat(&(dbe->nwpath), "nsp_handle_salvage_purge");
if (!S_ISDIR(dbe->nwpath.statb.st_mode))
return(-0x9c);
result = nsp_salvage_find_current_by_dbe(dbe, scan_sequence, &scan);
if (result)
return(result);
result = nwsalvage_purge_scan_result(&scan);
if (result < 0)
return(-0x98);
if (result == 0)
return(-0xff);
XDPRINTF((3, 0,
"INFO SALVAGE 87/18 DONE fn=0x57 sub=0x12 ns=0x%02x seq=0x%08lx vol=0x%08lx base=0x%08lx name=\"%s\"",
namespace, (unsigned long)scan_sequence, (unsigned long)volume,
(unsigned long)directory_base, scan.metadata.original_name));
return(0);
}
int handle_func_0x57(uint8 *p, int request_len,
uint8 *responsedata, int task)
{
@@ -3165,7 +3448,7 @@ static int code = 0;
break;
case 0x12 : /* 87/18 Purge Salvageable File */
result = -0xfb;
result = handle_func_0x57_salvage_purge(p - 1, request_len, responsedata, task);
break;
case 0x14 : /* Search for File or Subdir Set */

View File

@@ -3349,6 +3349,33 @@ static int handle_ncp_serv(void)
}
break;
case 0x1b : { /* Scan Salvageable Files, old 22/27 */
int result = handle_func_0x16_salvage_scan(p, requestlen - 2,
responsedata,
(int)(ncprequest->task));
if (result > -1) data_len = result;
else completition = (uint8)(-result);
}
break;
case 0x1c : { /* Recover Salvageable File, old 22/28 */
int result = handle_func_0x16_salvage_recover(p, requestlen - 2,
responsedata,
(int)(ncprequest->task));
if (result > -1) data_len = result;
else completition = (uint8)(-result);
}
break;
case 0x1d : { /* Purge Salvageable File, old 22/29 */
int result = handle_func_0x16_salvage_purge(p, requestlen - 2,
responsedata,
(int)(ncprequest->task));
if (result > -1) data_len = result;
else completition = (uint8)(-result);
}
break;
case 0x1e : { /* SCAN a Directory, e.g. used by ndir.exe */
struct INPUT {
uint8 header[7]; /* Requestheader */

View File

@@ -2161,6 +2161,25 @@ static int nwsalvage_copy_payload_with_novell_io(int volume,
return(result);
}
int nwsalvage_purge_scan_result(const struct nwsalvage_scan_result *scan)
{
int failed = 0;
if (!scan) {
errno = EINVAL;
return(-1);
}
if (scan->recycle_path[0] && unlink(scan->recycle_path) < 0 && errno != ENOENT)
failed = 1;
if (scan->metadata_path[0] && unlink(scan->metadata_path) < 0 && errno != ENOENT)
failed = 1;
if (failed)
return(-1);
return(1);
}
int nwsalvage_recover_scan_result(int volume,
const struct nwsalvage_scan_result *scan,
const char *dest_unixname, int task)