tests: add WebSDK AFP set file information smoke

This commit is contained in:
Mario Fetka
2026-05-30 20:34:27 +00:00
parent 211d04ea62
commit dce62be6d5
2 changed files with 121 additions and 59 deletions

View File

@@ -41,7 +41,7 @@
static void usage(const char *prog)
{
fprintf(stderr,
"Usage: %s [--afp09|--afp20] [--expect-completion CODE] [--allow-invalid-namespace] [--allow-invalid-path] "
"Usage: %s [--afp09|--afp20] [--websdk-layout] [--expect-completion CODE] [--allow-invalid-namespace] [--allow-invalid-path] "
"[--volume N] [--entry-id ID] [--type FOUR] [--creator FOUR] "
"[--hidden|--clear-hidden|--invisible|--clear-invisible|--system|--clear-system|--archive|--clear-archive] "
"[--access-time-epoch SECONDS] [--create-time-epoch SECONDS] [--mtime-epoch SECONDS] [--backup-time-epoch SECONDS] [--finder-info-only|--attributes-only|--access-time-only|--create-time-only|--timestamp-only|--backup-time-only] "
@@ -168,6 +168,7 @@ int main(int argc, char **argv)
int allow_invalid_namespace = 0;
int allow_invalid_path = 0;
int expect_completion = -1;
int websdk_layout = 0;
uint32_t volume_number = 0;
uint32_t entry_id = 0;
uint8_t finder_info[32];
@@ -217,6 +218,8 @@ int main(int argc, char **argv)
set_subfunction = AFP_SET_FILE_INFORMATION;
} else if (!strcmp(argv[i], "--afp20")) {
set_subfunction = AFP20_SET_FILE_INFORMATION;
} else if (!strcmp(argv[i], "--websdk-layout")) {
websdk_layout = 1;
} else if (!strcmp(argv[i], "--expect-completion")) {
uint32_t completion;
if (++i >= argc || parse_u32(argv[i], &completion) || completion > 255) {
@@ -367,67 +370,102 @@ int main(int argc, char **argv)
request[0] = (uint8_t)volume_number;
cpu_to_be32(entry_id, request + 1);
cpu_to_be16(request_mask, request + 5);
request[7] = (uint8_t)path_len;
memcpy(request + 8, path, path_len);
/*
* The server-side AFP request buffer includes the NCP AFP subfunction byte
* at offset 0. This smoke helper passes only the subfunction payload to
* NWRequestSimple(), so every server offset after the leading function byte
* maps to request_offset - 1 here. Align once in AFP/server coordinates,
* then subtract one; do not align the payload offset again or FinderInfo-only
* requests with an even path length get a leading zero byte persisted.
*/
afp_data_off = 1 + 8 + path_len;
if (afp_data_off & 1)
afp_data_off++;
data_off = afp_data_off - 1;
if (request_mask & AFP_ATTRIBUTES_MASK) {
cpu_to_be16(attr_request, request + data_off);
data_off += 2;
if ((request_mask & AFP_ACCESS_DATE_MASK) && !have_access_time) {
fprintf(stderr, "--access-time-only requires --access-time-epoch\n");
ncp_close(conn);
return 2;
}
if (request_mask & AFP_ACCESS_DATE_MASK) {
if (!have_access_time) {
fprintf(stderr, "--access-time-only requires --access-time-epoch\n");
ncp_close(conn);
return 2;
if ((request_mask & AFP_CREATE_DATE_MASK) && !have_create_time) {
fprintf(stderr, "--create-time-only requires --create-time-epoch\n");
ncp_close(conn);
return 2;
}
if ((request_mask & AFP_MODIFY_DATE_MASK) && !have_modify_time) {
fprintf(stderr, "--timestamp-only requires --mtime-epoch\n");
ncp_close(conn);
return 2;
}
if ((request_mask & AFP_BACKUP_DATE_MASK) && !have_backup_time) {
fprintf(stderr, "--backup-time-only requires --backup-time-epoch\n");
ncp_close(conn);
return 2;
}
if (websdk_layout) {
size_t path_len_off;
size_t path_off;
/*
* WebSDK/nwafp.h fixed SetInfo layout, in the payload passed to
* NWRequestSimple() without the leading AFP subfunction byte:
* 0x09: path_len @ 53, path @ 54
* 0x10: ProDOSInfo @ 53..58, path_len @ 59, path @ 60
*/
if (set_subfunction == AFP20_SET_FILE_INFORMATION) {
path_len_off = 59;
path_off = 60;
} else {
path_len_off = 53;
path_off = 54;
}
memcpy(request + data_off, access_time, sizeof(access_time));
data_off += sizeof(access_time);
}
if (request_mask & AFP_CREATE_DATE_MASK) {
if (!have_create_time) {
fprintf(stderr, "--create-time-only requires --create-time-epoch\n");
ncp_close(conn);
return 2;
cpu_to_be16(attr_request, request + 7);
if (have_create_time)
memcpy(request + 9, create_time, sizeof(create_time));
if (have_access_time)
memcpy(request + 11, access_time, sizeof(access_time));
if (have_modify_time)
memcpy(request + 13, modify_time, sizeof(modify_time));
if (have_backup_time)
memcpy(request + 17, backup_time, sizeof(backup_time));
memcpy(request + 21, finder_info, sizeof(finder_info));
request[path_len_off] = (uint8_t)path_len;
memcpy(request + path_off, path, path_len);
data_off = path_off + path_len;
} else {
request[7] = (uint8_t)path_len;
memcpy(request + 8, path, path_len);
/*
* The server-side AFP request buffer includes the NCP AFP subfunction byte
* at offset 0. This smoke helper passes only the subfunction payload to
* NWRequestSimple(), so every server offset after the leading function byte
* maps to request_offset - 1 here. Align once in AFP/server coordinates,
* then subtract one; do not align the payload offset again or FinderInfo-only
* requests with an even path length get a leading zero byte persisted.
*/
afp_data_off = 1 + 8 + path_len;
if (afp_data_off & 1)
afp_data_off++;
data_off = afp_data_off - 1;
if (request_mask & AFP_ATTRIBUTES_MASK) {
cpu_to_be16(attr_request, request + data_off);
data_off += 2;
}
memcpy(request + data_off, create_time, sizeof(create_time));
data_off += sizeof(create_time);
}
if (request_mask & AFP_MODIFY_DATE_MASK) {
if (!have_modify_time) {
fprintf(stderr, "--timestamp-only requires --mtime-epoch\n");
ncp_close(conn);
return 2;
if (request_mask & AFP_ACCESS_DATE_MASK) {
memcpy(request + data_off, access_time, sizeof(access_time));
data_off += sizeof(access_time);
}
memcpy(request + data_off, modify_time, sizeof(modify_time));
data_off += sizeof(modify_time);
}
if (request_mask & AFP_BACKUP_DATE_MASK) {
if (!have_backup_time) {
fprintf(stderr, "--backup-time-only requires --backup-time-epoch\n");
ncp_close(conn);
return 2;
if (request_mask & AFP_CREATE_DATE_MASK) {
memcpy(request + data_off, create_time, sizeof(create_time));
data_off += sizeof(create_time);
}
if (request_mask & AFP_MODIFY_DATE_MASK) {
memcpy(request + data_off, modify_time, sizeof(modify_time));
data_off += sizeof(modify_time);
}
if (request_mask & AFP_BACKUP_DATE_MASK) {
memcpy(request + data_off, backup_time, sizeof(backup_time));
data_off += sizeof(backup_time);
}
if ((request_mask & AFP_FINDER_INFO_MASK) &&
(request_mask & (AFP_ATTRIBUTES_MASK | AFP_ACCESS_DATE_MASK | AFP_CREATE_DATE_MASK | AFP_MODIFY_DATE_MASK | AFP_BACKUP_DATE_MASK)) &&
((data_off + 1) & 1))
data_off++;
if (request_mask & AFP_FINDER_INFO_MASK) {
memcpy(request + data_off, finder_info, sizeof(finder_info));
data_off += sizeof(finder_info);
}
memcpy(request + data_off, backup_time, sizeof(backup_time));
data_off += sizeof(backup_time);
}
if ((request_mask & AFP_FINDER_INFO_MASK) &&
(request_mask & (AFP_ATTRIBUTES_MASK | AFP_ACCESS_DATE_MASK | AFP_CREATE_DATE_MASK | AFP_MODIFY_DATE_MASK | AFP_BACKUP_DATE_MASK)) &&
((data_off + 1) & 1))
data_off++;
if (request_mask & AFP_FINDER_INFO_MASK) {
memcpy(request + data_off, finder_info, sizeof(finder_info));
data_off += sizeof(finder_info);
}
err = NWRequestSimple(conn,
@@ -534,8 +572,8 @@ int main(int argc, char **argv)
return 1;
}
printf("AFP Set File Info subfunction=0x%02x path=%s bitmap=0x%04x attrs=0x%04x create=0x%04x access=0x%04x modify=0x%04x%04x backup=0x%04x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
set_subfunction, path, request_mask, be16_to_cpu(verify_buf + 8),
printf("AFP Set File Info subfunction=0x%02x layout=%s path=%s bitmap=0x%04x attrs=0x%04x create=0x%04x access=0x%04x modify=0x%04x%04x backup=0x%04x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
set_subfunction, websdk_layout ? "websdk" : "compact", path, request_mask, be16_to_cpu(verify_buf + 8),
be16_to_cpu(verify_buf + 20), be16_to_cpu(verify_buf + 22),
be16_to_cpu(verify_buf + 24), be16_to_cpu(verify_buf + 26),
be16_to_cpu(verify_buf + 28), be16_to_cpu(verify_buf + 30),

View File

@@ -601,6 +601,30 @@ run_cmd \
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
--afp09 --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
run_cmd \
"AFP Set File Information FinderInfo WebSDK layout" \
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
--websdk-layout --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
run_cmd \
"AFP Set File Information FinderInfo WebSDK legacy" \
"./afp_set_file_info_smoke $COMMON_PRINT --afp09 --websdk-layout --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
--afp09 --websdk-layout --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
run_cmd \
"AFP Set File Information Hidden WebSDK layout" \
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --attributes-only --hidden '$NETWARE_PATH'" \
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
--websdk-layout --attributes-only --hidden "$NETWARE_PATH"
run_cmd \
"AFP Set File Information Clear Hidden WebSDK layout" \
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --attributes-only --clear-hidden '$NETWARE_PATH'" \
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
--websdk-layout --attributes-only --clear-hidden "$NETWARE_PATH"
run_cmd \
"AFP Set File Information Hidden" \
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --hidden '$NETWARE_PATH'" \