207 lines
6.2 KiB
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;
|
|
}
|