The WebSDK/NCP AFP File Information records use a distinct SetInfo request bitmap and attribute word. The previous smoke-oriented implementation reused the low response-bit positions for Set Attributes, Modify Date/Time, FinderInfo, Hidden/Invisible, System, and Archive. That made the current tests pass, but it was not faithful to the documented header semantics and risked keeping AFP metadata parallel to existing NetWare attributes.
Switch Set File Information to the documented request bitmap values: 0x0100 for Attributes, 0x1000 for Modify Date/Time, and 0x4000 for FinderInfo. Switch the AFP attribute word to the documented NetWare-style bits: Hidden 0x0200, System 0x0400, Subdirectory 0x1000, and Archive 0x2000.
Map Hidden, System, and Archive through the existing NetWare attribute store via FILE_ATTR_H, FILE_ATTR_S, and FILE_ATTR_A. This keeps AFP Set/Get/Scan aligned with mars_nwe's existing attribute helper instead of maintaining duplicate AFP-only xattr state. FinderInfo remains AFP metadata and still uses the Modify-rights gate added earlier.
Update the Linux smoke helper and suite to use --hidden / --clear-hidden while keeping --invisible / --clear-invisible as compatibility aliases. Document the corrected WebSDK bit values and the convergence rule that NetWare attributes must use mars_nwe NetWare helpers.
Tests: git diff --check; bash -n tests/linux/afp_smoke_suite.sh; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
Route the AFP Set File Information Archive attribute through the existing NetWare attribute store instead of treating it as another mars_nwe AFP metadata xattr bit. The previous rename from Backup to Archive fixed the WebSDK naming, but the implementation still stored Archive together with Finder Invisible/System under org.mars-nwe.afp.attributes. That would duplicate NetWare's existing FILE_ATTR_A state and bypass the attribute path that already owns trustee Modify checks and volume attribute semantics.
Keep Finder Invisible and System as the narrow AFP metadata-only xattr bits for now, but strip Archive from nwatalk's xattr mask. AFP Get/Scan File Information now merges the AFP Archive bit from get_nw_attrib_dword(FILE_ATTR_A), while AFP Set File Information uses set_nw_attrib_word() for Archive set/clear. This reuses the existing nwattrib.c path, including TRUSTEE_M checks, instead of adding a new nwarchive.c flag. The org.mars-nwe.netware.archive xattr remains reserved for archive date/time/archiver metadata.
Tests: gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c; bash -n tests/linux/afp_smoke_suite.sh; git diff --check
TODO: verify the updated archive mapping with afp_smoke_suite.sh and confirm that Archive set/clear is reflected by AFP Get File Information while user.org.mars-nwe.afp.attributes remains limited to Invisible/System.
The NWAFP Set File Information attribute word uses a metadata bit that our earlier smoke code called Backup. That name is too easy to confuse with the distinct AFP backup date/time fields in the Set/Get File Information records. Treat the bit consistently as the Archive attribute in the server constants, Netatalk/xattr helper mask, Linux smoke helper, smoke suite, and documentation.
Keep --backup and --clear-backup as compatibility aliases in afp_set_file_info_smoke so existing local invocations continue to work, but make the generated suite use --archive and --clear-archive. The source-level xattr payload remains unchanged: org.mars-nwe.afp.attributes still stores the same versioned attribute word and bit value 0x0040.
Tests: git diff --check; bash -n tests/linux/afp_smoke_suite.sh; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
Extend the conservative AFP 2.0 Set File Information smoke path to accept the metadata-only System and Backup file attribute bits alongside the already-supported Finder Invisible bit.
The WebSDK/NWAFP Set File Information request uses the file Attributes bitmap to pass a set/clear attribute word. Netatalk stores several AFP file attributes in AppleDouble metadata while computing open-fork state dynamically and leaving enforcement-sensitive bits to the file/fork paths. Mirror only the low-risk mars_nwe subset here: persist Invisible, System, and Backup in the private org.mars-nwe.afp.attributes xattr, and keep NoWrite, NoRename, NoDelete, NoCopy, data-fork-open, resource-fork-open, timestamps, resource forks, and Entry-ID-only write semantics rejected until they have deliberate enforcement and backend design.
The xattr payload remains versioned and unchanged. Reads now expose the three supported metadata bits through Get/Scan File Information, and writes preserve the existing set/clear semantics over the supported mask.
Update the Linux Set File Information smoke helper with --system/--clear-system and --backup/--clear-backup options, while keeping the smoke-suite default unchanged. Document the expected Linux xattr forms 0x01000004 and 0x01000040 for those optional probes.
Tests: git diff --check; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c.
Extend the conservative NCP 0x2222/35/16 AFP 2.0 Set File Information smoke path beyond FinderInfo-only writes by accepting the file Attributes bitmap for one deliberately narrow bit: Finder Invisible.
WebSDK and Netatalk FPSetFileParams semantics carry file attributes as bitmap bit 0, with ATTRBIT_SETCLR selecting set-vs-clear behavior. Mirror that model only for ATTRBIT_INVISIBLE and reject all other AFP attribute bits so DOS/NetWare mode bits, timestamp writes, resource forks, and broader file protection semantics are not implied accidentally.
Persist the mars_nwe-owned AFP attribute word in org.mars-nwe.afp.attributes via the local xattr abstraction. On Linux this maps to user.org.mars-nwe.afp.attributes, matching the org.mars-nwe.* source-level namespace while remaining portable on Linux xattr backends. Get File Information and Scan File Information now merge that stored Invisible bit into the existing 120-byte AFP file-info record.
Update the Linux Set File Information smoke helper with --invisible, --clear-invisible, --attributes-only, and --finder-info-only so FinderInfo and the narrow AFP attribute path can be tested independently or together.
Tests: git diff --check
Tests: gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c
TODO: keep all other AFP Set File Information bits rejected until their write-safe mapping to NetWare/DOS attributes, timestamps, CNID, and resource-fork metadata is designed.
The AFP smoke endpoints can now read mars_nwe-owned entry ids from the versioned org.mars-nwe.afp.entry-id xattr, but a newly discovered file still had to fall back to the temporary stat-derived id on every request until a real CNID allocator exists.
Preserve the existing WebSDK/NWAFP response semantics while making that fallback sticky: when Get Entry ID, Get File Information, or Scan File Information has no mars_nwe xattr and no Netatalk/libatalk AppleDouble/CNID id, derive the existing compatibility id and cache it through nwatalk_set_entry_id(). The first request still logs fallback so diagnostics remain honest about the id origin; subsequent requests should read the xattr directly and avoid re-entering the stat fallback path.
Keep the write narrowly scoped to mars_nwe's private AFP metadata namespace. The payload is versioned, big-endian, and stored through the nwxattr helper, so Linux persists it as user.org.mars-nwe.afp.entry-id while source-level code continues to use the Netatalk-style org.mars-nwe.afp.entry-id name. This does not implement CNID allocation, parent-id lookup, entry-id-only resolution, FinderInfo mutation beyond the existing smoke path, or resource-fork semantics.
Tests:
- git diff --check
- cmake --build build-xattr-off --target nwconn with ENABLE_NETATALK_LIBATALK=OFF
- cmake --build build-xattr-on --target nwconn with ENABLE_NETATALK_LIBATALK=ON against Netatalk 4.4.3 headers plus local link stubs
Implement a deliberately narrow write-safe slice of the WebSDK/NWAFP Set File Information semantics for the NCP 0x2222/35/16 AFP 2.0 Set File Information call.
The only accepted request bitmap is the FinderInfo bit (0x0020). The handler uses the same path-backed raw VOL:-style compatibility subset as the existing AFP get, scan, open-fork, and temporary-directory-handle smoke endpoints, resolves the effective NetWare volume from the path prefix, rejects entry-id-only lookup until persistent CNID/base-ID mapping exists, and rejects directory or non-FinderInfo writes rather than pretending to implement DOS attribute, timestamp, delete-protect, resource-fork, or broader Mac namespace write semantics.
Store the 32-byte FinderInfo block in mars_nwe-owned metadata under the source-level xattr name org.mars-nwe.afp.finder-info and teach the existing AFP file-info response builder to read that value before falling back to Netatalk/libatalk AppleDouble FinderInfo. This makes the write immediately verifiable through AFP 2.0 Get File Information without changing data-fork or resource-fork contents.
Add a small local xattr abstraction for mars_nwe-private metadata names. Netatalk exposes names such as org.netatalk.Metadata at the libatalk layer, but prefixes them with user. on Linux inside its EA wrapper. Mirror that behavior for mars_nwe so source code and documentation use org.mars-nwe.* consistently while Linux stores user.org.mars-nwe.* where the kernel requires a namespace prefix. Convert the existing archive/fileinfo xattr calls to the same wrapper so the previous org.mars-nwe.* namespace rename remains functional on Linux.
Add tests/linux/afp_set_file_info_smoke, which sends AFP 0x10 with a FinderInfo bitmap, then verifies the result through AFP 0x0f Get File Information. Document the smoke command, expected output, server-log shape, and the remaining unsupported Set File Information write semantics.
Tests: git diff --check; gcc -Iinclude -I/mnt/data/stubs -fsyntax-only tests/linux/afp_set_file_info_smoke.c; cmake --build build-off --target nwconn with ENABLE_NETATALK_LIBATALK=OFF; cmake --build build-on --target nwconn with ENABLE_NETATALK_LIBATALK=ON against Netatalk-4.4.3 headers and local link stubs.
Add the first mars_nwe-owned AFP metadata xattr reader before expanding the AFP write surface. The new versioned org.mars-nwe.afp.entry-id payload gives the compatibility layer a stable, project-owned namespace for persistent AFP entry ids without reusing the unreleased user.mars_nwe.* test names or pretending that Netatalk-owned org.netatalk.* keys are ours to mutate.
The lookup order remains conservative: an existing mars_nwe entry-id xattr wins, then the optional Netatalk/libatalk AppleDouble/CNID helper is consulted, and the AFP handlers continue to fall back to their stat-derived temporary id when no persistent metadata exists. No Set File Information, CNID allocation, Finder Info write, or resource-fork write path is introduced here.
This keeps the WebSDK/NWAFP read-only endpoint semantics intact while preparing the metadata storage boundary needed by later AFP Set File Information and CNID work. ENABLE_NETATALK_LIBATALK=OFF still rejects AFP calls at the handler guard, and the xattr reader has an XATTR_SUPPORT-disabled stub so non-xattr builds keep compiling.
Tests:
- git diff --check
- cmake --build build-xattr-off --target nwconn
- cmake -S . -B build-afp-on -DENABLE_NETATALK_LIBATALK=ON -DCMAKE_PREFIX_PATH=/mnt/data/afp_build_prefix
- cmake --build build-afp-on --target nwconn
TODO:
- Add a deliberate write-safe AFP metadata writer/allocator before enabling AFP 2.0 Set File Information.
- Decide whether future mars_nwe AFP metadata stays split across org.mars-nwe.afp.* keys or moves into a compact org.mars-nwe.afp.metadata record.
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.