diff --git a/tests/linux/afp_set_file_info_smoke.c b/tests/linux/afp_set_file_info_smoke.c index 488d4ea..ebcb8b3 100644 --- a/tests/linux/afp_set_file_info_smoke.c +++ b/tests/linux/afp_set_file_info_smoke.c @@ -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), diff --git a/tests/linux/afp_smoke_suite.sh b/tests/linux/afp_smoke_suite.sh index ee70007..a7efee2 100755 --- a/tests/linux/afp_smoke_suite.sh +++ b/tests/linux/afp_smoke_suite.sh @@ -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'" \