tests: add AFP open file fork entry-id smoke
All checks were successful
Source release / source-package (push) Successful in 52s
All checks were successful
Source release / source-package (push) Successful in 52s
This commit is contained in:
@@ -502,20 +502,25 @@ NCP 0x2222/35/08 AFP Open File Fork
|
||||
```
|
||||
|
||||
mars_nwe supports raw `VOL:`-style path requests such as `SYS:` or
|
||||
`HOME:` with base Entry ID zero and opens only the AFP data fork. Read and
|
||||
write data-fork opens are routed through the existing NetWare file open/share
|
||||
path (`nw_creat_open_file()`/`file_creat_open()`), so trustee rights, read-only
|
||||
`HOME:` with base Entry ID zero and opens only the AFP data fork. It also
|
||||
accepts entry-id-only data-fork opens for files whose AFP entry id is already
|
||||
persisted in the `org.mars-nwe.afp.entry-id` nwatalk metadata. Read and write
|
||||
data-fork opens are routed through the existing NetWare file open/share path
|
||||
(`nw_creat_open_file()`/`file_creat_open()`), so trustee rights, read-only
|
||||
attributes, and share-deny checks stay shared with regular NCP file opens. For
|
||||
path-backed requests, mars_nwe resolves the effective NetWare volume from the
|
||||
raw path prefix instead of assuming volume 0. On success the server returns the
|
||||
normal six-byte NetWare file handle shape used by AFP handle APIs plus the
|
||||
current data-fork length. The smoke helper immediately closes the returned
|
||||
NetWare file handle in the same connection.
|
||||
raw path prefix instead of assuming volume 0. Entry-id-only file opens reverse
|
||||
resolve through the AFP/nwatalk metadata cache, not through DOS namespace
|
||||
directory numbers. On success the server returns the normal six-byte NetWare
|
||||
file handle shape used by AFP handle APIs plus the current data-fork length.
|
||||
The smoke helper immediately closes the returned NetWare file handle in the
|
||||
same connection.
|
||||
|
||||
Useful smoke cases for a standard MARS-NWE `SYS` volume are:
|
||||
|
||||
```sh
|
||||
./tests/linux/afp_open_file_fork_smoke -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini
|
||||
./tests/linux/afp_open_file_fork_smoke --entry-id-only -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini
|
||||
./tests/linux/afp_open_file_fork_smoke -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/ohlogscr.bat
|
||||
```
|
||||
|
||||
@@ -529,6 +534,7 @@ against the standard DOS utility files produced:
|
||||
|
||||
```text
|
||||
AFP Open File Fork path=SYS:PUBLIC/pmdflts.ini handle=1 fork=0 access=0x01 fork_len=8161
|
||||
AFP Open File Fork path=SYS:PUBLIC/pmdflts.ini entry_id=0x32d8e6b2 handle=1 fork=0 access=0x01 fork_len=8161 entry-id-only
|
||||
AFP Open File Fork path=SYS:PUBLIC/ohlogscr.bat handle=1 fork=0 access=0x01 fork_len=1296
|
||||
```
|
||||
|
||||
@@ -548,12 +554,13 @@ then removed with AFP Delete:
|
||||
```sh
|
||||
./tests/linux/afp_create_file_smoke -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/afpwrit
|
||||
./tests/linux/afp_open_file_fork_smoke --access 0x02 -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/afpwrit
|
||||
./tests/linux/afp_open_file_fork_smoke --entry-id-only --access 0x02 -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/afpwrit
|
||||
./tests/linux/afp_delete_smoke -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/afpwrit
|
||||
```
|
||||
|
||||
Resource-fork opens (`--fork 1`) and Entry-ID-only open remain unsupported until
|
||||
AppleDouble/resource-fork support and persistent CNID/base-ID lookup exist. The
|
||||
smoke helper can assert the resource-fork rejection explicitly:
|
||||
Resource-fork opens (`--fork 1`) remain unsupported until AppleDouble/resource
|
||||
fork support exists. The smoke helper can assert the resource-fork rejection
|
||||
explicitly:
|
||||
|
||||
```sh
|
||||
./tests/linux/afp_open_file_fork_smoke --expect-completion 0x9c --fork 1 -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
* Linux smoke test for NetWare AFP Open File Fork.
|
||||
*
|
||||
* This uses ncpfs/libncp so the request travels through the same NCP path as a
|
||||
* normal Linux requester. mars_nwe routes path-backed AFP data-fork read and
|
||||
* write opens through the normal NetWare open/share path and returns a normal
|
||||
* NetWare file handle, which this helper closes before exiting.
|
||||
* normal Linux requester. mars_nwe routes path-backed and entry-id-backed AFP
|
||||
* data-fork read/write opens through the normal NetWare open/share path and
|
||||
* returns a normal NetWare file handle, which this helper closes before exiting.
|
||||
*/
|
||||
|
||||
#include <errno.h>
|
||||
@@ -36,8 +36,8 @@ static void usage(const char *prog)
|
||||
fprintf(stderr,
|
||||
"Usage: %s [--allow-invalid-namespace] [--allow-invalid-path] "
|
||||
"[--expect-completion CODE] [--volume N] [--entry-id ID] "
|
||||
"[--fork N] [--access N] "
|
||||
"[ncpfs options] PATH\n"
|
||||
"[--entry-id-only] [--fork N] [--access N] "
|
||||
"[ncpfs options] [PATH]\n"
|
||||
"\n"
|
||||
"ncpfs options are parsed by ncp_initialize(), for example:\n"
|
||||
" -S SERVER -U USER -P PASSWORD -n\n"
|
||||
@@ -47,8 +47,9 @@ static void usage(const char *prog)
|
||||
" %s --allow-invalid-namespace -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s --allow-invalid-path -S MARS -U SUPERVISOR -P secret SYS:NO_SUCH_FILE\n"
|
||||
" %s --access 0x02 -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/testfile.dat\n"
|
||||
" %s --entry-id-only -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s --expect-completion 0x9c --fork 1 -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini\n",
|
||||
prog, prog, prog, prog, prog, prog);
|
||||
prog, prog, prog, prog, prog, prog, prog);
|
||||
}
|
||||
|
||||
static int parse_u32(const char *text, uint32_t *value)
|
||||
@@ -96,6 +97,40 @@ static void cpu_to_le32(uint32_t v, uint8_t p[4])
|
||||
p[3] = (uint8_t)(v >> 24);
|
||||
}
|
||||
|
||||
|
||||
static NWCCODE afp_get_entry_id_from_path(NWCONN_HANDLE conn, const char *path,
|
||||
uint32_t volume_number,
|
||||
uint32_t *entry_id)
|
||||
{
|
||||
NW_FRAGMENT reply;
|
||||
uint8_t request[1 + 4 + 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] = (uint8_t)volume_number;
|
||||
cpu_to_be32(0, request + 1);
|
||||
request[5] = (uint8_t)path_len;
|
||||
memcpy(request + 6, 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, 0x0c),
|
||||
request, 6 + 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 close_file_handle(NWCONN_HANDLE conn, uint32_t fhandle)
|
||||
{
|
||||
uint8_t rq[7];
|
||||
@@ -114,6 +149,7 @@ int main(int argc, char **argv)
|
||||
int allow_invalid_namespace = 0;
|
||||
int allow_invalid_path = 0;
|
||||
int expected_completion = -1;
|
||||
int entry_id_only = 0;
|
||||
uint32_t volume_number = 0;
|
||||
uint32_t base_entry_id = 0;
|
||||
uint32_t fork_indicator = AFP_DATA_FORK;
|
||||
@@ -164,6 +200,9 @@ int main(int argc, char **argv)
|
||||
ncp_close(conn);
|
||||
return 2;
|
||||
}
|
||||
entry_id_only = 1;
|
||||
} else if (!strcmp(argv[i], "--entry-id-only")) {
|
||||
entry_id_only = 1;
|
||||
} else if (!strcmp(argv[i], "--fork")) {
|
||||
if (++i >= argc || parse_u32(argv[i], &fork_indicator) ||
|
||||
fork_indicator > 255) {
|
||||
@@ -192,14 +231,31 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
if (!path) {
|
||||
fprintf(stderr, "missing PATH\n");
|
||||
if (!path && !base_entry_id) {
|
||||
fprintf(stderr, "missing PATH or --entry-id\n");
|
||||
usage(argv[0]);
|
||||
ncp_close(conn);
|
||||
return 2;
|
||||
}
|
||||
|
||||
path_len = strlen(path);
|
||||
if (entry_id_only && !base_entry_id) {
|
||||
err = afp_get_entry_id_from_path(conn, path, volume_number,
|
||||
&base_entry_id);
|
||||
if (err) {
|
||||
fprintf(stderr,
|
||||
"AFP Get Entry ID From Path Name failed before entry-id-only open: 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 = (path && !entry_id_only) ? strlen(path) : 0;
|
||||
if (path_len > 255) {
|
||||
fprintf(stderr, "PATH is too long for AFP Open File Fork: %zu\n", path_len);
|
||||
ncp_close(conn);
|
||||
@@ -211,7 +267,8 @@ int main(int argc, char **argv)
|
||||
request[5] = (uint8_t)fork_indicator;
|
||||
request[6] = (uint8_t)access_mode;
|
||||
request[7] = (uint8_t)path_len;
|
||||
memcpy(request + 8, path, path_len);
|
||||
if (path_len)
|
||||
memcpy(request + 8, path, path_len);
|
||||
|
||||
memset(reply_buf, 0, sizeof(reply_buf));
|
||||
reply.fragAddr.rw = reply_buf;
|
||||
@@ -225,16 +282,18 @@ int main(int argc, char **argv)
|
||||
|
||||
if (expected_completion >= 0) {
|
||||
if (((unsigned int)err & 0xff) == (unsigned int)expected_completion) {
|
||||
printf("AFP Open File Fork returned expected completion 0x%02x: path=%s fork=%u access=0x%02x\n",
|
||||
expected_completion, path, (unsigned int)fork_indicator,
|
||||
printf("AFP Open File Fork returned expected completion 0x%02x: path=%s entry_id=0x%08x fork=%u access=0x%02x\n",
|
||||
expected_completion, path ? path : "(entry-id-only)",
|
||||
(unsigned int)base_entry_id, (unsigned int)fork_indicator,
|
||||
(unsigned int)access_mode);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
}
|
||||
if (!err) {
|
||||
fprintf(stderr,
|
||||
"AFP Open File Fork unexpectedly succeeded: expected=0x%02x path=%s fork=%u access=0x%02x\n",
|
||||
expected_completion, path, (unsigned int)fork_indicator,
|
||||
"AFP Open File Fork unexpectedly succeeded: expected=0x%02x path=%s entry_id=0x%08x fork=%u access=0x%02x\n",
|
||||
expected_completion, path ? path : "(entry-id-only)",
|
||||
(unsigned int)base_entry_id, (unsigned int)fork_indicator,
|
||||
(unsigned int)access_mode);
|
||||
if (reply.fragSize >= 6)
|
||||
close_file_handle(conn, le32_to_cpu(reply_buf + 2));
|
||||
@@ -242,8 +301,9 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
fprintf(stderr,
|
||||
"AFP Open File Fork returned completion 0x%02x, expected 0x%02x: path=%s fork=%u access=0x%02x\n",
|
||||
(unsigned int)err & 0xff, expected_completion, path,
|
||||
"AFP Open File Fork returned completion 0x%02x, expected 0x%02x: path=%s entry_id=0x%08x fork=%u access=0x%02x\n",
|
||||
(unsigned int)err & 0xff, expected_completion,
|
||||
path ? path : "(entry-id-only)", (unsigned int)base_entry_id,
|
||||
(unsigned int)fork_indicator, (unsigned int)access_mode);
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
@@ -251,22 +311,24 @@ int main(int argc, char **argv)
|
||||
|
||||
if (((unsigned int)err & 0xff) == NWE_INVALID_NAMESPACE &&
|
||||
allow_invalid_namespace) {
|
||||
printf("AFP Open File Fork returned invalid namespace as expected: path=%s\n",
|
||||
path);
|
||||
printf("AFP Open File Fork returned invalid namespace as expected: path=%s entry_id=0x%08x\n",
|
||||
path ? path : "(entry-id-only)", (unsigned int)base_entry_id);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (((unsigned int)err & 0xff) == NWE_INVALID_PATH && allow_invalid_path) {
|
||||
printf("AFP Open File Fork returned invalid path as expected: path=%s\n", path);
|
||||
printf("AFP Open File Fork returned invalid path as expected: path=%s entry_id=0x%08x\n",
|
||||
path ? path : "(entry-id-only)", (unsigned int)base_entry_id);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
fprintf(stderr,
|
||||
"AFP Open File Fork failed: completion=0x%02x (%u) path=%s\n",
|
||||
(unsigned int)err & 0xff, (unsigned int)err, path);
|
||||
"AFP Open File Fork failed: completion=0x%02x (%u) path=%s entry_id=0x%08x\n",
|
||||
(unsigned int)err & 0xff, (unsigned int)err,
|
||||
path ? path : "(entry-id-only)", (unsigned int)base_entry_id);
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
}
|
||||
@@ -279,9 +341,11 @@ int main(int argc, char **argv)
|
||||
|
||||
fhandle = le32_to_cpu(reply_buf + 2);
|
||||
fork_len = be32_to_cpu(reply_buf + 6);
|
||||
printf("AFP Open File Fork path=%s handle=%u fork=%u access=0x%02x fork_len=%u\n",
|
||||
path, fhandle, (unsigned int)fork_indicator,
|
||||
(unsigned int)access_mode, fork_len);
|
||||
printf("AFP Open File Fork path=%s entry_id=0x%08x handle=%u fork=%u access=0x%02x fork_len=%u%s\n",
|
||||
path ? path : "(entry-id-only)", (unsigned int)base_entry_id,
|
||||
fhandle, (unsigned int)fork_indicator,
|
||||
(unsigned int)access_mode, fork_len,
|
||||
entry_id_only ? " entry-id-only" : "");
|
||||
|
||||
close_file_handle(conn, fhandle);
|
||||
ncp_close(conn);
|
||||
|
||||
@@ -576,6 +576,11 @@ run_cmd \
|
||||
"AFP Open File Fork" \
|
||||
"./afp_open_file_fork_smoke $COMMON_PRINT '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_open_file_fork_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
||||
run_cmd \
|
||||
"AFP Open File Fork by Entry ID" \
|
||||
"./afp_open_file_fork_smoke --entry-id-only $COMMON_PRINT '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_open_file_fork_smoke" --entry-id-only \
|
||||
-S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$NETWARE_PATH"
|
||||
|
||||
run_optional_cmd \
|
||||
"Prepare AFP Open File Fork write cleanup" \
|
||||
@@ -590,6 +595,11 @@ run_cmd \
|
||||
"./afp_open_file_fork_smoke --access 0x02 $COMMON_PRINT '$CREATE_FILE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_open_file_fork_smoke" --access 0x02 \
|
||||
-S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$CREATE_FILE_PATH"
|
||||
run_cmd \
|
||||
"AFP Open File Fork write access by Entry ID" \
|
||||
"./afp_open_file_fork_smoke --entry-id-only --access 0x02 $COMMON_PRINT '$CREATE_FILE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_open_file_fork_smoke" --entry-id-only --access 0x02 \
|
||||
-S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" "$CREATE_FILE_PATH"
|
||||
run_cmd \
|
||||
"AFP Open File Fork write cleanup" \
|
||||
"./afp_delete_smoke $COMMON_PRINT '$CREATE_FILE_PATH'" \
|
||||
|
||||
Reference in New Issue
Block a user