Dev Docs Libatalk API

libatalk API Reference

Audited against Netatalk d63155e13 on 2026-10-10. This describes the current source checkout; older releases may differ.

Build and ownership

libatalk/meson.build aggregates internal static libraries into libatalk, currently with library version 23.0.0 and soversion 23. Linux builds expose the corresponding libatalk.so.23; other platforms use their own naming conventions. Consumers include daemons, UAM-related code, and utilities.

Public declarations live in include/atalk. AFP-only handlers and cache APIs in etc/afpd are not exported libatalk subsystems merely because they use shared structures.

Module Source API header
AppleDouble libatalk/adouble include/atalk/adouble.h
CNID libatalk/cnid include/atalk/cnid.h
DSI libatalk/dsi include/atalk/dsi.h
Unicode / charset conversion libatalk/unicode include/atalk/unicode.h
VFS and EAs libatalk/vfs include/atalk/vfs.h, include/atalk/ea.h
ACL / UUID / LDAP libatalk/acl include/atalk/acl.h, include/atalk/uuid.h
Configuration and utilities libatalk/util include/atalk/netatalk_conf.h, include/atalk/util.h
Compatibility libatalk/compat include/atalk/compat.h
ASP / ATP / NBP / DDP libatalk/asp, libatalk/atp, libatalk/nbp, libatalk/netddp asp.h, atp.h, nbp.h, netddp.h (AppleTalk builds)
Spotlight allocation libatalk/dalloc include/atalk/dalloc.h (Spotlight builds)

AppleDouble

struct adouble owns parsed metadata, fork descriptors, locks, and reference counts. Storage modes are AD_VERSION2 (legacy .AppleDouble files) and AD_VERSION_EA (metadata EAs with platform-dependent resource-fork storage). Apple ._ sidecars are not the same layout as Netatalk’s legacy .AppleDouble files.

API Implementation Contract
ad_init() libatalk/adouble/ad_open.c Initialize from volume storage settings
ad_open() / ad_close() libatalk/adouble/ad_open.c Open/close selected data, metadata, and resource-fork components
ad_metadata() libatalk/adouble/ad_open.c Read metadata; caller must respect descriptor lifecycle
ad_entry() libatalk/adouble/ad_open.c Validated pointer into parsed metadata, or NULL
ad_flush() libatalk/adouble/ad_flush.c Persist modified metadata
ad_read() / ad_write() libatalk/adouble/ad_read.c, libatalk/adouble/ad_write.c I/O on the selected fork at an offset
ad_lock() / ad_tmplock() / ad_unlock() libatalk/adouble/ad_lock.c Tracked and temporary byte-range/share-mode locks
sys_sendfile() / ad_recvfile() libatalk/adouble/ad_sendfile.c, libatalk/adouble/ad_recvfile.c Optional platform transfer paths

ad_ref()/ad_unref() track shared AppleDouble object ownership. They are distinct from fork-open reference counts and must not substitute for ad_close().

Metadata entry IDs such as ADEID_FINDERI, ADEID_FILEDATESI, and ADEID_AFPFILEI describe entry types. Header bounds and actual parsed data length constrain access; an entry ID alone does not prove its bytes are present.

CNID

cnid_init() registers mandatory SQLite and optional MySQL modules. The dispatch layer is libatalk/cnid/cnid.c. There is no BDB backend or signal-blocking CNID_FLAG_BLOCK dispatch behavior.

Core APIs are cnid_open(), cnid_close(), cnid_add(), cnid_get(), cnid_lookup(), cnid_resolve(), cnid_update(), cnid_delete(), cnid_getstamp(), and cnid_wipe(). CNIDs are network-order values in the AFP-facing interface.

The current search signatures are:

int cnid_find(struct _cnid_db *cdb, const char *name, size_t namelen,
              void *buffer, size_t buflen, bool *more_available);
int cnid_find_scoped(struct _cnid_db *cdb, const char *name,
                     size_t namelen, cnid_t scope_did,
                     void *buffer, size_t buflen, bool *more_available);

The backend callback includes scope_did. Results require a minimum 100-slot buffer and report whether more matches exist. CNID_ERRNO() exposes unsigned backend error codes; CNID_ERRNO_IS_BACKEND_FAILURE() separates transient/unusable database answers from not-found results. See CNID Database.

DSI

DSI contains the header, buffers, sockets, timer, transport state, and optional recvfile pipe. The on-wire header is 16 bytes; code packs and decodes fields explicitly rather than sending a host-layout struct.

API Source
dsi_init() / dsi_free() libatalk/dsi/dsi_init.c
dsi_getsession() libatalk/dsi/dsi_getsess.c
dsi_opensession() libatalk/dsi/dsi_opensess.c
dsi_stream_read() / dsi_stream_write() / dsi_stream_send() / dsi_stream_receive() libatalk/dsi/dsi_stream.c
dsi_readinit() / dsi_read() / dsi_readdone() libatalk/dsi/dsi_read.c
dsi_writeinit() / dsi_write() / dsi_writeflush() libatalk/dsi/dsi_write.c
dsi_cmdreply() libatalk/dsi/dsi_cmdreply.c
dsi_attention() libatalk/dsi/dsi_attn.c
dsi_tickle() libatalk/dsi/dsi_tickle.c
dsi_close() libatalk/dsi/dsi_close.c

DSI receive readahead is incoming network buffering. The server quantum limits write data, and streaming reads are a separate path. See Network Protocols.

Configuration

include/atalk/netatalk_conf.h declares afp_config_parse(), afp_config_free(), load_afp_conf_vols(), volume lookup/free helpers, charset setup, and extension-map lookup.

load_volumes() is an obsolete name. netatalk_readbuf_clamp() bounds the configured DSI buffer product. Volume option lookup and substitutions are implemented inside libatalk/util/netatalk_conf.c; most typed lookup helpers are internal, not general public APIs. See Configuration.

IPC and children

include/atalk/server_ipc.h defines the control commands, 14-byte header, and 8-byte cache-hint payload. The current sender signature takes an AFPObj, not a raw fd:

int ipc_child_write(AFPObj *obj, uint16_t command, size_t len, void *token);

ipc_server_read() dispatches parent-side messages; ipc_child_state() reports session state; ipc_send_cache_hint() sends invalidation hints. hint_buf_count() and hint_flush_pending() are parent-only batching APIs in libatalk/util/server_ipc.c.

include/atalk/server_child.h declares child-table allocation, add/remove/resolve/free, signal forwarding, authenticated-login reporting, and session transfer. afp_child_t includes the IPC/hint fds, client identity, UID/state/volumes, and opaque reconnect token. The table has 32 PID hash buckets. See libatalk/util/server_child.c.

Session signal wakeups use atalk_sigpipe_init(), atalk_sigpipe_notify(), atalk_sigpipe_readfd(), and atalk_sigpipe_drain() from libatalk/util/sigpipe.c; declarations are in include/atalk/util.h. This self-pipe is separate from the parent’s cache-hint pipe.

Unicode, VFS, and identity mapping

convert_charset(), convert_string(), and convert_string_allocate() are declared in include/atalk/unicode.h. Higher-level conversion is in libatalk/unicode/charcnv.c; iconv handles and charset registration are in libatalk/unicode/iconv.c. Conversion flags affect normalization, case handling, and invalid sequences.

initvol_vfs() selects built-in operations for a volume. include/atalk/vfs.h defines the operations table and a maximum of 3 modules. EA implementations are libatalk/vfs/ea_sys.c and libatalk/vfs/ea_ad.c; platform xattr wrappers are in libatalk/vfs/extattr.c. This is static dispatch, not a dynamic plugin-loader ABI.

UUID/name mapping is in libatalk/acl/uuid.c, local identity support in libatalk/acl/unix.c, and optional LDAP identity lookup in libatalk/acl/ldap.c. LDAP UUID lookup is not a password-authentication UAM.

SRP parameters and verifier-format helpers are shared through include/atalk/srp.h. Constant-time comparison is declared in include/atalk/constant_time.h and implemented in libatalk/util/constant_time.c.

Logging, fault handling, and errors

LOG() and log levels/types are defined in include/atalk/logger.h. libatalk/util/logger.c handles configuration, log entries, and reopen behavior. Debug calls depend on build settings as well as configured levels.

libatalk/util/fault.c installs fault-reporting support, including thread-specific setup. include/atalk/errchk.h provides cleanup macros (EC_INIT, EC_NULL, EC_NEG1, EC_ZERO, EC_CLEANUP, and EC_EXIT). Return values and errno contracts still belong to the individual API; the macros do not make every failure equivalent.

FCE declarations are in include/atalk/fce_api.h, but the event-emission implementation is AFP-specific in etc/afpd/fce_api.c and etc/afpd/fce_util.c. External FCE notifications are separate from internal cache hints.

AFP cache APIs

The following APIs are in the AFP daemon, not libatalk:

API group Header Role
dircache_init(), lookup/add/remove/purge, deferred cleanup etc/afpd/dircache.h Directory/file identity and stat cache
ad_metadata_cached(), ad_store_to_cache(), ad_rebuild_from_cache() etc/afpd/ad_cache.h Cached read-only metadata
rfork_cache_store_from_fd(), rfork_cache_free(), rfork_cache_evict_to_budget() etc/afpd/ad_cache.h Resource-fork content cache
pfd_ostat(), pfd_purge(), pfd_purge_vol(), pfd_shutdown() etc/afpd/pfd_cache.h Parent-directory descriptor cache
iw_init(), iw_grant(), iw_revoke(), iw_note_work(), iw_shutdown() etc/afpd/idle_worker.h Deferred cleanup with exclusive temporal access

iw_revoke() must precede cache access after poll(), including EINTR paths. iw_revoke_signal_safe() only revokes without waiting and is for exit paths. See Caching Architecture and AFP Daemon.

Footnotes

Generated from the Netatalk GitHub Wiki

Last updated 2026-10-21