-
Notifications
You must be signed in to change notification settings - Fork 100
Dev Docs Arch DataFlow
WIP - ALL LINKS IN THIS WIKI STRUCTURE ARE CURRENTLY BROKEN DURING WIKI MIGRATION
THESE ARE COMMUNITY DOCS
This document describes how data flows through the Netatalk system from client requests to filesystem operations, including the interaction between different components and services.
Implementation Files:
-
Master Process Coordination:
etc/netatalk/netatalk.c
- Service orchestration and process management -
AFP Worker Processes:
etc/afpd/main.c
- Client connection handling and request processing -
Authentication Flow:
etc/afpd/auth.c
- User authentication and session management -
Volume Management:
etc/afpd/volume.c
- Volume mounting and access control -
File Operations:
etc/afpd/file.c
,etc/afpd/fork.c
- File I/O and fork handling -
CNID Integration:
libatalk/cnid/cnid.c
- File identification and metadata management
graph TB
subgraph "Client Side"
A[Mac Client Application]
B[macOS Finder/Apps]
end
subgraph "Network Layer"
C[AFP over TCP/DSI]
D[AFP over AppleTalk/ASP]
end
subgraph "Netatalk Master Process"
E[netatalk daemon]
F[Configuration Manager]
G[Service Coordinator]
end
subgraph "AFP Service Layer"
H[afpd Worker Process]
I[Authentication Handler]
J[Volume Manager]
K[File Operation Handler]
end
subgraph "Metadata Management"
L[CNID Metadata Daemon]
M[CNID Database Daemon]
N[Berkeley DB]
end
subgraph "Storage Layer"
O[Unix Filesystem]
P[Extended Attributes]
Q[AppleDouble Files]
end
A --> C
B --> C
A --> D
B --> D
C --> H
D --> H
E --> F
E --> G
G --> H
G --> L
H --> I
H --> J
H --> K
K --> L
L --> M
M --> N
K --> O
K --> P
K --> Q
Netatalk uses AppleDouble format for storing Mac metadata on Unix filesystems. The structure provides comprehensive metadata storage:
Implementation Files:
-
AppleDouble Core:
libatalk/adouble/ad_open.c
- AppleDouble file handling and structure management -
Metadata Operations:
libatalk/adouble/ad_attr.c
- Attribute read/write operations -
Entry Management:
libatalk/adouble/ad_read.c
,libatalk/adouble/ad_write.c
- Entry data I/O -
Header Definitions:
include/atalk/adouble.h
- AppleDouble structure definitions and constants -
Date Management:
libatalk/adouble/ad_date.c
- Timestamp handling for AppleDouble entries
graph TB
subgraph "AppleDouble File Structure"
Header["AppleDouble Header<br/>26 bytes"]
Header --> NumEntries["Number of Entries<br/>2 bytes"]
NumEntries --> EntryDesc["Entry Descriptors<br/>12 bytes each"]
EntryDesc --> DataFork["Data Fork Entry<br/>(optional)"]
EntryDesc --> ResAttrs["Resource Fork Entry"]
EntryDesc --> FileName["Filename Entry"]
EntryDesc --> FileInfo["File Info Entry<br/>32 bytes"]
EntryDesc --> FinderInfo["Finder Info Entry<br/>32 bytes"]
EntryDesc --> Comment["Comment Entry"]
EntryDesc --> IconBW["Icon B&W Entry"]
EntryDesc --> IconColor["Icon Color Entry"]
EntryDesc --> FileDates["File Dates Entry<br/>16 bytes"]
EntryDesc --> MacInfo["Mac File Info<br/>4 bytes"]
EntryDesc --> ProDOS["ProDOS File Info"]
EntryDesc --> MSDOS["MS-DOS File Info"]
EntryDesc --> AFPName["AFP Short Name"]
EntryDesc --> AFPInfo["AFP File Info"]
EntryDesc --> AFPDir["AFP Directory ID"]
end
subgraph "Entry Types"
ET1["ID 1: Data Fork"]
ET2["ID 2: Resource Fork"]
ET3["ID 3: Real Name"]
ET4["ID 4: Comment"]
ET5["ID 5: Icon B&W"]
ET6["ID 6: Icon Color"]
ET7["ID 7: File Info"]
ET8["ID 8: File Dates"]
ET9["ID 9: Finder Info"]
ET10["ID 10: Mac Info"]
ET11["ID 11: ProDOS Info"]
ET12["ID 12: MS-DOS Info"]
ET13["ID 13: AFP Short Name"]
ET14["ID 14: AFP File Info"]
ET15["ID 15: AFP Directory ID"]
end
// AppleDouble header format
struct ad_header {
uint32_t magic; // 0x00051607 (AppleDouble)
uint32_t version; // 0x00020000 (version 2.0)
uint8_t filler[16]; // Reserved (all zeros)
uint16_t numEntries; // Number of entries
// Followed by entry descriptors
};
// Entry descriptor
struct ad_entry {
uint32_t entryID; // Entry type ID
uint32_t offset; // Offset to entry data
uint32_t length; // Length of entry data
};
Netatalk implements sophisticated character set conversion between Mac and Unix filesystems:
Implementation Files:
-
Conversion Engine:
libatalk/unicode/charset.c
- Core character set conversion system -
UTF-8 Support:
libatalk/unicode/utf8.c
- UTF-8 encoding/decoding functions -
Unicode Normalization:
libatalk/unicode/precompose.c
- NFC/NFD normalization handling -
Character Tables:
libatalk/unicode/charsets/
- Character mapping tables and definitions -
Volume Integration:
etc/afpd/volume.c
- Character conversion configuration per volume -
Path Conversion:
etc/afpd/directory.c
- Filename conversion in directory operations
flowchart TD
MacClient["Mac Client<br/>Mac Roman/UTF-8"]
subgraph "Character Conversion Pipeline"
Input["Input Character Data"]
DetectEnc["Detect Encoding<br/>Mac Roman vs UTF-8"]
subgraph "Mac-to-Unix Conversion"
MacToUTF8["Convert to UTF-8<br/>Intermediate format"]
ApplyCaseM2U["Apply Case Folding<br/>AFPVOL_MTOU* flags"]
HandleIllegal["Handle Illegal Sequences<br/>AFPVOL_EILSEQ flag"]
NormalizeUTF8["UTF-8 Normalization<br/>NFC/NFD handling"]
end
subgraph "Unix-to-Mac Conversion"
UTF8ToMac["Convert from UTF-8"]
ApplyCaseU2M["Apply Case Folding<br/>AFPVOL_UTOM* flags"]
EncodeResult["Encode for Mac Client<br/>Based on AFP version"]
end
FilesystemPath["Unix Filesystem Path<br/>UTF-8 normalized"]
MacPath["Mac Client Path<br/>Encoded for transport"]
end
MacClient --> Input
Input --> DetectEnc
DetectEnc --> MacToUTF8
MacToUTF8 --> ApplyCaseM2U
ApplyCaseM2U --> HandleIllegal
HandleIllegal --> NormalizeUTF8
NormalizeUTF8 --> FilesystemPath
FilesystemPath --> UTF8ToMac
UTF8ToMac --> ApplyCaseU2M
ApplyCaseU2M --> EncodeResult
EncodeResult --> MacPath
MacPath --> MacClient
subgraph "Conversion Flags"
CF1["AFPVOL_MTOUUPPER: Mac→Unix uppercase"]
CF2["AFPVOL_MTOULOWER: Mac→Unix lowercase"]
CF3["AFPVOL_UTOMUPPER: Unix→Mac uppercase"]
CF4["AFPVOL_UTOMLOWER: Unix→Mac lowercase"]
CF5["AFPVOL_EILSEQ: Preserve illegal sequences"]
end
// Character conversion control
struct charset_functions {
size_t (*to_ucs2)(const charset_t from, char *src, size_t srclen,
char *dest, size_t destlen);
size_t (*from_ucs2)(const charset_t to, char *src, size_t srclen,
char *dest, size_t destlen, char **inbuf, size_t *inbytesleft);
size_t (*to_utf8)(const charset_t from, char *src, size_t srclen,
char *dest, size_t destlen);
size_t (*utf8_to_charset)(const charset_t to, char *src, size_t srclen,
char *dest, size_t destlen);
};
// Volume character conversion state
typedef struct {
charset_t v_volcharset; // Volume filesystem encoding
charset_t v_maccharset; // Mac client encoding
uint16_t v_mtou_flags; // Mac-to-Unix conversion flags
uint16_t v_utom_flags; // Unix-to-Mac conversion flags
uint32_t v_kTextEncoding;// Network byte order text encoding
} charset_vol_t;
Implementation Files:
-
Connection Handling:
etc/afpd/main.c
- TCP connection acceptance and client process forking -
DSI Session Setup:
libatalk/dsi/dsi_stream.c
- DSI session establishment and parameter negotiation -
Authentication Processing:
etc/afpd/auth.c
- User login and authentication flow -
UAM Integration:
etc/uams/
- User Authentication Module implementations -
Session Management:
etc/afpd/afp_options.c
- Session configuration and state management
sequenceDiagram
participant Client as Mac Client
participant Master as netatalk
participant AFP as afpd
participant Auth as UAM Module
Client->>AFP: TCP Connect (port 548)
AFP->>Master: Register new connection
Client->>AFP: DSI OpenSession
AFP-->>Client: Session parameters
Client->>AFP: FPLogin (username/password)
AFP->>Auth: Authenticate user
Auth-->>AFP: Authentication result
AFP-->>Client: Login response
Note over Client,AFP: Session established
Implementation Files:
-
Volume Operations:
etc/afpd/volume.c
- Volume mounting, access control, and configuration -
Volume Discovery:
etc/afpd/afp_config.c
- Volume configuration parsing and validation -
CNID Initialization:
etc/cnid_metad/cnid_metad.c
- CNID database service initialization -
Database Setup:
etc/cnid_dbd/main.c
- Berkeley DB backend initialization -
Filesystem Validation:
etc/afpd/volume.c
- Path validation and permissions checking
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant Vol as Volume Manager
participant CNID as CNID System
participant FS as Filesystem
Client->>AFP: FPOpenVol (volume name)
AFP->>Vol: Locate volume config
Vol->>FS: Check volume path access
Vol->>CNID: Initialize CNID database
CNID-->>Vol: Database ready
Vol-->>AFP: Volume opened
AFP-->>Client: Volume parameters
Implementation Files:
-
Fork Operations:
etc/afpd/fork.c
- File fork opening, reading, and management -
File I/O:
etc/afpd/file.c
- Core file operation implementations -
CNID Resolution:
libatalk/cnid/cnid.c
- Path-to-CNID resolution and metadata lookup -
Buffer Management:
libatalk/dsi/dsi_stream.c
- DSI read buffering and streaming - Cache Integration: Built into AFP daemon for frequently accessed data
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant CNID as CNID System
participant FS as Unix Filesystem
participant Cache as Buffer Cache
Client->>AFP: FPOpenFork (file path)
AFP->>CNID: Resolve path to CNID
CNID-->>AFP: File CNID + metadata
AFP->>FS: Open file descriptor
AFP-->>Client: Fork reference number
Client->>AFP: FPRead (offset, length)
AFP->>Cache: Check buffer cache
alt Cache hit
Cache-->>AFP: Cached data
else Cache miss
AFP->>FS: Read from filesystem
FS-->>AFP: File data
AFP->>Cache: Update cache
end
AFP-->>Client: File data
Implementation Files:
-
Write Operations:
etc/afpd/fork.c
- File writing, data streaming, and fork management -
Metadata Updates:
etc/afpd/file.c
- File size and modification time updates -
CNID Updates:
libatalk/cnid/cnid.c
- Metadata consistency and CNID updates -
Extended Attributes:
etc/afpd/extattrs.c
- Extended attribute synchronization -
AppleDouble Sync:
libatalk/adouble/ad_write.c
- Metadata file updates
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant CNID as CNID System
participant FS as Unix Filesystem
participant Meta as Metadata Store
Client->>AFP: FPWrite (data, offset, length)
AFP->>FS: Write to file
FS-->>AFP: Write confirmation
AFP->>CNID: Update file metadata
CNID->>Meta: Store modification time
CNID->>Meta: Update file size
Meta-->>CNID: Metadata stored
AFP->>FS: Sync extended attributes
AFP-->>Client: Write confirmation
Netatalk implements sophisticated directory management through two primary data structures (from include/atalk/directory.h
):
Implementation Files:
-
Directory Structures:
include/atalk/directory.h
- Core directory and path structure definitions -
Directory Operations:
etc/afpd/directory.c
- Directory enumeration, caching, and management -
Path Resolution:
etc/afpd/directory.c
- Path parsing and CNID resolution -
Directory Cache:
etc/afpd/directory.c
- Queue-based directory cache management -
Path Utilities:
libatalk/util/unix.c
- Path manipulation and validation utilities
// Core directory object (93 lines of implementation detail)
struct dir {
bstring d_fullpath; // Complete Unix path to directory (or file)
bstring d_m_name; // Mac name representation
bstring d_u_name; // Unix name (may share storage with d_m_name)
ucs2_t *d_m_name_ucs2; // Mac name as UCS2 Unicode
// Queue and cache management
qnode_t *qidx_node; // Position in directory cache queue
time_t d_ctime; // Inode ctime for reenumeration detection
time_t dcache_ctime; // Directory cache ctime
ino_t dcache_ino; // Inode number for change detection
// Directory metadata and state
int d_flags; // Directory flags (filesystem type, cache state)
cnid_t d_pdid; // Parent directory CNID
cnid_t d_did; // Directory CNID
uint32_t d_offcnt; // Offspring count (when valid)
uint16_t d_vid; // Volume ID (for multi-volume cache)
uint32_t d_rights_cache; // Cached access rights (mode + ACL)
};
// Path resolution structure
struct path {
int m_type; // Mac name type (long name, Unicode)
char *m_name; // Mac name pointer
char *u_name; // Unix name pointer
cnid_t id; // File/directory CNID (for getmetadata)
struct dir *d_dir; // Associated directory object
// Filesystem state caching
int st_valid; // Whether stat information is valid
int st_errno; // Last stat() error code
struct stat st; // Cached stat() results
};
// Directory flags and constants
#define DIRF_FSMASK (3<<0) // Filesystem type mask
#define DIRF_UFS (1<<1) // UFS filesystem
#define DIRF_ISFILE (1<<3) // Cached file, not directory
#define DIRF_OFFCNT (1<<4) // Offspring count is valid
#define DIRF_CNID (1<<5) // Requires CNID renumeration
// Reserved directory CNIDs
#define DIRDID_ROOT_PARENT htonl(1) // Parent of root directory
#define DIRDID_ROOT htonl(2) // Root directory CNID
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant DirCache as Directory Cache
participant CNID as CNID System
participant FS as Unix Filesystem
Client->>AFP: FPOpenDir (directory path)
AFP->>AFP: Parse path into struct path
AFP->>DirCache: Lookup struct dir in cache
alt Directory cached and valid
DirCache-->>AFP: Return cached struct dir
Note over AFP: Check d_ctime vs dcache_ctime
else Directory not cached/invalid
AFP->>FS: stat() directory for metadata
AFP->>CNID: Get/create directory CNID
AFP->>DirCache: Create new struct dir object
Note over DirCache: Set d_fullpath, d_m_name, d_u_name
Note over DirCache: Cache in qidx_node queue position
end
AFP-->>Client: Directory reference (d_did)
Client->>AFP: FPEnumerate (count, start index)
AFP->>DirCache: Check offspring count (d_offcnt)
alt Offspring count valid (DIRF_OFFCNT set)
Note over DirCache: Use cached count for bounds checking
else Offspring count invalid
AFP->>FS: readdir() to count entries
AFP->>DirCache: Update d_offcnt, set DIRF_OFFCNT
end
AFP->>FS: Read directory contents
FS-->>AFP: Directory entries
loop For each directory entry
AFP->>AFP: Create struct path for entry
AFP->>CNID: Resolve u_name to CNID + metadata
CNID-->>AFP: File/directory metadata
AFP->>DirCache: Update or create child struct dir
end
AFP-->>Client: Directory listing with CNIDs
The directory cache uses a sophisticated queue-based system with change detection:
// Directory cache validation (inline function)
static inline int path_isadir(struct path *o_path) {
return o_path->d_dir != NULL; // Directory if struct dir exists
}
// Cache invalidation triggers:
// 1. d_ctime != dcache_ctime (inode ctime changed)
// 2. dcache_ino != current_ino (inode number changed)
// 3. DIRF_CNID flag set (requires renumeration)
// 4. Volume remount (d_vid mismatch)
Implementation Files:
-
CNID Interface:
libatalk/cnid/cnid.c
- Core CNID operations and database interface -
Database Backend:
etc/cnid_dbd/dbd.c
- Berkeley DB operations and transaction management -
CNID Daemon:
etc/cnid_dbd/main.c
- CNID database daemon service -
Metadata Daemon:
etc/cnid_metad/cnid_metad.c
- CNID metadata service coordination -
Database Utilities:
etc/cnid_dbd/cmd_dbd.c
- Database maintenance and repair utilities
graph LR
A[File Path] --> B[Path Parser]
B --> C[Component Lookup]
C --> D{CNID Cache}
D -->|Hit| E[Return CNID]
D -->|Miss| F[Database Query]
F --> G[Berkeley DB]
G --> H[CNID Record]
H --> I[Update Cache]
I --> E
Implementation Files:
-
Transaction Management:
etc/cnid_dbd/dbd.c
- Database transaction handling and commit logic -
IPC Communication:
libatalk/util/server_ipc.c
- Inter-process communication between AFP and CNID -
Request Processing:
etc/cnid_dbd/cmd_dbd.c
- CNID request parsing and response generation -
Database Operations:
etc/cnid_dbd/dbd_*.c
- Specialized database operation implementations -
Error Handling:
etc/cnid_dbd/main.c
- Database error recovery and logging
sequenceDiagram
participant AFP as afpd
participant Meta as cnid_metad
participant DBD as cnid_dbd
participant BDB as Berkeley DB
AFP->>Meta: CNID request
Meta->>DBD: Forward request
DBD->>BDB: Begin transaction
DBD->>BDB: Database operation
BDB-->>DBD: Operation result
alt Success
DBD->>BDB: Commit transaction
BDB-->>DBD: Commit success
else Failure
DBD->>BDB: Rollback transaction
BDB-->>DBD: Rollback complete
end
DBD-->>Meta: Response
Meta-->>AFP: CNID result
Netatalk implements sophisticated AppleDouble metadata handling through a comprehensive 231-line structure (from include/atalk/adouble.h
):
Implementation Files:
-
Structure Definitions:
include/atalk/adouble.h
- Complete AppleDouble structure and constants -
File Operations:
libatalk/adouble/ad_open.c
- AppleDouble file creation and access -
Entry Management:
libatalk/adouble/ad_read.c
,libatalk/adouble/ad_write.c
- Entry I/O operations -
Locking System:
libatalk/adouble/ad_lock.c
- AppleDouble file locking mechanisms -
Metadata Integration:
etc/afpd/file.c
- AppleDouble integration with AFP file operations -
Attribute Handling:
libatalk/adouble/ad_attr.c
- Extended attribute management
// Core AppleDouble object (231 lines of implementation)
struct adouble {
// Official AppleDouble header format
uint32_t ad_magic; // Magic number (AD_APPLEDOUBLE_MAGIC = 0x00051607)
uint32_t ad_version; // Version (AD_VERSION2 = 0x00020000, AD_VERSION_EA = 0x00020002)
char ad_filler[16]; // Filler bytes ("Netatalk " or "Mac OS X")
// Entry table for all metadata components
struct ad_entry ad_eid[ADEID_MAX]; // 19 possible entry types
// File descriptor management
struct ad_fd ad_data_fork; // Data fork file descriptor
struct ad_fd ad_resource_fork; // Resource fork/metadata file descriptor
struct ad_fd *ad_rfp; // Resource fork pointer
struct ad_fd *ad_mdp; // Metadata pointer
// Version and state management
int ad_vers; // Our AppleDouble version info
int ad_adflags; // Open flags (ADFLAGS_DIR, ADFLAGS_RF, etc.)
uint32_t ad_inited; // Initialization state (AD_INITED = 0xad494e54)
int ad_options; // Volume options
// Reference counting for multiple fork access
int ad_refcount; // Overall reference count
int ad_data_refcount; // Data fork references
int ad_meta_refcount; // Metadata references
int ad_reso_refcount; // Resource fork references
// Resource fork and name handling
off_t ad_rlen; // Resource fork length (AFP 3.0+)
char *ad_name; // Mac name (maccharset or UTF8-MAC)
struct adouble_fops *ad_ops; // Function operations pointer
uint16_t ad_open_forks; // Open forks count (by others)
// Data buffer management
size_t valid_data_len; // Bytes read into ad_data
char ad_data[AD_DATASZ_MAX]; // Metadata buffer (1024 bytes max)
};
// File descriptor structure for each fork
struct ad_fd {
int adf_fd; // File descriptor (-1: invalid, AD_SYMLINK: symlink)
char *adf_syml; // Symlink target
int adf_flags; // Open flags
adf_lock_t *adf_lock; // Lock structure
int adf_refcount, adf_lockcount, adf_lockmax; // Lock management
};
AppleDouble supports 19 different metadata entry types:
// Standard AppleDouble entries
#define ADEID_DFORK 1 // Data fork
#define ADEID_RFORK 2 // Resource fork
#define ADEID_NAME 3 // Original filename
#define ADEID_COMMENT 4 // File comment
#define ADEID_ICONBW 5 // Black & white icon
#define ADEID_ICONCOL 6 // Color icon
#define ADEID_FILEDATESI 8 // File dates and info
#define ADEID_FINDERI 9 // Finder info (32 bytes)
#define ADEID_MACFILEI 10 // Mac file info (unused)
#define ADEID_PRODOSFILEI 11 // ProDOS file info
#define ADEID_SHORTNAME 13 // 8.3 short name
#define ADEID_AFPFILEI 14 // AFP file info
#define ADEID_DID 15 // Directory ID
// Netatalk private entries (reuse DID for files)
#define ADEID_PRIVDEV 16 // Device number
#define ADEID_PRIVINO 17 // Inode number
#define ADEID_PRIVSYN 18 // Database synchronization
#define ADEID_PRIVID 19 // Private ID
// Entry data lengths
#define ADEDLEN_NAME 255 // Filename length
#define ADEDLEN_COMMENT 200 // Comment length
#define ADEDLEN_FINDERI 32 // Finder info length
#define ADEDLEN_FILEDATESI 16 // File dates length
#define ADEDLEN_AFPFILEI 4 // AFP file info length
Netatalk supports multiple AppleDouble formats:
// Format version data sizes (compile-time validated)
#define AD_DATASZ2 741 // AppleDouble v2 format size
#define AD_DATASZ_EA 402 // Extended attributes format size
#define AD_DATASZ_OSX 82 // Mac OS X format size
#define AD_DATASZ_MAX 1024 // Maximum buffer size
// Header structure (26 bytes)
#define AD_HEADER_LEN 26 // Magic(4) + Version(4) + Filler(16) + NumEntries(2)
#define AD_ENTRY_LEN 12 // Each entry: ID(4) + Offset(4) + Length(4)
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant AD as AppleDouble Handler
participant FS as Filesystem
participant EA as Extended Attributes
participant Lock as File Locking
Client->>AFP: Request file metadata
AFP->>AD: ad_open(path, ADFLAGS_HF)
Note over AD: Initialize struct adouble
AD->>AD: ad_init() - set ad_magic, ad_version, ad_ops
alt Extended Attributes mode (AD_VERSION_EA)
AD->>FS: open() data file for metadata fd
AD->>EA: fgetxattr() for each entry type
Note over AD: Store in ad_data[AD_DATASZ_EA] buffer
else AppleDouble v2 mode (AD_VERSION2)
AD->>FS: open() ._filename AppleDouble file
AD->>Lock: ad_lock(ADLOCK_RD) for read lock
AD->>FS: read() AppleDouble header + entries
Note over AD: Parse into ad_eid[] entry table
end
AD->>AD: ad_init_offsets() - calculate entry positions
Note over AD: Set ad_inited = AD_INITED (0xad494e54)
AD-->>AFP: struct adouble with metadata
AFP->>AD: ad_entry(ADEID_FINDERI) - get Finder info
AFP->>AD: ad_getdate(AD_DATE_MODIFY) - get dates
AFP-->>Client: File information with metadata
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant AD as AppleDouble Handler
participant FS as Filesystem
participant Lock as File Locking
participant EA as Extended Attributes
Client->>AFP: Set file metadata
AFP->>AD: ad_open(path, ADFLAGS_HF | ADFLAGS_RDWR)
AD->>Lock: ad_lock(ADLOCK_WR) - exclusive write lock
Note over Lock: Lock ranges: AD_FILELOCK_BASE + offset
AFP->>AD: ad_setattr() or ad_setdate()
AD->>AD: Update ad_eid[] entries and ad_data[] buffer
alt Extended Attributes mode
AD->>EA: fsetxattr() for modified entries
Note over EA: Atomic update of extended attributes
else AppleDouble v2 mode
AD->>AD: ad_rebuild_header() - reconstruct header
AD->>FS: lseek(0) + write() complete file
Note over FS: Write magic + version + filler + entries
end
AD->>AD: ad_flush() - sync changes to disk
AD->>Lock: ad_unlock() - release write lock
AD-->>AFP: Update complete
AFP-->>Client: Success response
The AppleDouble system manages detailed Mac file attributes:
// FinderInfo flags (stored in ADEID_FINDERI entry)
#define FINDERINFO_INVISIBLE (1<<14) // File is invisible
#define FINDERINFO_HASCUSTOMICON (1<<10) // Custom icon present
#define FINDERINFO_ISALIAS (1<<15) // File is alias
#define FINDERINFO_NAMELOCKED (1<<12) // Name locked
#define FINDERINFO_HASBUNDLE (1<<13) // Has bundle
// AFP attributes (computed from FinderInfo + filesystem)
#define ATTRBIT_INVISIBLE (1<<0) // Invisible (from FinderInfo)
#define ATTRBIT_SYSTEM (1<<2) // System file
#define ATTRBIT_NOWRITE (1<<5) // Write protected
#define ATTRBIT_BACKUP (1<<6) // Needs backup
#define ATTRBIT_NORENAME (1<<7) // Cannot rename
#define ATTRBIT_NODELETE (1<<8) // Cannot delete
AppleDouble implements sophisticated file locking for fork management:
// Lock types and ranges
#define ADLOCK_RD (1<<0) // Read lock
#define ADLOCK_WR (1<<1) // Write lock
#define ADLOCK_FILELOCK (1<<3) // File-level lock
// Lock ranges (using high offset values)
#define AD_FILELOCK_OPEN_WR (AD_FILELOCK_BASE + 0) // Data fork write
#define AD_FILELOCK_OPEN_RD (AD_FILELOCK_BASE + 1) // Data fork read
#define AD_FILELOCK_RSRC_OPEN_WR (AD_FILELOCK_BASE + 2) // Resource fork write
#define AD_FILELOCK_RSRC_OPEN_RD (AD_FILELOCK_BASE + 3) // Resource fork read
sequenceDiagram
participant Client as Mac Client
participant AFP as afpd
participant SL as Spotlight Module
participant Tracker as GNOME Tracker
participant Index as Search Index
Client->>AFP: Spotlight search query
AFP->>SL: Parse search criteria
SL->>Tracker: SPARQL query
Tracker->>Index: Search index
Index-->>Tracker: Matching files
Tracker-->>SL: Result set
SL->>SL: Filter by volume/permissions
SL-->>AFP: Filtered results
AFP-->>Client: Search results
- Read-ahead caching: Anticipate sequential reads
- Write-behind buffering: Batch filesystem writes
- Directory caching: Cache frequently accessed directories
- CNID caching: Keep recently accessed CNIDs in memory
- Keep-alive handling: Efficient idle connection management
- Request pipelining: Process multiple requests concurrently
- Connection pooling: Reuse worker processes
- Load balancing: Distribute connections across workers
- Transaction batching: Group related operations
- Index optimization: Efficient CNID lookups
- Cache warming: Preload frequently accessed data
- Compaction scheduling: Periodic database maintenance
graph TD
A[Connection Error] --> B{Error Type}
B -->|Network| C[Reconnect with backoff]
B -->|Protocol| D[Reset session state]
B -->|Authentication| E[Re-authenticate user]
B -->|Resource| F[Free resources and retry]
C --> G[Resume operations]
D --> G
E --> G
F --> G
graph TD
A[Database Error] --> B{Error Type}
B -->|Corruption| C[Database repair]
B -->|Lock timeout| D[Retry with backoff]
B -->|Disk full| E[Alert and cleanup]
B -->|Permission| F[Check filesystem access]
C --> G[Resume operations]
D --> G
E --> H[Graceful degradation]
F --> G
This data flow documentation provides a comprehensive view of how information moves through the Netatalk system, enabling better understanding of performance characteristics, optimization opportunities, and failure modes.
Resources
OS Specific Guides
- Installing Netatalk on Alpine Linux
- Installing Netatalk on Debian Linux
- Installing Netatalk on Fedora Linux
- Installing Netatalk on FreeBSD
- Installing Netatalk on macOS
- Installing Netatalk on NetBSD
- Installing Netatalk on OmniOS
- Installing Netatalk on OpenBSD
- Installing Netatalk on OpenIndiana
- Installing Netatalk on openSUSE
- Installing Netatalk on Solaris
- Installing Netatalk on Ubuntu
Technical Docs
- CatalogSearch
- Kerberos
- Special Files and Folders
- Spotlight
- AppleTalk Kernel Module
- Print Server
- MacIP Gateway
- MySQL CNID Backend
Development