148 lines
4.0 KiB
C
148 lines
4.0 KiB
C
/*
|
|
* Linux smoke helper for reading a NetWare file through ncpfs/ncplib.
|
|
*
|
|
* The helper is intentionally small and uses the public ncplib open/read/close
|
|
* calls. The salvage smoke script uses it instead of local Unix cat so the
|
|
* content check goes through the same NCP path that created/recovered the file.
|
|
*/
|
|
|
|
#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 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 --expect hello -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/SALVAGE.TXT\n",
|
|
prog, prog);
|
|
}
|
|
|
|
static int content_matches(const char *buf, size_t len, const char *expected)
|
|
{
|
|
size_t expected_len;
|
|
|
|
if (!expected)
|
|
return 1;
|
|
|
|
expected_len = strlen(expected);
|
|
if (len == expected_len && !memcmp(buf, expected, expected_len))
|
|
return 1;
|
|
if (len == expected_len + 1 && buf[expected_len] == '\n' &&
|
|
!memcmp(buf, expected, expected_len))
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
NWCONN_HANDLE conn;
|
|
long init_err = 0;
|
|
const char *path = NULL;
|
|
const char *expected = NULL;
|
|
struct ncp_file_info file_info;
|
|
char *buf = NULL;
|
|
size_t alloc_len;
|
|
long err;
|
|
int i;
|
|
int rc = 1;
|
|
|
|
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")) {
|
|
if (++i >= argc) {
|
|
fprintf(stderr, "missing --expect value\n");
|
|
ncp_close(conn);
|
|
return 2;
|
|
}
|
|
expected = 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;
|
|
}
|
|
|
|
memset(&file_info, 0, sizeof(file_info));
|
|
err = ncp_open_file(conn, 0, path, 0, AR_READ_ONLY, &file_info);
|
|
if (err) {
|
|
fprintf(stderr, "NCP open for read failed: path=%s error=0x%04x\n",
|
|
path, (unsigned int)err);
|
|
ncp_close(conn);
|
|
return 1;
|
|
}
|
|
|
|
alloc_len = file_info.file_length ? (size_t)file_info.file_length : 1;
|
|
buf = malloc(alloc_len + 1);
|
|
if (!buf) {
|
|
fprintf(stderr, "out of memory reading path=%s size=%lu\n",
|
|
path, (unsigned long)alloc_len);
|
|
ncp_close_file(conn, file_info.file_id);
|
|
ncp_close(conn);
|
|
return 1;
|
|
}
|
|
|
|
err = ncp_read(conn, file_info.file_id, 0, alloc_len, buf);
|
|
if (err < 0) {
|
|
fprintf(stderr, "NCP read failed: path=%s error=%ld\n", path, err);
|
|
goto out;
|
|
}
|
|
|
|
buf[err] = '\0';
|
|
if (err > 0 && fwrite(buf, 1, (size_t)err, stdout) != (size_t)err) {
|
|
fprintf(stderr, "stdout write failed while reading path=%s\n", path);
|
|
goto out;
|
|
}
|
|
|
|
if (!content_matches(buf, (size_t)err, expected)) {
|
|
fprintf(stderr,
|
|
"NCP read content mismatch: path=%s bytes=%ld expected='%s'\n",
|
|
path, err, expected ? expected : "");
|
|
goto out;
|
|
}
|
|
|
|
fprintf(stderr, "NCP read path=%s bytes=%ld verified\n", path, err);
|
|
rc = 0;
|
|
|
|
out:
|
|
free(buf);
|
|
ncp_close_file(conn, file_info.file_id);
|
|
ncp_close(conn);
|
|
return rc;
|
|
}
|