ncp: add legacy salvage endpoints
This commit is contained in:
285
src/namspace.c
285
src/namspace.c
@@ -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 */
|
||||
|
||||
27
src/nwconn.c
27
src/nwconn.c
@@ -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 */
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user