tests: add AFP temporary directory handle entry-id smoke

This commit is contained in:
OAI
2026-05-31 05:26:07 +00:00
committed by Mario Fetka
parent b52c52e421
commit f5ec189c24
3 changed files with 82 additions and 11 deletions

View File

@@ -433,7 +433,7 @@ mapping through the existing NetWare namespace identity path.
## AFP Alloc Temporary Directory Handle smoke test
`afp_temp_dir_handle_smoke` sends the WebSDK-documented NetWare AFP request:
`afp_temp_dir_handle_smoke` sends the WebSDK-documented NetWare AFP request. It can send either a path-backed request or `--entry-id-only`, where it first resolves the directory entry ID through AFP Get Entry ID From Path Name and then sends Alloc Temporary Directory Handle with `path_len=0`:
```text
NCP 0x2222/35/11 AFP Alloc Temporary Directory Handle
@@ -454,6 +454,7 @@ Useful smoke cases for a standard MARS-NWE `SYS` volume are:
```sh
./tests/afp/afp_temp_dir_handle_smoke -S MARS -U SUPERVISOR -P secret SYS:
./tests/afp/afp_temp_dir_handle_smoke -S MARS -U SUPERVISOR -P secret SYS:PUBLIC
./tests/afp/afp_temp_dir_handle_smoke --entry-id-only -S MARS -U SUPERVISOR -P secret SYS:PUBLIC
./tests/afp/afp_temp_dir_handle_smoke -S MARS -U SUPERVISOR -P secret SYS:SYSTEM
./tests/afp/afp_temp_dir_handle_smoke -S MARS -U SUPERVISOR -P secret SYS:BURST
```
@@ -472,7 +473,8 @@ Runtime-verified output and server diagnostic shape:
```text
AFP Alloc Temporary Dir Handle path=SYS: dir_handle=2 rights=0xff
AFP Alloc Temporary Dir Handle path=SYS:PUBLIC dir_handle=2 rights=0xff
AFP Alloc Temporary Dir Handle path=SYS:PUBLIC entry_id=0x00000000 dir_handle=2 rights=0xff
AFP Alloc Temporary Dir Handle path=SYS:PUBLIC entry_id=0x00000004 dir_handle=2 rights=0xff entry-id-only
AFP Alloc Temporary Dir Handle path=SYS:SYSTEM dir_handle=2 rights=0xff
AFP Alloc Temporary Dir Handle path=SYS:BURST dir_handle=2 rights=0xff
AFP Alloc Temporary Dir Handle: vol=0 request_vol=0 entry=0x00000000 path='SYS:' dir_handle=2 rights=0x1ff

View File

@@ -461,6 +461,11 @@ run_cmd \
"./afp_temp_dir_handle_smoke $COMMON_PRINT '$DIR_PATH'" \
"$SCRIPT_DIR/afp_temp_dir_handle_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$DIR_PATH"
run_cmd \
"AFP Alloc Temporary Directory Handle by Entry ID" \
"./afp_temp_dir_handle_smoke --entry-id-only $COMMON_PRINT '$DIR_PATH'" \
"$SCRIPT_DIR/afp_temp_dir_handle_smoke" --entry-id-only -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$DIR_PATH"
if [ -d "$UNIX_DIR_PATH" ] || [ -d "$UNIX_DIR_PATH_DOS" ]; then
run_optional_cmd \
"Prepare AFP Create Directory cleanup" \

View File

@@ -3,8 +3,8 @@
*
* This uses ncpfs/libncp so the request travels through the same NCP path as a
* normal Linux requester. The server-side AFP endpoint returns a temporary
* NetWare directory handle and an effective-rights mask for a path-backed AFP
* request.
* NetWare directory handle and an effective-rights mask for either a
* path-backed AFP request or an entry-id-only request.
*/
#include <errno.h>
@@ -25,6 +25,7 @@
#endif
#define AFP_ALLOC_TEMPORARY_DIR_HANDLE 0x0b
#define AFP_GET_ENTRY_ID_FROM_PATH_NAME 0x0c
#define NWE_INVALID_NAMESPACE 0xbf
#define NWE_INVALID_PATH 0x9c
#define AFP_TEMP_DH_NONE 0xff
@@ -32,17 +33,19 @@
static void usage(const char *prog)
{
fprintf(stderr,
"Usage: %s [--allow-invalid-namespace] [--allow-invalid-path] "
"[--volume N] [--entry-id ID] [ncpfs options] PATH\n"
"Usage: %s [--entry-id-only] [--allow-invalid-namespace] "
"[--allow-invalid-path] [--volume N] [--entry-id ID] "
"[ncpfs options] PATH\n"
"\n"
"ncpfs options are parsed by ncp_initialize(), for example:\n"
" -S SERVER -U USER -P PASSWORD -n\n"
"\n"
"Examples:\n"
" %s -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
" %s --entry-id-only -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
" %s --allow-invalid-namespace -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
" %s --allow-invalid-path -S MARS -U SUPERVISOR -P secret SYS:NO_SUCH_PATH\n",
prog, prog, prog, prog);
prog, prog, prog, prog, prog);
}
static int parse_u32(const char *text, uint32_t *value)
@@ -66,6 +69,46 @@ static void cpu_to_be32(uint32_t v, uint8_t p[4])
p[3] = (uint8_t)v;
}
static uint32_t be32_to_cpu(const uint8_t p[4])
{
return ((uint32_t)p[0] << 24) |
((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) |
(uint32_t)p[3];
}
static NWCCODE afp_get_entry_id_from_path(NWCONN_HANDLE conn, const char *path,
uint32_t *entry_id)
{
NW_FRAGMENT reply;
uint8_t request[1 + 1 + 255];
uint8_t reply_buf[4];
size_t path_len = strlen(path);
NWCCODE err;
if (path_len > 255)
return NWE_INVALID_PATH;
request[0] = 0; /* directory handle 0, raw VOL:path */
request[1] = (uint8_t)path_len;
memcpy(request + 2, path, path_len);
memset(reply_buf, 0, sizeof(reply_buf));
reply.fragAddr.rw = reply_buf;
reply.fragSize = sizeof(reply_buf);
err = NWRequestSimple(conn,
NCPC_SFN(0x23, AFP_GET_ENTRY_ID_FROM_PATH_NAME),
request, 2 + path_len, &reply);
if (err)
return err;
if (reply.fragSize < 4)
return NWE_INVALID_PATH;
*entry_id = be32_to_cpu(reply_buf);
return 0;
}
static void deallocate_dir_handle(NWCONN_HANDLE conn, unsigned int dir_handle)
{
uint8_t rq[1];
@@ -85,6 +128,7 @@ int main(int argc, char **argv)
const char *path = NULL;
int allow_invalid_namespace = 0;
int allow_invalid_path = 0;
int entry_id_only = 0;
uint32_t volume_number = 0;
uint32_t base_entry_id = 0;
unsigned int allocated_dir_handle = AFP_TEMP_DH_NONE;
@@ -109,6 +153,8 @@ int main(int argc, char **argv)
for (i = 1; i < argc; i++) {
if (!strcmp(argv[i], "--allow-invalid-namespace")) {
allow_invalid_namespace = 1;
} else if (!strcmp(argv[i], "--entry-id-only")) {
entry_id_only = 1;
} else if (!strcmp(argv[i], "--allow-invalid-path")) {
allow_invalid_path = 1;
} else if (!strcmp(argv[i], "--volume")) {
@@ -145,7 +191,23 @@ int main(int argc, char **argv)
return 2;
}
path_len = strlen(path);
if (entry_id_only && !base_entry_id) {
err = afp_get_entry_id_from_path(conn, path, &base_entry_id);
if (err) {
fprintf(stderr,
"AFP Get Entry ID From Path Name failed before entry-id-only temporary handle allocation: completion=0x%02x (%u) path=%s\n",
(unsigned int)err & 0xff, (unsigned int)err, path);
ncp_close(conn);
return 1;
}
if (!base_entry_id) {
fprintf(stderr, "AFP Get Entry ID From Path Name returned zero for %s\n", path);
ncp_close(conn);
return 1;
}
}
path_len = entry_id_only ? 0 : strlen(path);
if (path_len > 255) {
fprintf(stderr,
"PATH is too long for AFP Alloc Temporary Directory Handle: %zu\n",
@@ -157,7 +219,8 @@ int main(int argc, char **argv)
request[0] = (uint8_t)volume_number;
cpu_to_be32(base_entry_id, request + 1);
request[5] = (uint8_t)path_len;
memcpy(request + 6, path, path_len);
if (path_len)
memcpy(request + 6, path, path_len);
memset(reply_buf, 0, sizeof(reply_buf));
reply.fragAddr.rw = reply_buf;
@@ -199,8 +262,9 @@ int main(int argc, char **argv)
}
allocated_dir_handle = reply_buf[0];
printf("AFP Alloc Temporary Dir Handle path=%s dir_handle=%u rights=0x%02x\n",
path, allocated_dir_handle, (unsigned int)reply_buf[1]);
printf("AFP Alloc Temporary Dir Handle path=%s entry_id=0x%08x dir_handle=%u rights=0x%02x%s\n",
path, (unsigned int)base_entry_id, allocated_dir_handle,
(unsigned int)reply_buf[1], entry_id_only ? " entry-id-only" : "");
deallocate_dir_handle(conn, allocated_dir_handle);
ncp_close(conn);