nwconn: implement AFP entry id from NetWare handle
All checks were successful
Source release / source-package (push) Successful in 49s
All checks were successful
Source release / source-package (push) Successful in 49s
Wire NCP 0x23/0x06 AFP Get Entry ID From NetWare Handle to the existing AFP entry-id backend. The WebSDK documents NCP 0x2222/35/06 as taking a 6-byte NetWare file handle and returning the volume number, a 32-bit AFP Entry ID, and a fork indicator. The SDK headers expose the same operation as AFPGetEntryIDFromNetWareHandle() and NWAFPGetEntryIDFromNetWareHandle(). Use the connection-local mars_nwe file handle table to map the supplied NetWare file handle back to its Unix path, require the optional libatalk backend as for the other AFP calls, and then return a libatalk Entry ID when available or the existing stat-derived fallback ID otherwise. Report the data fork for now because mars_nwe does not yet expose AFP resource-fork open semantics. Extend the Linux AFP entry-id smoke test with --from-handle. The test opens the requested file through libncp in the same connection, sends the returned 6-byte NetWare file handle to the AFP call, and closes the file afterwards. This implements the read-only data-fork handle-to-entry-id path; persistent CNID mapping and resource-fork handle semantics remain future work.
This commit is contained in:
@@ -23,8 +23,9 @@
|
||||
#define NCPC_SFN(FN, SFN) ((FN) | ((SFN) << 8) | NCPC_SUBFUNCTION)
|
||||
#endif
|
||||
|
||||
#define AFP_GET_ENTRY_ID_FROM_NAME 0x04
|
||||
#define AFP_GET_ENTRY_ID_FROM_PATH_NAME 0x0c
|
||||
#define AFP_GET_ENTRY_ID_FROM_NAME 0x04
|
||||
#define AFP_GET_ENTRY_ID_FROM_NETWARE_HANDLE 0x06
|
||||
#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
|
||||
@@ -33,7 +34,7 @@ static void usage(const char *prog)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [--allow-invalid-namespace] [--allow-invalid-path] "
|
||||
"[--from-name] [--volume N] [--entry-id ID] "
|
||||
"[--from-name] [--from-handle] [--volume N] [--entry-id ID] "
|
||||
"[--dir-handle N] [--alloc-handle] [--raw-path] [ncpfs options] PATH\n"
|
||||
"\n"
|
||||
"ncpfs options are parsed by ncp_initialize(), for example:\n"
|
||||
@@ -42,11 +43,12 @@ static void usage(const char *prog)
|
||||
"Examples:\n"
|
||||
" %s -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
|
||||
" %s --from-name -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
|
||||
" %s --from-handle -S MARS -U SUPERVISOR -P secret SYS:PUBLIC/pmdflts.ini\n"
|
||||
" %s --dir-handle 2 -S MARS -U SUPERVISOR -P secret PUBLIC\n"
|
||||
" %s --alloc-handle -S MARS -U SUPERVISOR -P secret SYS:PUBLIC\n"
|
||||
" %s --allow-invalid-namespace -S MARS SYS:PUBLIC\n"
|
||||
" %s --allow-invalid-path -S MARS SYS:NO_SUCH_PATH\n",
|
||||
prog, prog, prog, prog, prog, prog, prog);
|
||||
prog, prog, prog, prog, prog, prog, prog, prog);
|
||||
}
|
||||
|
||||
static int parse_u8(const char *text, unsigned int *value)
|
||||
@@ -194,13 +196,16 @@ int main(int argc, char **argv)
|
||||
int raw_path = 1;
|
||||
int alloc_handle = 0;
|
||||
int from_name = 0;
|
||||
int from_handle = 0;
|
||||
uint32_t volume_number = 0;
|
||||
uint32_t base_entry_id = 0;
|
||||
struct ncp_file_info opened_file;
|
||||
int opened_file_valid = 0;
|
||||
int i;
|
||||
size_t path_len;
|
||||
char volume[32];
|
||||
uint8_t request[1 + 4 + 1 + 255];
|
||||
uint8_t reply_buf[4];
|
||||
uint8_t reply_buf[6];
|
||||
NWCCODE err;
|
||||
|
||||
if (NWCallsInit(NULL, NULL)) {
|
||||
@@ -230,6 +235,12 @@ int main(int argc, char **argv)
|
||||
allow_invalid_path = 1;
|
||||
} else if (!strcmp(argv[i], "--from-name")) {
|
||||
from_name = 1;
|
||||
from_handle = 0;
|
||||
raw_path = 1;
|
||||
alloc_handle = 0;
|
||||
} else if (!strcmp(argv[i], "--from-handle")) {
|
||||
from_handle = 1;
|
||||
from_name = 0;
|
||||
raw_path = 1;
|
||||
alloc_handle = 0;
|
||||
} else if (!strcmp(argv[i], "--volume")) {
|
||||
@@ -300,16 +311,34 @@ int main(int argc, char **argv)
|
||||
allocated_dir_handle = dir_handle;
|
||||
}
|
||||
|
||||
if (from_handle) {
|
||||
memset(&opened_file, 0, sizeof(opened_file));
|
||||
err = ncp_open_file(conn, 0, request_path, 0, AR_READ_ONLY, &opened_file);
|
||||
if (err) {
|
||||
fprintf(stderr,
|
||||
"Open file failed before AFP request: completion=0x%02x (%u) path=%s request_path=%s\n",
|
||||
(unsigned int)err & 0xff, (unsigned int)err, path, request_path);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
}
|
||||
opened_file_valid = 1;
|
||||
}
|
||||
|
||||
path_len = strlen(request_path);
|
||||
if (path_len > 255) {
|
||||
fprintf(stderr, "PATH is too long for AFP Get Entry ID From Path Name: %zu\n",
|
||||
path_len);
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (from_name) {
|
||||
if (from_handle) {
|
||||
memcpy(request, opened_file.file_id, 6);
|
||||
} else if (from_name) {
|
||||
request[0] = (uint8_t)volume_number;
|
||||
cpu_to_be32(base_entry_id, request + 1);
|
||||
request[5] = (uint8_t)path_len;
|
||||
@@ -325,17 +354,21 @@ int main(int argc, char **argv)
|
||||
reply.fragSize = sizeof(reply_buf);
|
||||
|
||||
err = NWRequestSimple(conn,
|
||||
NCPC_SFN(0x23, from_name
|
||||
? AFP_GET_ENTRY_ID_FROM_NAME
|
||||
: AFP_GET_ENTRY_ID_FROM_PATH_NAME),
|
||||
NCPC_SFN(0x23, from_handle
|
||||
? AFP_GET_ENTRY_ID_FROM_NETWARE_HANDLE
|
||||
: (from_name
|
||||
? AFP_GET_ENTRY_ID_FROM_NAME
|
||||
: AFP_GET_ENTRY_ID_FROM_PATH_NAME)),
|
||||
request,
|
||||
(from_name ? 6 : 2) + path_len,
|
||||
from_handle ? 6 : ((from_name ? 6 : 2) + path_len),
|
||||
&reply);
|
||||
|
||||
if (((unsigned int)err & 0xff) == NWE_INVALID_NAMESPACE && allow_invalid_namespace) {
|
||||
printf("AFP Get Entry ID returned invalid namespace "
|
||||
"as expected: path=%s request_path=%s dir_handle=%u\n",
|
||||
path, request_path, dir_handle);
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
@@ -345,6 +378,8 @@ int main(int argc, char **argv)
|
||||
printf("AFP Get Entry ID returned invalid path "
|
||||
"as expected: path=%s request_path=%s dir_handle=%u\n",
|
||||
path, request_path, dir_handle);
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
@@ -355,23 +390,37 @@ int main(int argc, char **argv)
|
||||
"AFP Get Entry ID From Path Name failed: completion=0x%02x (%u) path=%s request_path=%s dir_handle=%u\n",
|
||||
(unsigned int)err & 0xff, (unsigned int)err, path,
|
||||
request_path, dir_handle);
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (reply.fragSize < 4) {
|
||||
if (reply.fragSize < (from_handle ? 6 : 4)) {
|
||||
fprintf(stderr, "short AFP reply: %zu bytes\n", reply.fragSize);
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("AFP Entry ID path=%s request_path=%s dir_handle=%u entry_id=0x%08x (%u)\n",
|
||||
path, request_path, dir_handle,
|
||||
(unsigned int)be32_to_cpu(reply_buf),
|
||||
(unsigned int)be32_to_cpu(reply_buf));
|
||||
if (from_handle) {
|
||||
printf("AFP Entry ID From NetWare Handle path=%s volume=%u entry_id=0x%08x (%u) fork=%u\n",
|
||||
path, (unsigned int)reply_buf[0],
|
||||
(unsigned int)be32_to_cpu(reply_buf + 1),
|
||||
(unsigned int)be32_to_cpu(reply_buf + 1),
|
||||
(unsigned int)reply_buf[5]);
|
||||
} else {
|
||||
printf("AFP Entry ID path=%s request_path=%s dir_handle=%u entry_id=0x%08x (%u)\n",
|
||||
path, request_path, dir_handle,
|
||||
(unsigned int)be32_to_cpu(reply_buf),
|
||||
(unsigned int)be32_to_cpu(reply_buf));
|
||||
}
|
||||
|
||||
if (opened_file_valid)
|
||||
(void)ncp_close_file(conn, opened_file.file_id);
|
||||
deallocate_dir_handle(conn, allocated_dir_handle);
|
||||
ncp_close(conn);
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user