# TODO This file collects follow-up work that is known but intentionally not part of the current patches. It is meant for project-level items that are too broad or too low-priority to keep as inline source TODO comments. ## Server / NCP compatibility ### Console privilege model Current status: - `NCP 23/200 Check Console Privileges` is implemented as a protocol-compatible status check. - For now, console privileges are mapped to the existing supervisor-equivalence state computed for the connection. - Callers with supervisor equivalence get success; other callers get `0xc6` (`No Console Rights`). Follow-up: - Add a real console-operator privilege model instead of treating console rights as identical to supervisor equivalence. - Decide where the console privilege map should live: - a bindery property, - a server configuration option, - or a small explicit internal list similar to queue operator handling. - Check how NetWare 3.x tools such as `PCONSOLE`, `SYSCON`, and console utilities expect console operators to be represented. - Keep `NCP 23/200` as a completion-code-only endpoint; only the privilege source should change. ### Queue spool path case handling Current status: - Queue job paths can still be rebuilt from DOS/bindery path spelling such as `SYS:SYSTEM/EPSON.QDR`. - On a case-sensitive Unix filesystem this can differ from the existing directory, for example `system/epson.qdr`. Follow-up: - Resolve queue job file paths case-insensitively in the queue connection/path resolver, or use the queue object's already-resolved Unix spool directory instead of rebuilding it from the DOS path. - Avoid creating duplicate directories that differ only by case. ### NCP 17/4C test coverage Current status: - `NCP 17/4C List Relations of an Object` is implemented server-side. - Existing DOS and Linux tools do not reliably trigger it for all useful set properties such as `GROUP_MEMBERS` and `GROUPS_I'M_IN`. Follow-up: - Add a small direct test utility to `mars-dosutils` / `NWTESTS` that sends `NCP 17/4C` directly. - Suggested test cases: - `TESTGRP1` type `0x0002`, property `GROUP_MEMBERS` - `TESTGRP2` type `0x0002`, property `GROUP_MEMBERS` - `MARIO` type `0x0001`, property `GROUPS_I'M_IN` - `NOPASSUSER` type `0x0001`, property `GROUPS_I'M_IN` - `GUEST` type `0x0001`, property `GROUPS_I'M_IN` ### NCP endpoint SDK documentation / stub audit Current status: - Several legacy NCP endpoints in `src/nwconn.c` are implemented only as disabled stubs, explicit `0xfb` unsupported replies, or success/no-op dummies. - The known candidates now have inline SDK-context comments so future work can start from the documented wire semantics instead of from guesswork. Follow-up: - Implement or deliberately reject remaining endpoint gaps after client evidence or direct protocol tests. - Keep SDK details close to the corresponding endpoint in `nwconn.c`, and keep broader prioritization/status here in `TODO.md`. ### NCP endpoint audit tracking Current status: - `src/nwconn.c` contains a mix of implemented, forwarded, partial, dummy, and intentionally unsupported NCP endpoints. - Endpoint comments should be aligned with the Novell SDK Web documentation, SDK headers, the Rust `nwserver` implementation, `lwared`, and the existing mars_nwe admin/Pascal code where those sources cover the same call. Follow-up: - Keep inline `TODO:` comments only where endpoint behavior is incomplete, approximate, intentionally dummy/no-op, or still needs SDK layout verification. - Mirror every real incomplete endpoint in this file so follow-up work remains visible outside the source code. - Do not treat every `return(-1)` in `nwconn.c` as incomplete: many of those paths intentionally forward bindery/global-server work to `nwbind`. ### NCP synchronization endpoint audit Current status: - The old NCP synchronization endpoint family in `src/nwconn.c` is now annotated with Novell SDK endpoint names. - The existing source already marked this area as not well tested, so the comments intentionally keep that compatibility warning visible. - `NCP 0x03`, `0x05`, `0x06`, `0x07`, `0x08`, `0x09`, `0x0a`, `0x0b`, `0x0d`, `0x0e`, `0x1a`, and `0x1e` have local implementations. Follow-up: - Verify the implemented file/logical-record/physical-record calls against the Novell SDK request/reply layouts and a real DOS requester or direct test caller. - Continue direct requester or NWTESTS coverage for the file, logical-record, and physical-record synchronization calls that are now wired. - Verify timeout and error-code behavior for set-oriented locking calls against a real requester, especially where MARS-NWE currently relies on the existing underlying share implementation. ### Extended volume information field mapping Current status: - `NCP 0x16/0x33 Get Extended Volume Information` returns the documented `NWVolExtendedInfo` reply and fills the core fields that can be derived from generic Unix filesystem statistics. - NetWare-specific fields that MARS-NWE does not currently model are returned as zero for now instead of guessed values. Follow-up: - Fill additional `NWVolExtendedInfo` fields when reliable data is available from the backing filesystem or from MARS-NWE metadata. - Candidate fields include suballocation, deleted-file/limbo accounting, compression counters, migration counters, EA counters, Directory Services object id, and last-modified timestamp data. - Treat compression-related fields as real follow-up work rather than permanent zeroes; populate them only when the backing filesystem exposes trustworthy compressed-file or compressed-block accounting. ### Object disk restriction fallback coverage Current status: - `NCP 0x16/0x29 Get Object Disk Usage And Restrictions` keeps the existing `QUOTA_SUPPORT` split. - With quota support enabled, the endpoint is routed through `nwbind` so the bindery Object ID can be mapped to a Unix uid before querying the quota backend. - Without quota support, the endpoint returns the SDK-compatible fallback: unrestricted (`0x40000000`) and no space in use. Follow-up: - Add direct tests for both build modes. - Verify the quota-enabled path against a real Unix quota setup. - Verify that the quota-disabled fallback remains compatible with requesters and with the WebSDK rule for invalid object IDs. ## Printing / Queue backend ### Q_UNIX_PRINT backend status Current status: - Queue metadata handling and the `Q_UNIX_PRINT` backend are intentionally separate. - The backend can already call `/usr/bin/lp`, `lpr`, or a custom script. Follow-up: - Improve logging around queue job submission to the Unix print command. - Capture and expose backend exit status where possible. - Consider direct CUPS integration only if MARS_NWE needs CUPS job IDs, cancellation, or status polling. Do not add a hard CUPS dependency for basic queue compatibility. ### Transaction Tracking System (TTS) Current status: - `NCP 0x22/0x00 TTS Is Available` reports the WebSDK-documented unavailable status. - MARS-NWE does not currently implement TTS rollback semantics, transaction files, transaction status tracking, or the begin/end/abort transaction state machine. - Other TTS subfunctions remain unsupported instead of pretending to succeed without real transaction tracking. Follow-up: - Implement TTS only if a concrete client requires it. - Treat this as a real transaction subsystem, not as a completion-code shim: the WebSDK TTS calls include begin/end/abort transaction, status, threshold, and control/statistics operations. ### AFP / Mac namespace backend Current status: - `NCP 0x23` still returns invalid namespace for AFP calls that are not implemented yet. - `AFP Get Entry ID From Path Name` is implemented when the optional Netatalk/libatalk backend is available. Linux smoke coverage exists in `tests/linux/afp_entry_id_smoke` and has been verified against `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST` with stat-derived fallback entry IDs. - `AFP Get Entry ID From Name` is implemented for the same path-backed smoke mode. Linux smoke coverage uses `tests/linux/afp_entry_id_smoke --from-name` and has been verified against `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST` with stat-derived fallback entry IDs. - `AFP Get File Information` is implemented for read-only path-based requests. Linux smoke coverage exists in `tests/linux/afp_file_info_smoke` and has been verified against `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST`. The same test verifies the AFP 2.0 Get File Information subfunction via `--afp20` against the same paths, using the same path-backed read-only reply for now. The current reply fills stat/libatalk-derived fields and leaves persistent CNID Parent ID / fuller Mac namespace metadata as future work. - `AFP Scan File Information` (`0x0a`) and `AFP 2.0 Scan File Information` (`0x11`) are implemented for path-backed read-only directory scans. Linux smoke coverage exists in `tests/linux/afp_scan_info_smoke`; the helper defaults to the AFP 2.0 subfunction and uses `--afp10` for the older endpoint. Runtime coverage has been verified against `SYS:PUBLIC` by walking multiple directory entries with the returned `next_last_seen` AFP Entry ID continuation value. The verified AFP 2.0 and older `0x0a` first records both return `pmdflts.ini` (`entry_id=0x23c8787d`, `data_len=8161`) on the sample tree, and an AFP 2.0 continuation with that Entry ID returns `ohlogscr.bat` (`entry_id=0x260437f6`, `data_len=1296`). - `AFP Get Entry ID From NetWare Handle` is implemented for read-only data-fork file handles that are opened in the same client connection. Linux smoke coverage uses `tests/linux/afp_entry_id_smoke --from-handle` and has been verified against `SYS:PUBLIC/pmdflts.ini` and `SYS:PUBLIC/ohlogscr.bat`, returning volume 0, `fork=0`, and stat-derived fallback Entry IDs for now. - `AFP Open File Fork` is implemented for the same path-backed smoke subset. Raw `VOL:`-style paths resolve the effective NetWare volume from the path prefix instead of assuming volume 0, so the same smoke path can cover `SYS:` and non-`SYS:` volumes. It opens only the data fork read-only and returns a normal six-byte NetWare file handle plus the current data-fork length; the Linux smoke helper `tests/linux/afp_open_file_fork_smoke` closes the returned handle in the same connection. Runtime smoke coverage is green for `SYS:PUBLIC/pmdflts.ini` (`fork_len=8161`) and `SYS:PUBLIC/ohlogscr.bat` (`fork_len=1296`) using `fork=0` and read access `0x01`. Resource-fork opens, write access, and Entry-ID-only lookup stay TODO until AppleDouble/resource-fork and persistent CNID/base-ID semantics are available. - `AFP Alloc Temporary Directory Handle` is implemented for the same path-backed smoke subset. Raw `VOL:`-style paths resolve the effective NetWare volume from the path prefix instead of assuming volume 0. Linux smoke coverage exists in `tests/linux/afp_temp_dir_handle_smoke`; runtime smoke coverage is green for `SYS:`, `SYS:PUBLIC`, `SYS:SYSTEM`, and `SYS:BURST`. The helper returns a temporary NetWare directory handle plus the AFP one-byte access-rights mask and immediately deallocates the handle in the same connection. Server diagnostics log the wider internal NetWare effective-rights mask, so privileged directories can show `rights=0x1ff` while the client prints `rights=0xff`. Entry-ID-only allocation remains TODO until persistent CNID/base-ID lookup exists. - `AFP 2.0 Set File Information` is implemented only for path-backed file metadata smoke writes: the FinderInfo bitmap (`0x0020`) and the AFP Attributes bitmap (`0x0001`) restricted to metadata-only file bits: Finder Invisible, System, and Backup. Linux smoke coverage exists in `tests/linux/afp_set_file_info_smoke`; runtime FinderInfo coverage is green for `SYS:PUBLIC/pmdflts.ini` with Finder type `TEXT` and creator `MARS`. The helper writes 32 bytes of FinderInfo to `org.mars-nwe.afp.finder-info`, stores the narrow attribute word in `org.mars-nwe.afp.attributes`, and verifies the result through AFP 2.0 Get File Information. The smoke-suite report helper now includes FinderInfo plus Invisible/System/Backup set/clear probes and has a green `failures=0` run for `SYS:PUBLIC/pmdflts.ini`; that run confirms the corrected FinderInfo payload alignment by reading `user.org.mars-nwe.afp.finder-info=0x544558544d415253...` (`TEXTMARS` with no leading padding byte), confirms Invisible set/clear via the versioned attributes xattr (`0x01000001` then `0x01000000`), and confirms the cached Entry ID xattr (`0x0100000033f9a1ed`). The first stat-derived AFP entry id for a path is now cached in the versioned `org.mars-nwe.afp.entry-id` xattr; a `fallback` marker on that first verification Get File Information diagnostic describes the entry-id origin, not the FinderInfo write result. Follow-up probes should read the cached mars_nwe entry id and omit the fallback marker. System and Backup are now supported by the same narrow xattr-only attribute path; runtime probes verified System set/clear and Backup set with AFP-visible attrs `0x0004`, `0x0000`, and `0x0040`, with server diagnostics showing the matching WebSDK SETCLR forms `0x8004`, `0x0004`, and `0x8040`. All other Set File Information bits and AFP attribute bits remain rejected until their write/enforcement semantics are explicitly designed. - The AFP dispatcher now decodes the WebSDK/NWAFP subfunction number in diagnostics so real client probes can be mapped to the corresponding AFP call before implementation work starts. - Optional build-time detection/linking for Netatalk/libatalk exists as a first local metadata backend hook. It is deliberately not an AFP protocol implementation yet. - Existing mars_nwe private xattr payloads use the `org.mars-nwe..*` namespace (`org.mars-nwe.netware.archive` and `org.mars-nwe.netware.fileinfo`) rather than the unreleased test-only `user.mars_nwe.*` names. There is no legacy read fallback because the old names never shipped outside local test systems. On Linux, mars_nwe's local xattr helper maps source-level `org.mars-nwe..*` names to the portable `user.org.mars-nwe..*` storage namespace, mirroring Netatalk's `org.netatalk.*` EA abstraction. - NetWare AFP calls are NCP entry points for Mac namespace semantics on a NetWare volume, not transport-level AFP proxy calls to `afpd`. Follow-up: - Implement the NetWare AFP NCP calls locally, using libatalk helpers rather than proxying requests to `afpd`. - Candidate libatalk pieces include the new AppleDouble/Finder Info/resource fork helper wrappers, plus future CNID/directory-id helpers, attribute mapping, and filename conversion. - Keep returning invalid namespace for AFP calls that still lack a real per-volume Mac namespace/AFP metadata layer. Do not return success for additional AFP calls without data/resource fork and Finder Info semantics. - Replace the compatibility stat-derived AFP entry-id generator with a real CNID/directory-id allocator once the libatalk/CNID backend is integrated. - mars_nwe-owned AFP entry ids are probed first from the versioned `org.mars-nwe.afp.entry-id` xattr before consulting Netatalk/libatalk AppleDouble/CNID metadata. If neither source has an id, mars_nwe derives the existing stat-compatible id and caches it in that xattr so subsequent probes can use persistent mars_nwe metadata. Linux smoke coverage confirms the versioned xattr payload shape, for example `0x010000007b9c42e1` for a cached `0x7b9c42e1` Entry ID. AFP directory-scan continuation remains directory iteration based: `last_seen` skips past the previously returned object, but the next returned Entry ID is not required to be numerically greater than the continuation token. FinderInfo plus the Finder Invisible/System/Backup AFP attributes now have deliberately narrow write paths through AFP 2.0 Set File Information; CNID allocation and broader AFP metadata writes still need a deliberate write-safe design. - Put additional future mars_nwe-owned AFP metadata under `org.mars-nwe.afp.*` (or a compact `org.mars-nwe.afp.metadata` record) and keep Netatalk-owned metadata under Netatalk's own `org.netatalk.*` keys. - Extend the Linux AFP smoke tests once additional AFP subfunctions are implemented, especially Finder Info updates, fork open/read/write paths, resource-fork handling, and broader directory-scan edge cases. ## Deferred / optional protocol work * Basic Packet Burst file transfer support is implemented and verified with a diagnostics-enabled DOS client test. * Packet Burst support is built by default, but runtime use remains controlled by `nwserv.conf`. * Packet Burst/NDS fragmentation support remains out of scope unless a concrete client requires it.