Files
mars-nwe/tests/salvage/ncp_delete_smoke.c

207 lines
6.2 KiB
C

/*
* Linux smoke helper for classic NetWare file create/delete.
*
* The helper intentionally uses the official ncpfs ncplib create/close/erase
* APIs, not private request packing or a local Unix unlink. It is used by
* the salvage smoke script to verify that mars_nwe captures files deleted
* through the server path.
*/
#include <errno.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ncp/nwcalls.h>
#include <ncp/ncplib.h>
#include <ncp/kernel/ncp.h>
static void usage(const char *prog)
{
fprintf(stderr,
"Usage: %s [--expect-delete CODE] [--create-only] [--delete-only] "
"[--payload TEXT] [ncpfs options] PATH\n"
"\n"
"ncpfs options are parsed by ncp_initialize(), for example:\n"
" -S SERVER -U USER -P PASSWORD -n\n"
"\n"
"Example:\n"
" %s -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/SALVAGE.TXT\n",
prog, prog);
}
static int parse_u32(const char *text, uint32_t *value)
{
char *end = NULL;
unsigned long v;
errno = 0;
v = strtoul(text, &end, 0);
if (errno || !end || *end || v > 0xffffffffUL)
return -1;
*value = (uint32_t)v;
return 0;
}
int main(int argc, char **argv)
{
NWCONN_HANDLE conn;
long init_err = 0;
const char *path = NULL;
uint32_t expect_delete = 0xffffffffU;
struct ncp_file_info file_info;
int create = 1;
int delete = 1;
const char *payload = NULL;
int i;
long err;
if (NWCallsInit(NULL, NULL)) {
fprintf(stderr, "NWCallsInit failed\n");
return 2;
}
conn = ncp_initialize(&argc, argv, 1, &init_err);
if (!conn) {
fprintf(stderr, "ncp_initialize/login failed: %ld\n", init_err);
usage(argv[0]);
return 2;
}
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--expect-delete")) {
if (++i >= argc || parse_u32(argv[i], &expect_delete) ||
expect_delete > 255) {
fprintf(stderr, "invalid --expect-delete value\n");
ncp_close(conn);
return 2;
}
} else if (!strcmp(argv[i], "--create-only")) {
create = 1;
delete = 0;
} else if (!strcmp(argv[i], "--delete-only")) {
create = 0;
delete = 1;
} else if (!strcmp(argv[i], "--payload")) {
if (++i >= argc) {
fprintf(stderr, "missing --payload value\n");
ncp_close(conn);
return 2;
}
payload = argv[i];
} else if (!strcmp(argv[i], "-h") || !strcmp(argv[i], "--help")) {
usage(argv[0]);
ncp_close(conn);
return 0;
} else if (!path) {
path = argv[i];
} else {
fprintf(stderr, "unexpected argument: %s\n", argv[i]);
usage(argv[0]);
ncp_close(conn);
return 2;
}
}
if (!path) {
usage(argv[0]);
ncp_close(conn);
return 2;
}
if (create) {
memset(&file_info, 0, sizeof(file_info));
err = ncp_create_file(conn, 0, path, 0, &file_info);
if (err) {
fprintf(stderr, "NCP create failed: path=%s error=0x%04x\n",
path, (unsigned int)err);
ncp_close(conn);
return 1;
}
err = ncp_close_file(conn, file_info.file_id);
if (err) {
fprintf(stderr,
"NCP close after create failed: path=%s error=0x%04x\n",
path, (unsigned int)err);
ncp_close(conn);
return 1;
}
if (payload) {
size_t payload_len = strlen(payload);
memset(&file_info, 0, sizeof(file_info));
err = ncp_open_file(conn, 0, path, 0, AR_WRITE_ONLY, &file_info);
if (err) {
fprintf(stderr,
"NCP open for write failed: path=%s error=0x%04x\n",
path, (unsigned int)err);
ncp_close(conn);
return 1;
}
err = ncp_write(conn, file_info.file_id, 0, payload_len, payload);
if (err != (long)payload_len) {
fprintf(stderr,
"NCP write failed: path=%s wrote=%ld expected=%lu\n",
path, err, (unsigned long)payload_len);
ncp_close_file(conn, file_info.file_id);
ncp_close(conn);
return 1;
}
err = ncp_write(conn, file_info.file_id, payload_len, 1, "\n");
if (err != 1) {
fprintf(stderr,
"NCP write newline failed: path=%s wrote=%ld expected=1\n",
path, err);
ncp_close_file(conn, file_info.file_id);
ncp_close(conn);
return 1;
}
err = ncp_close_file(conn, file_info.file_id);
if (err) {
fprintf(stderr,
"NCP close after write failed: path=%s error=0x%04x\n",
path, (unsigned int)err);
ncp_close(conn);
return 1;
}
printf("NCP write path=%s bytes=%lu verified\n",
path, (unsigned long)(payload_len + 1));
}
printf("NCP create path=%s verified\n", path);
}
if (delete) {
err = ncp_erase_file(conn, 0, path, 0);
if (expect_delete != 0xffffffffU) {
if (err != (long)expect_delete) {
fprintf(stderr,
"NCP delete completion mismatch: path=%s got=0x%04x expected=0x%02x\n",
path, (unsigned int)err, (unsigned int)expect_delete);
ncp_close(conn);
return 1;
}
printf("NCP delete returned expected completion 0x%02x: path=%s\n",
(unsigned int)expect_delete, path);
} else if (err) {
fprintf(stderr, "NCP delete failed: path=%s error=0x%04x\n",
path, (unsigned int)err);
ncp_close(conn);
return 1;
} else {
printf("NCP delete path=%s verified\n", path);
}
}
ncp_close(conn);
return 0;
}