Files
mars-nwe/src/nwatalk.c
Mario Fetka eb2983bc1a
All checks were successful
Source release / source-package (push) Successful in 48s
nwconn: implement AFP entry id path lookup
Wire NCP 0x23/0x0c AFP Get Entry ID From Path Name to a real path lookup when the optional Netatalk/libatalk backend is available.

The WebSDK documents NCP 0x2222/35/12 as converting a NetWare directory handle plus short-name path string into a unique 32-bit Macintosh file or directory Entry ID. The request carries the AFP subfunction, NetWare directory handle, path length, and path string; the reply carries the 4-byte AFP Entry ID. The SDK headers expose the same operation as AFPGetEntryIDFromPathName() and NWAFPGetEntryIDFromPathName(), and NWAFPSupported() uses this path-name probe to test AFP support.

Resolve the NetWare directory handle and path through the existing mars_nwe path machinery, require the optional libatalk backend before returning AFP success, and then ask libatalk for an AppleDouble/CNID-style id when available. If libatalk is present but the file has no stored id yet, return a deterministic stat-derived local entry id as a temporary fallback so the path-name probe can succeed without inventing NetWare directory base numbers.

Keep all other AFP subfunctions returning invalid namespace for now. They still need Finder Info, resource fork, AFP file information, fork open, and persistent CNID/directory-id support before they can safely report success.

Add the SDK request/reply semantics to the inline endpoint comments and keep the remaining AFP work tracked in TODO.md.

This implements only the AFP path-to-entry-id probe; it does not add general AFP file or resource-fork semantics yet.
2026-05-30 01:45:58 +02:00

133 lines
2.7 KiB
C

/* Optional Netatalk/libatalk AFP metadata backend helpers. */
#include "net.h"
#include "config.h"
#include "nwatalk.h"
#include "tools.h"
#include <string.h>
#if NETATALK_SUPPORT
#include <errno.h>
#include <sys/stat.h>
#include <atalk/adouble.h>
#endif
int nwatalk_backend_available(void)
{
#if NETATALK_SUPPORT
return(1);
#else
return(0);
#endif
}
#if NETATALK_SUPPORT
static int nwatalk_open_adouble(const char *path, struct adouble *ad)
{
int result;
if (!path || !*path) return(-0x9c); /* invalid path */
ad_init_old(ad, AD_VERSION, 0);
result = ad_open(ad, path,
ADFLAGS_HF | ADFLAGS_RF | ADFLAGS_RDONLY |
ADFLAGS_NOHF | ADFLAGS_NORF);
if (result < 0) {
return(-0x9c);
}
return(0);
}
#endif
int nwatalk_get_finder_info(const char *path, uint8 *finder_info,
int finder_info_len)
{
#if NETATALK_SUPPORT
struct adouble ad;
void *entry;
int result;
if (!finder_info || finder_info_len < NWATALK_FINDER_INFO_LEN) {
return(-0x9c);
}
memset(finder_info, 0, finder_info_len);
result = nwatalk_open_adouble(path, &ad);
if (result < 0) return(result);
entry = ad_entry(&ad, ADEID_FINDERI);
if (entry && ad_getentrylen(&ad, ADEID_FINDERI) >= NWATALK_FINDER_INFO_LEN) {
memcpy(finder_info, entry, NWATALK_FINDER_INFO_LEN);
}
ad_close(&ad, 0);
return(0);
#else
(void)path;
(void)finder_info;
(void)finder_info_len;
return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}
int nwatalk_get_resource_fork_size(const char *path, uint32 *resource_size)
{
#if NETATALK_SUPPORT
struct adouble ad;
off_t size;
int result;
if (!resource_size) return(-0x9c);
*resource_size = 0;
result = nwatalk_open_adouble(path, &ad);
if (result < 0) return(result);
size = ad_size(&ad, ADEID_RFORK);
if (size > 0) {
if (size > 0xffffffffUL) size = 0xffffffffUL;
*resource_size = (uint32)size;
}
ad_close(&ad, 0);
return(0);
#else
(void)path;
(void)resource_size;
return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}
int nwatalk_get_entry_id(const char *path, uint32 *entry_id)
{
#if NETATALK_SUPPORT
struct adouble ad;
struct stat stbuff;
uint32_t id;
int result;
if (!entry_id) return(-0x9c);
*entry_id = 0;
if (!path || !*path) return(-0x9c);
if (stat(path, &stbuff)) return(-0x9c);
result = nwatalk_open_adouble(path, &ad);
if (result < 0) return(result);
id = ad_getid(&ad, stbuff.st_dev, stbuff.st_ino, 0, NULL);
if (id) *entry_id = (uint32)id;
ad_close(&ad, 0);
return(id ? 0 : -0x9c);
#else
(void)path;
(void)entry_id;
return(-0xbf); /* invalid namespace / backend unavailable */
#endif
}