Files
mars-nwe/AI.md
2026-06-02 18:30:37 +02:00

38 KiB

AI working notes for mars-nwe

This file is for future ChatGPT sessions. It records general working rules and local build/test notes only. It should not be used as the current project status log; the current patch stack and task context should be pasted into a new chat separately.

Start of a new chat

When the user says this is a new chat or asks to continue mars-nwe work, first read this file before proposing patches or making assumptions. Then ask for, or use, the current project status that the user pasted into the chat.

Current handoff status after patch 0222

The current accepted patch line in this chat is expected to include:

  • endpoint-audit/documentation patches through 0176-docs-audit-direct-lifecycle-buffer-endpoints.patch;
  • redesign documentation patches 0177 through 0198;
  • endpoint-audit/documentation patches 0199 through 0219;
  • redesign clarification patch 0220-docs-record-print-queue-redesign-link.patch;
  • endpoint-audit patch 0221-docs-audit-ncp-extension-stubs.patch;
  • endpoint-audit patch 0222-docs-audit-direct-file-metadata-stubs.patch;
  • latest expected patch name: 0222-docs-audit-direct-file-metadata-stubs.patch.

When continuing in a new chat, first ask the user which patch was actually last applied. If they confirm 0222, build the next patch as 0223-... against a tree that already contains 0222. If they only applied through 0221, apply or rebuild 0222 before continuing endpoint work. If any patch failed or was skipped, rebuild against the last confirmed applied patch instead of assuming the file in /mnt/data was accepted.

Known numbering/patch-history notes from this chat:

  • 0190-docs-clarify-imported-nwlog-backend-layout.patch was superseded because patch number 0189 was accidentally skipped and the old 0190 failed after 0188. Do not reuse that old file.
  • Use 0189-docs-clarify-imported-nwlog-backend-layout.patch instead.
  • Then use 0190-docs-clarify-simple-syslog-nwlog-backends.patch, followed by 0191 ... 0203.

The user prefers patch verification snippets to contain only:

git am patchname.patch

Do not include git diff --check HEAD^..HEAD in the final summary unless the user asks for it.

Current redesign decisions to preserve

REDESIGN.md is now the place for broad architecture notes. Do not keep growing TODO.md with long-term redesign material. TODO.md should remain for concrete endpoint/test/fix follow-ups.

High-level NCP architecture direction:

  • Add a small internal NCP dispatch/handoff layer over time; avoid a large message-bus rewrite.
  • Provider boundary is not the same as process boundary.
  • nwbind remains legacy bindery provider/service.
  • Queue is a strong candidate for a future nwqueue provider/process, but first split it logically from bindery.

NCP Extension note from patch 0221:

  • SDK 0x2222/36 / wire 0x24 NCP Extension information and SDK 0x2222/37 / wire 0x25 Execute NCP Extension are source-stub-audited as planned NetWare 4.x extension-registration work.
  • src/nwconn.c now contains disabled MARS_NWE_4 stubs for 36/00 through 36/06 and direct 37. They intentionally return 0xfb if ever enabled without a real extension registry/provider.
  • Future owner is an extension registry/provider. Do not route extension payloads through nwserv as a data-plane broker; nwserv remains only control-plane/supervision/registry.
  • Patch 0222 audits the remaining old direct file-metadata/open-create compatibility slots SDK 0x2222/79, 0x2222/84, and 0x2222/85 / wire 0x4f, 0x54, and 0x55. No active top-level handlers existed; the patch records disabled #if 0 stubs in src/nwconn.c. Future owner is the filesystem/namespace provider, not NDS.
  • The next patch number should be 0223 if 0222 was applied.

Print/queue redesign note from patch 0220:

  • Do not describe printing as entirely absent. Queue-backed printing already exists in the project through the queue/job printing paths.
  • The old direct 0x2222/17 Print/Spool NCP family is a separate compatibility surface and currently remains documented as disabled stubs.
  • Future direct 17/xx implementation should bridge to existing queue printing mechanics rather than creating a separate print subsystem.
  • Logical owner: queue/print-spool provider area, possible future nwqueue; not nwnds, not nwdirectory.
  • Filesystem/volume/namespace should become a provider/module boundary first; a separate process would be risky and later only.
  • Semaphore, server-management, and most small call families should remain modules/providers, not separate processes.
  • nwserv is the control plane/supervisor/provider registry, not a data-plane payload router. Normal requests should flow client -> nwconn -> provider -> nwconn -> client, not through nwserv as broker.
  • Provider processes must always return one formal internal handoff reply. NO_REPLY is an explicit reply kind, not silence. nwconn owns the final client NCP reply envelope and send.

Transport direction:

  • TCP/IP support is a transport split below nwconn/nwserv, not a new daemon.
  • Planned code layout: src/nwtransport.c, src/nwipx.c, src/nwtcp.c.
  • nwtransport is a code/library boundary, not a process.
  • Higher providers must not depend on raw ipxAddr_t long-term.
  • IPX SAP/RIP/watchdog/broadcast behavior remains isolated as IPX-specific.

Secure IPC/TLS direction:

  • Client-facing NetWare 4.x/NCP/NDS compatibility must not require TLS by default. Keep historical clients compatible.
  • LDAP/LDAPS/StartTLS for nwdirectory uses wolfSSL at the external LDAP edge.
  • Internal provider IPC over TCP, if added later, must always use wolfSSL-backed TLS with mutual authentication. No plaintext fallback for TCP provider IPC.
  • Local IPC may remain Unix-domain sockets, pipes, socketpairs, or inherited FDs with strict permissions; still avoid logging decoded secrets.
  • Add nwtls as the internal TLS facade if/when wolfSSL is wired into runtime: include/nwtls.h, src/nwtls.c, src/nwtls_wolfssl.c.

Directory/NetWare 4.x direction:

  • libdirectory is the shared internal C API/library used by nwbind, future nwnds, nwdirectory, and nwsetup. These components should not talk LDAP internally just to reach the directory store.
  • libflaim is the planned persistent store under libdirectory. FLAIM is C++; keep its C++ API behind libdirectory so old mars-nwe C code does not include FLAIM C++ headers directly.
  • nwdirectory is the mars-nwe integration name for the tinyldap-derived LDAP/LDAPS service. Standalone/upstream identity remains tinyldap; inside mars-nwe it builds the nwdirectory service.
  • Future nwnds is the NetWare 4.x/NDS compatibility layer and should use libdirectory, not LDAP protocol calls, as its internal backend path.
  • nwbind should eventually become a legacy bindery adapter over libdirectory/libflaim, not maintain a second persistent truth.
  • Do not mention or design Kerberos for the current NetWare 4.x target.

Configuration and setup direction:

  • Move toward a real typed, documented INI format. Do not use JSON as the admin config format.
  • The generated INI is also user documentation. Writers must preserve comments where possible or regenerate from a full documented template; never rewrite it into an undocumented minimal key/value dump.
  • nwsetup is the provisioning/setup tool. It should initialize the libdirectory/libflaim store, create initial schema/tree/admin/server objects, migrate bindery data later, and edit config atomically.
  • No reusable Admin/Supervisor/NDS/LDAP plaintext passwords in the new typed INI. Initial passwords and recovery resets belong to explicit nwsetup commands and only hashes/verifiers go into the store.
  • Legacy bindery config-password reset may remain only as deprecated compatibility behavior; Directory/NDS mode uses nwsetup recovery commands.

Logging direction:

  • Add a small internal nwlog facade instead of direct zlog/log.c calls in handlers/providers. Project layout: include/nwlog.h, src/nwlog.c.
  • Category wrappers should exist for normal code: nwlog_ncp(), nwlog_handoff(), nwlog_bindery(), nwlog_queue(), nwlog_directory(), nwlog_nds(), nwlog_ldap(), nwlog_auth(), nwlog_acl(), nwlog_recovery(), nwlog_security(). They populate an internal nwlog_event and call nwlog_emit().
  • rxi/log.c may be vendored/adapted as nwlog_simple, not exposed directly: include/nwlog_simple.h, src/nwlog_simple.c. It is a simple stderr/stdout/file/callback basis and is a good default for systemd/journald.
  • nwlog_syslog may later be derived/cloned from the simple backend for classic syslog(3) explicitly: src/nwlog_syslog.c.
  • zlog is the preferred optional advanced routing backend behind the facade: src/nwlog_zlog.c. It may live as a third_party/zlog submodule.
  • Never route raw decoded NCP/handoff/auth payloads to remote loggers. Only redacted structured events should leave the host.

Third-party/fork policy:

  • Fixed third-party libraries live under third_party/, such as existing yyjson, planned wolfssl, planned libflaim, and optional zlog.
  • wolfSSL is the fixed bundled TLS implementation, similar in spirit to yyjson. Do not design a first-pass OpenSSL/LibreSSL backend matrix.
  • libflaim should live under third_party/libflaim as a mars-nwe-maintained import/fork/mirror. Source may come from SourceForge/SVN and/or a distro source package such as openSUSE libflaim-4.9.1046. Document exact import, revision/version, license files, distro patches, and local patches in third_party/libflaim/README.mars-nwe.md.
  • FLAIM r1112 has Autotools (configure.ac, Makefile.am, libtool, config.h, subprojects ftk, flaim, sql, xflaim). Do not wrap Autotools from CMake; replace it with a real CMake build. First required targets are FLAIM::ftk and FLAIM::flaim; SQL/XFLAIM/tools/tests/docs can come later.
  • FLAIM source license observed by the user: library sources LGPL-2.1; helper files like svn2cl.xsl may have separate licenses such as BSD-3-Clause. Keep these separated in import docs.
  • Forked/integrated mars components that become project services live in the repository root, matching existing style such as mail, admin, and dosutils. mars-tinyldap belongs in the root, not third_party, because it will be heavily adapted into nwdirectory.
  • tinyldap currently has a hand-written Makefile and flat-file/mmap storage. It needs a real CMake build, not a Makefile wrapper. Standalone remains tinyldap; mars-nwe integration builds nwdirectory.
  • For tinyldap/nwdirectory, first CMake split can expose internal targets such as tinyldap::asn1, tinyldap::ldap, tinyldap::ldif, tinyldap::auth, tinyldap::storage, and tinyldap::server. Replace flat-file storage with libdirectory -> libflaim later.
  • Old tinyldap TLS code can remain reference/legacy/standalone-only; mars-nwe nwdirectory TLS should go through nwtls/wolfSSL.

Schema/import direction:

  • Do not invent NetWare 4.11 schema by hand if a real source can be obtained. The user expects the complete schema to be hidden in NetWare 4.11 installation material such as install.dat; a real 4.11 install may be needed to extract it.
  • .SCH files such as uploaded NLS.SCH are useful format examples/fragments. They contain readable ASN.1-like ATTRIBUTE and OBJECT-CLASS blocks, but are not the full schema truth.
  • nwsetup should eventually support native NetWare 4.11 schema import, .SCH fragment import, and LDIF import/export. LDIF remains human-readable, diffable, and testable, but the canonical runtime representation is libdirectory schema objects stored in libflaim.
  • tinyldap has useful ASN.1 BER/DER and LDIF code (scan_asn1*, fmt_asn1*, asn1dump, ldif_parse.c), but it does not appear to be an NDS .SCH or NetWare schema importer. Reuse ideas/code carefully through the nwdirectory fork, but plan a dedicated schema import layer.
  • Samba source4/dsdb/schema and setup schema conversion code are useful references for OID/prefixMap/schema-loading ideas, but Samba is GPL-family; do not blindly copy code into mars-nwe. Use as a reference and implement a mars-nwe-native importer/OID module.

Latest endpoint audit note:

  • Patch 0221 audits SDK 0x2222/36 / wire 0x24 NCP Extension information and SDK 0x2222/37 / wire 0x25 Execute NCP Extension as planned NetWare 4.x extension-registration work.
  • src/nwconn.c contains disabled MARS_NWE_4 stubs for 36/00 through 36/06 and direct 37; they are documentation/source markers only and do not change the default runtime.
  • Future implementation needs an extension registry/provider. nwserv may supervise/register providers but must not become the data-plane broker for extension payloads.
  • Patch 0222 audits SDK 0x2222/79, 0x2222/84, and 0x2222/85 / wire 0x4f, 0x54, and 0x55 as old direct file-metadata/open-create and sparse-data compatibility gaps. It adds disabled #if 0 stubs next to the old direct file-I/O switch in src/nwconn.c; future owner is the filesystem/namespace provider.
  • Previous print note still applies: direct 17/xx spool NCPs are only the old direct-spool compatibility surface; queue-backed printing already exists.

The next patch number should be 0223 if 0222 was applied. Likely next blocks are deeper 0x2222/23 bindery/property/admin subfunction coverage, SDK 0x2222/90 scope, or another user-selected endpoint family.

Patch workflow

  • Produce patches that apply with exactly:

    git am patchname.patch
    
  • Assume the user has already applied and committed accepted earlier patches. Build every new patch against the current tree the user provides.

  • Do not ask the user to apply a long patch chain unless they explicitly say earlier patches were not committed.

  • Keep follow-up patches small and reviewable. Do not mix functional changes, cleanup, and logging refactors unless the user asks for that.

  • If a patch is only documentation or test cleanup, keep it that way.

Current protocol audit scope

  • The current endpoint documentation/audit pass is scoped to compatibility NCPs through NetWare 3.x by default, including NetWare 1.x/2.x legacy calls where they are documented. Bucket endpoints by the oldest NetWare generation that documents them: put 1.x/2.x legacy calls in their own sections, keep the remaining through-3.x compatibility calls in the 3.x/default section, and put endpoints introduced in NetWare 4.x in a separate planning/stub section. Do not create stub work merely for NetWare 5.x/OES/MOAB/newer endpoints.
  • NetWare 4.x-only endpoints are not part of the default implementation target yet, but they are the current forward-planning target. Already implemented compatibility code must not be removed or wrapped just because it is 4.x-era; only new, not-yet-implemented 4.x stubs should be placed behind #if MARS_NWE_4. Do not add disabled stubs for 5.x/OES/MOAB/newer calls unless the user explicitly changes the target scope later. MARS_NWE_4 is currently hard-disabled in include/config.h.cmake and should stay 0 unless the user explicitly asks to start that work.
  • When a 0x2222 group or subfunction is forwarded out of nwconn.c, follow the handoff before declaring the endpoint documented. nwconn.c should document the handoff and the exact header/payload bytes that are preserved or rewritten before forwarding; the destination file (for example nwbind.c) must document the concrete subfunction request/reply layout at the real handler. Do not stop at a comment such as nwbind must do prehandling, nwbind must do the rest, or handled by nwbind.
  • For forwarded paths, document any nwconn-side payload mutation as part of the audit. Examples in the current tree include queue create path expansion, queue job file-handle insertion, quota bindery prehandling, and semaphore/message group forwarding. If a forwarded subfunction is not audited yet, record it as a target-file follow-up rather than only documenting the nwconn dispatcher.
  • For documentation-only endpoint patches, do not change parser offsets, byte order, reply layout, or completion behavior. Always compare the code parser/reply layout against the applicable SDK/WebSDK/PDF request format and, when available, the uploaded SDK include prototypes. If the code differs from the SDK layout, document the concrete difference inline and mirror it in TODO.md for later testing. If it matches, say so in the patch summary so the audit trail is clear.
  • When an SDK/WebSDK/PDF endpoint number is written in decimal notation, convert it carefully to the wire case value before adding inline documentation. Example: Directory Services 0x2222/22/12 in the PDF means SubFunctionCode decimal 12, i.e. wire case 0x0c; it is not the existing case 0x12 / decimal 18 Allocate Permanent Directory Handle. Place disabled stubs directly at the correct numeric slot inside the dispatcher, never appended at the end of the function. For implemented endpoints, keep the detailed documentation inside the relevant case block, immediately after the case label/opening brace, matching the local style; do not leave a large endpoint block before the case label.
  • If a PDF/WebSDK page title and an internal table row disagree, prefer the endpoint title plus include/WebSDK cross-checks and record the mismatch instead of inventing a new wire case. Example: 0x2222/23 Verify Serialization is titled SDK decimal 23/12 / wire 0x0c, even though one PDF table row prints SubFunctionCode (212); do not add a wire 0xd4 case without a packet trace or include-level confirmation.
  • In TODO.md and endpoint summaries, avoid ambiguous mixed notation for grouped subfunctions. Write SDK/PDF numbers as decimal and include the wire byte explicitly when it differs or could be confused, for example SDK 22/18 / wire 0x12 or SDK 22/12 / wire 0x0c. Do not write 22/12 for a wire case 0x12 unless the SDK number is actually decimal 12.
  • Do not assume every 0x2222 endpoint key is only request_type/function/subfunction. Some SDK/PDF/WebSDK families have deeper selectors inside the subfunction payload, such as NDS 0x2222/104/02 with a 32-bit NDS Verb, statistical 0x2222/123/34 with InfoLevelNumber, NCP extension 0x2222/36/37 with dynamic extension numbers, or reply layouts selected by an information type. When auditing such a family, document the selector path explicitly, for example 0x2222/104/02 verb=<n> or 0x2222/123/34 level=<n>, and distinguish true wire dispatch bytes from payload fields that merely select a structure or backend operation.
  • Keep TODO.md endpoint audit notes grouped by endpoint family and NetWare generation instead of as one long flat list.
  • Before starting the next detailed endpoint block, maintain a coverage index for SDK/WebSDK-listed 0x2222 groups that are not yet audited. Classify each group as present in code but not audited, missing a top-level handler, or likely later-generation/unclear. This index is only a planning aid: do not add active TODO work or source stubs until the specific block has been checked for handoffs and bucketed by oldest documented NetWare generation.
  • Before every new endpoint-family patch, first do a missing-endpoint pass for that family: enumerate the SDK/PDF/WebSDK/include endpoint list, compare it against actual case labels and forwarded destination handlers, then document implemented, disabled-stub, and absent slots separately. Do this retroactively for already documented families when touching them again.
  • Always document both the request handoff/parser and the reply builder. For forwarded calls, the nwconn.c comment should explain exactly why return(-1) or return(-2) is used; the destination handler should explain the concrete request bytes and response payload. Do not treat return(-1) inside disabled #if 0 snippets in nwbind.c as a forwarding mechanism.
  • For SDK-listed groups that appear missing from nwconn.c, also search destination files such as nwbind.c, queue helpers, salvage helpers, AFP/name-space dispatchers, and any prehandler path before declaring the endpoint absent.
  • The rejected 0152-docs-note-message-control-subfunction.patch must not be applied: it documented 0x2222/21/0x0c Connection Message Control, which is outside the default NetWare 1.x/2.x/3.x MARS-NWE target scope.

mars-nwe coding style rules

  • Prefer existing mars_nwe / NetWare functions over new helper code.
  • Before adding a helper, search the tree for an existing equivalent.
  • Do not introduce parallel mechanisms for paths, trustees, xattrs, AFP metadata, copy/write/restore, u16/u32 packing, or logging.
  • Use existing integer and wire-format macros such as GET_16, GET_32, U16_TO_16, U32_TO_32, and related mars_nwe helpers instead of open-coded byte parsing/serialization.
  • Use existing namespace/path conversion and basehandle logic instead of parsing NetWare paths by hand.
  • For file restore/copy/write behavior, prefer the existing Novell/mars_nwe file functions over direct POSIX operations. Use POSIX only where there is no suitable internal mechanism, and keep it clearly isolated.
  • Do not add a new trustee or xattr database. Salvage JSON is a snapshot; real restore should feed existing mars_nwe trustee/xattr/AFP mechanisms.

NCP path and hidden repository notes

  • Normal NCP path resolution intentionally treats Unix dot path components as hidden/special. In the classic path resolver (build_dir_name() in connect.c), a component beginning with . is accepted only for ./.. semantics; a component such as .recycle or .salvage returns invalid path (0x899c).
  • nwattrib.c also marks Unix dot files/directories hidden by default when no explicit NetWare attributes are stored.
  • Therefore .recycle and .salvage are backend repositories, not user-visible NCP paths. Tests must not expect SYS:.recycle/... or SYS:.salvage/... to open through ordinary NCP file calls.
  • Use the official salvage endpoints (87/16 scan, 87/17 recover, 87/18 purge, and old 22/27-22/29) to observe or operate on salvage entries. Verify recovered payload content by reading the restored live file through NCP, not by opening backend repository paths through NCP.

Salvage endpoint rules

  • NCP 0x2222 / 87 / 16 is decimal 87/16, implemented as function 0x57, subfunction 0x10.
  • NCP 0x2222 / 87 / 17 is decimal 87/17, function 0x57, subfunction 0x11.
  • NCP 0x2222 / 87 / 18 is decimal 87/18, function 0x57, subfunction 0x12.
  • Legacy salvage endpoints are old function 22 decimal / 0x16: 22/27 scan, 22/28 recover, and 22/29 purge. They should remain thin adapters over the same shared salvage backend, not a second implementation.
  • Keep 0x57 subfunction dispatch in handle_func_0x57() / namespace code, not as a second subfunction switch in nwconn.c.
  • Old 0x16 calls need a minimal bridge in namespace code because short directory handles must be resolved through existing build_base() / dir_base[] internals before reaching the shared backend.
  • Versioned backend payload names follow Samba vfs_recycle literally: Copy #1 of NAME, Copy #2 of NAME, ... . Do not localize this string and do not run it through gettext; the NCP scan reply still reports the original deleted filename for every version.
  • Versioned salvage entries may have different .recycle/.salvage names but 87/16 returns the original deleted filename for every version. Do not match recover/purge by display name alone.
  • Scan must treat .salvage JSON as a sidecar for the matching .recycle payload. If an external tool such as Samba or an administrator removes the payload, 87/16 must not return the stale sidecar and should remove the JSON. The server log should contain a greppable line like WARN SALVAGE 87/16 STALE ... for this cleanup.
  • Scan, recover, and purge should share the same scan/sequence/basehandle view so that a sequence returned by scan identifies the exact sidecar used later.
  • The combined salvage smoke suite now covers NCP write/read payloads, 87/18 purge pre-clean, hidden backend repository behavior, stale sidecar cleanup with a manual payload-removal pause, three version captures, and recovering the oldest version via sequence 0.
  • Append salvage endpoint tests to tests/salvage/salvage_smoke_suite.sh rather than creating unrelated top-level scripts, unless a helper binary is needed and then started by the suite.

AFP 0x13 deleted-file info notes

  • AFP 0x13 Get Macintosh Info On Deleted File is NCP 0x2222 / 35 / 19 (wire subfunction byte 0x13). The Micro Focus / Novell WebSDK request is VolumeNumber plus DOSDirectoryNumber; the reply is FinderInfo[32], ProDOSInfo[6], ResourceForkSize, FileNameLen, FileName.
  • Implement it only as an adapter over the shared mars_nwe salvage/deleted-entry record. Do not expose or normally open .recycle or .salvage through AFP code; those remain hidden backend repositories.
  • The implementation returns FinderInfo[32], ProDOSInfo[6], resource fork size, and deleted original name from the Salvage JSON snapshot. FinderInfo and ProDOSInfo are captured through the existing nwatalk xattr-backed AFP metadata store, not through a parallel AFP metadata database.
  • The AFP smoke suite has a dedicated afp_deleted_info_smoke helper. It pre-cleans salvage entries in the tested directory through NCP purge, creates a temporary AFP file, writes FinderInfo and ProDOSInfo, deletes it, verifies AFP 0x13, and purges the tested deleted entry afterwards.
  • Verified AFP smoke status: the full suite completed with failures=0 after AFP 35/19 and ProDOSInfo work. It verifies live FinderInfo and ProDOSInfo xattrs on SYS:PUBLIC/pmdflts.ini, verifies AFP 35/19 returns prodos=010203040506 from the deleted-file Salvage snapshot, and leaves normal AFP-only attributes absent when Hidden/System/Archive map through the NetWare attribute path.
  • Reuse existing AFP/nwatalk metadata mechanisms for FinderInfo, AFP attributes, entry ids, resource fork state, and related restore/lookup behavior. Do not add a parallel AFP metadata database.

Logging rules

Desired future server log format:

<LVL4> <AREA> <DEC-CODE> <EVENT> key=value ...
  • LVL4 is exactly four characters: INFO, DBUG, WARN, ERRR.

  • AREA examples: NCP, SALVAGE, AFP, MAP, BIND, TRUST, AUTH, CONN, FILE, QUEUE.

  • The front code should be human/protocol decimal where applicable, for example 87/16, 87/17, 87/18.

  • Exact wire values should still be logged later as key/value hex fields, for example fn=0x57 sub=0x10 seq=0x00000000 base=0x00000004 result=0x89ff.

  • Unknown or unimplemented endpoints should be easy to grep, for example:

    INFO NCP 87/18 UNKNOWN fn=0x57 sub=0x12 msg="not implemented"
    INFO NCP 87/255 UNKNOWN fn=0x57 sub=0xff msg="unknown subfunction"
    INFO NCP 136 UNKNOWN fn=0x88 msg="unknown function"
    
  • Do not invent a parallel logger casually. Reuse existing mars_nwe logging functions/macros and normalize message format gradually.

Build and test notes

Dependencies used during local checks in this conversation:

  • gdbm-1.26.tar.gz
  • Linux-PAM-1.7.2.tar.xz for PAM headers; link against system PAM if present
  • ncpfs-master.zip for the salvage smoke helper client build
  • yyjson under third_party/yyjson

If CMake finds GDBM but a target still cannot see gdbm.h, pass include paths explicitly for local verification, for example:

CFLAGS="-I/path/to/gdbm/include -I/path/to/Linux-PAM-1.7.2/libpam/include" \
cmake -S . -B build
cmake --build build --target nwconn ncp_salvage_scan_smoke ncp_salvage_recover_smoke

Useful quick checks:

bash -n tests/salvage/salvage_smoke_suite.sh
cc -DLINUX -fsyntax-only -Iinclude -Isrc -Ithird_party/yyjson/src src/nwsalvage.c src/namspace.c

When server-side code or smoke helper clients change, rebuild both the server and the helper targets so the runtime test is not using stale binaries:

cmake --build build --target nwserv ncpserv
cmake --build build --target \
  ncp_delete_smoke \
  ncp_read_smoke \
  ncp_salvage_scan_smoke \
  ncp_salvage_recover_smoke \
  ncp_salvage_purge_smoke \
  afp_entry_id_smoke \
  afp_file_info_smoke \
  afp_scan_info_smoke \
  afp_set_file_info_smoke \
  afp_deleted_info_smoke

Runtime smoke suites:

tests/salvage/salvage_smoke_suite.sh --out /tmp/mars-salvage-report.txt
tests/afp/afp_smoke_suite.sh --out /tmp/mars-afp-smoke.txt

The suite streams the report to --out while running, so a failure before the end should still leave useful output. It has a manual stale-payload pause: the script prints a sudo rm -f .../.recycle/... command; remove that payload in a second shell and press Enter. The next scan should remove the stale sidecar and grep /var/log/mars_nwe/nw.log for WARN SALVAGE 87/16 STALE.

Normal NCP reads of .recycle or .salvage are expected to fail with invalid path. Verify payload data through the visible live file after NCP write or recover, using ncp_read_smoke. Treat the final summary (failures=0, ncp_warnings=0) as the important signal.

AFP ProDOSInfo storage

ProDOSInfo is AFP/NCP per-entry metadata. Store it in the existing nwatalk AFP metadata layer, not in nwarchive/nwxattr directly and not in a parallel DB. The xattr key is user.org.mars-nwe.afp.prodos-info via the mars_nwe xattr wrapper name org.mars-nwe.afp.prodos-info; it is a raw 6-byte value, analogous to FinderInfo's 32-byte org.mars-nwe.afp.finder-info.

Salvage captures this as prodos_info_hex (12 hex characters) beside finder_info_hex. AFP 35/19 Get Macintosh Info On Deleted File returns FinderInfo[32] followed by ProDOSInfo[6] from the Salvage snapshot. The verified smoke value is 010203040506 and the Linux xattr dump should show:

user.org.mars-nwe.afp.prodos-info=0x010203040506

Latest endpoint audit checkpoint

As of patch 0212-docs-audit-namespace-lock-salvage-stubs.patch, the latest audited endpoint block is the Name Space lock/quota/search/salvage-rights subset of NCP 0x2222/87 / wire 0x57 in src/namspace.c. nwconn.c still forwards requestdata starting at the Name Space SubFunction byte to handle_func_0x57(), and the handler return convention remains unchanged: non-negative values are reply payload lengths, negative values are Completion codes.

The previous 87/16..87/29 block contains active source cases for:

  • 87/16 Scan Salvageable Files;
  • 87/17 Recover Salvageable File;
  • 87/18 Purge Salvageable File;
  • 87/20 Search for File or Subdirectory Set;
  • 87/21 Get Path String from Short Directory Handle;
  • 87/22 Generate Directory Base and Volume Number;
  • 87/24 Get Name Spaces Loaded List from Volume Number;
  • 87/26 Get Huge NS Information;
  • 87/28 Get Full Path String;
  • 87/29 Get Effective Directory Rights.

Disabled source stubs exist for eligible 3.x/4.x metadata gaps from that range:

  • 87/19 Get NS Information;
  • 87/23 Query NS Information Format;
  • 87/25 Set NS Information;
  • 87/27 Get Name Space Directory Entry.

Patch 0212 added the next set of disabled source stubs for eligible 1.x/2.x/3.x and planned-4.x namespace/file gaps that were missing from the active switch range:

  • 87/36 Log File;
  • 87/37 Release File;
  • 87/38 Clear File;
  • 87/39 Get Directory Disk Space Restriction;
  • 87/40 Search for File or Subdirectory Set (Extended Errors);
  • 87/41 Scan Salvageable File List;
  • 87/42 Purge Salvageable File List;
  • 87/43 Revoke File Handle Rights.

These stubs are under #if 0, document selector path/request/reply/provider intent, and do not change runtime behavior. 87/44 Update File Handle Rights is NetWare 5.x in the NDK material and was not stubbed under the current scope. The existing 87/26 source slot is still effectively unimplemented and returns the default 0xfb completion.

The next endpoint block can continue with 87/64..87/69, the matching 89 long-name-space family, or another unaudited top-level family such as AFP 0x2222/35, packet burst 0x2222/97/101, or deeper 0x2222/23 bindery/property/admin subfunction coverage, unless the user requests a specific family first.

The next patch number should follow the latest applied patch; after patch 0223, use 0224.

Retro source-stub checkpoint from patch 0207:

  • Already documented eligible gaps in Directory Services 22/12, 22/35, and 22/36 have disabled source stubs at the correct src/nwconn.c dispatch slots. Do not rewrite those stubs unless implementing the endpoint.
  • Already documented File Server Environment 23 queue/server-management gaps have disabled source stubs at the appropriate src/nwbind.c switch slots. Some pre-existing disabled stubs still contain legacy placeholder control flow; leave existing stubs alone unless implementing or explicitly cleaning that exact block.
  • Message 21/04..21/08 were not SDK/PDF server endpoints in the default audit set, so no stubs are required. Message 21/12 is later-generation only and remains prose-only/out-of-scope under the current rules.
  • Physical-record 26..31 plus 110, TTS 34/00..34/10, and direct file 59, 61..77 do not have additional eligible missing slots in the audited ranges; no new source stubs were needed.
  • Future retro-audits must distinguish three cases: add a disabled source stub for an eligible missing endpoint, leave an already-present stub unchanged and only document that it exists, or keep non-endpoints / 5.x+ endpoints out of source.

Remember: for every new endpoint-audit patch, also update this AI handoff file with the latest audited block and expected next patch number. Put detailed Coverage/Request/Reply/Known-difference notes inline at each endpoint case rather than as one large audit block before the switch range.

Missing-endpoint rule: when an audited SDK/PDF/WebSDK/Header endpoint is not implemented but belongs to the compatibility scope, document it at the appropriate dispatch location as a disabled #if 0 stub instead of only mentioning it in prose. The compatibility scope for stubs is NetWare 1.x/2.x legacy calls, NetWare 3.x/default compatibility calls, and explicitly planned NetWare 4.x/NDS work. Do not add stubs merely for NetWare 5.x/OES/MOAB/newer endpoints: those are outside the current target unless the user explicitly asks for that later generation. A 3.x-compatible server should remain compatible with documented 1.x/2.x calls, and the current forward plan is only through 4.x. Disabled stubs should include selector path, name, request/reply sketch, provider/out-of-scope reason, and no active behavior change. Disabled stubs must not use misleading control flow such as return(-1) where that return value has no local handoff meaning.

Latest endpoint audit checkpoint from patch 0223:

  • Direct NCP 0x2222/111 / wire 0x6f Semaphore is now source-stub-audited in src/nwconn.c. There is no active top-level handler for this newer NetWare 3.x/4.x semaphore family.
  • Patch 0223 records disabled #if 0 selector slots for 111/00 Open/Create a Semaphore, 111/01 Examine Semaphore, 111/02 Wait On (P) Semaphore, 111/03 Signal (V) Semaphore, and 111/04 Close Semaphore.
  • The old 32/xx semaphore implementation in src/sema.c remains the active compatibility path. Future work should bridge both families through one semaphore provider/state table and verify the documented Lo-Hi handle order against existing MARS-NWE big-endian handle helpers before changing behavior.
  • This block is local synchronization, not nwnds/directory work.

Next patch number should be 0224.

Latest endpoint audit checkpoint from patch 0224:

  • SDK 0x2222/90 / wire 0x5a Data Migration / parse-tree / compression metadata is now source-stub-audited as planned NetWare-4.x filesystem and namespace work. There was no active top-level handler in src/nwconn.c.
  • Patch 0224 records the selector map behind MARS_NWE_4: 90/00 Parse Tree, 90/10 Get Reference Count from Dir Entry Number, 90/11 Get Reference Count from Dir Handle, 90/12 Set Compressed File Size, 90/128 Move File Data To DM, 90/129 DM File Information, 90/130 Volume DM Status, 90/131 Migrator Status Info, 90/132 DM Support Module Information, 90/133 Move File Data From DM, 90/134 Get/Set Default Read-Write Support Module ID, 90/135 DM Support Module Capacity Request, 90/136 RTDM Request, and 90/150 File Migration Request.
  • The future owner is the filesystem/namespace provider, not nwnds. There is no active Data Migration support module, parse-tree engine, compressed file-size backend, or RTDM provider yet. Keep this as unsupported 0xfb unless the filesystem provider grows real backing state.

Next patch number should be 0225.

Latest endpoint audit checkpoint from patch 0225:

  • SDK 0x2222/92 / wire 0x5c SecretStore is now scope-audited as later-generation and out of the current source-stub target. The NDK PDF marks SecretStore Services as NetWare Server 5.x and eDirectory 8.5 or later, with subverbs 0 Query Server through 9 Get Service Information.
  • No active top-level case 0x5c exists in src/nwconn.c, and no indirect handler/provider path was found during this audit. Do not add a disabled source stub for SecretStore while the target remains 1.x/2.x/3.x plus planned 4.x only.
  • SecretStore is not the same as the planned 4.x libdirectory/nwnds work. If a future post-4.x/eDirectory target is ever added, it should be designed as a separate secure secret-storage provider with strict no-secret logging rules.

Next patch number should be 0226.