Files
mars-nwe/TODO.md
Mario Fetka ee2271c099
All checks were successful
Source release / source-package (push) Successful in 48s
tests: record AFP namespace entry id smoke success
2026-05-30 20:22:44 +02:00

580 lines
31 KiB
Markdown

# 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.
### AFP Set File Information timestamp coverage
Current status:
- AFP Set File Information (`0x09`) and AFP 2.0 Set File Information (`0x10`)
now accept the file modification timestamp bitmap (`0x0010`) for path-backed
file requests.
- Timestamp writes are routed through the existing NetWare `nw_utime_node()`
helper so trustee Modify rights and the established Unix `utime(2)` fallback
behavior are reused instead of inventing AFP-specific timestamp handling.
- The Linux smoke helper verifies the AFP date/time fields via the follow-up
Get File Information response, and the smoke suite also records `stat -c %Y`
for the backing Unix file.
Follow-up:
- Add directory timestamp handling once the shared AFP path/object resolver grows
directory-specific Set File Information semantics.
- Keep create/access/backup timestamp writes disabled until their exact AFP to
NetWare/Unix metadata mapping is deliberately wired and tested.
- Keep Delete/Rename/Create/Remove for later patches that can reuse the existing
NetWare server helpers and trustee checks.
### 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. Entry IDs are now derived first from
existing mars_nwe NetWare namespace/basehandle state rather than from a
parallel AFP/stat fallback generator. Linux smoke coverage exists in
`tests/linux/afp_entry_id_smoke`; the latest full-suite run against
`SYS:PUBLIC/pmdflts.ini` returned `entry_id=0x00000004`.
- `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`; the identity source follows the
same NetWare namespace/basehandle path as Entry ID From Path Name.
- `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 now expose NetWare namespace/basehandle-derived Entry IDs. The
latest full-suite run against `SYS:PUBLIC` returned
`next_last_seen=0x00000004` and `entry_id=0x00000004` for the first scanned
record while preserving the expected file metadata.
- `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`. The latest
full-suite run verified `SYS:PUBLIC/pmdflts.ini`, returning volume 0,
`fork=0`, and the same NetWare namespace/basehandle-derived
`entry_id=0x00000004` as the path-backed lookup.
- `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`. The smoke suite
now also asserts that write-open requests fail with completion `0x84` and
resource-fork opens fail with completion `0x9c`, keeping the current
unsupported cases explicit until AppleDouble/resource-fork, AFP write-open,
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 Set File Information` (`0x09`) and `AFP 2.0 Set File Information`
(`0x10`) are implemented only for path-backed file metadata smoke writes:
the FinderInfo bitmap (`0x0020`) and the AFP
Attributes bitmap (`0x0001`) restricted to AFP Hidden, System, and
Archive. Archive is mapped to the existing NetWare `FILE_ATTR_A` attribute
path, while Hidden and System remain mars_nwe AFP metadata xattr bits. 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 AFP-only Hidden/System bits in
`org.mars-nwe.afp.attributes`, maps Archive through the existing NetWare
attribute store, and verifies the result through AFP 2.0 Get File Information. The smoke-suite report helper now includes AFP 2.0 FinderInfo, legacy AFP `0x09` FinderInfo, AFP 2.0 Hidden/System/Archive set/clear probes,
and legacy AFP `0x09` Invisible set/clear probes, and has green
`failures=0` runs for `SYS:PUBLIC/pmdflts.ini`; the latest run was from the
build-tree copy of `afp_smoke_suite.sh` after the CMake sync fix and confirms
legacy `0x09` FinderInfo plus legacy `0x09` Invisible set/clear in the same
report as AFP 2.0 `0x10`. It confirms the corrected FinderInfo payload
alignment by reading
`user.org.mars-nwe.afp.finder-info=0x544558544d415253...` (`TEXTMARS` with no
leading padding byte), confirms attribute set/clear via the versioned
attributes xattr ending clean when AFP-only bits are present. Current
Entry IDs are derived from the mars_nwe NetWare namespace/basehandle path and
only cached in `org.mars-nwe.afp.entry-id` as AFP compatibility metadata when
that write is permitted; an xattr cache write failure is non-fatal because
the namespace handle remains the source of truth.
System remains on the narrow AFP xattr-only attribute path, while Archive is
routed through the existing NetWare attribute path; runtime probes verified
System set/clear and Archive set/clear with AFP-visible attrs `0x0004`,
`0x0000`, and `0x0040`, with server diagnostics showing the matching WebSDK
SETCLR forms `0x8004`, `0x0004`, `0x8040`, and `0x0040`. A post-fix
full-suite run against the rebuilt server completed with `failures=0` and the
final `user.org.mars-nwe.afp.attributes=0x01000000`, confirming that Archive
is no longer duplicated in the AFP metadata xattr after Clear Archive. The smoke
helper verifies the targeted attribute bit by mask instead of comparing the
full AFP attribute word, because other stored metadata bits such as System may legitimately remain set while
another bit is being tested, and Archive may be supplied by the NetWare
attribute store. The earlier
smoke-helper `--backup` spelling is only kept as an alias; new docs and the
suite use Archive to avoid confusing this AFP attribute with the separate
backup date/time fields. 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.<domain>.*`
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.<domain>.*`
names to the portable `user.org.mars-nwe.<domain>.*` 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`.
- AFP Get DOS Name From Entry ID (0x12) is implemented as a conservative
read-only reverse lookup that first uses the existing mars_nwe
`map_directory_number_to_path()` namespace/basehandle path. The old
`nwatalk_get_entry_id()` volume scan remains only as a legacy fallback for
cached AFP IDs. The latest smoke run confirmed `entry_id=0x00000004`
resolving to `PUBLIC/PMDFLTS.INI`.
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.
- AFP Entry IDs now prefer the existing mars_nwe NetWare namespace/basehandle
mapping before consulting cached AFP metadata or the old fallback path. A
future libatalk/CNID backend may still provide Apple-native identity, but AFP
must not grow a second mars_nwe object-id resolver in parallel to the existing
namespace machinery.
- The full smoke suite verifies namespace-derived identity end to end:
Entry ID From Path Name, Entry ID From NetWare Handle, Get File Information,
Scan File Information, Set File Information verification, and Get DOS Name
From Entry ID all returned or consumed `entry_id=0x00000004` for the sample
`SYS:PUBLIC/pmdflts.ini` path, with `failures=0`. 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 Hidden/System/Archive AFP attributes now have
deliberately narrow write paths through AFP Set File Information `0x09` and
AFP 2.0 Set File Information `0x10`; 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.
### AFP implementation convergence plan
Current status:
- The AFP/NWAFP work is now broad enough that future endpoint patches should
treat AFP as an Apple-facing adapter over the existing mars_nwe NetWare
server machinery rather than as a parallel file server implementation.
- The safe baseline already includes path-backed Entry ID, Get/Scan File
Information, temporary directory handles, read-only data-fork Open File
Fork, narrow Set File Information metadata writes, NetWare-backed Archive
attribute mapping, Modify timestamp writes through `nw_utime_node()`, and
a conservative Get DOS Name From Entry ID reverse lookup.
- The Get DOS Name From Entry ID helper now returns the canonical DOS namespace
spelling from the existing mars_nwe `namedos.c` alias builder. The follow-up
smoke run confirms `PUBLIC/PMDFLTS.INI` for `SYS:PUBLIC/pmdflts.ini`, replacing
the earlier raw Unix/realcase `public/pmdflts.ini` result.
Design rule:
- AFP request handlers should parse the WebSDK/NWAFP request, resolve volume,
path, directory handle, or entry id to an existing mars_nwe object, call the
established NetWare helper, and translate the result into the AFP reply
layout.
- Do not introduce direct `open(2)`, `unlink(2)`, `rename(2)`, `mkdir(2)`,
`utime(2)`, attribute, trustee, or directory-scan logic inside AFP handlers
when a mars_nwe helper or wrapper already exists.
- Only keep AFP-specific storage for metadata that has no NetWare equivalent,
such as FinderInfo, AFP Entry IDs/CNIDs, and narrowly scoped AFP-only
attributes that are deliberately not mapped to NetWare attributes yet.
Refactor/wrapper follow-up:
- Continue reusing the existing mars_nwe volume, namespace, basehandle, and
directory-handle helpers for AFP object lookup. Do not add an AFP-local
object resolver where `conn_get_kpl_unxname()`, `nw_vol_inode_to_handle()`,
`map_directory_number_to_path()`, or related namespace helpers already cover
the case.
- Route all AFP writes through existing mars_nwe policy checks before changing
metadata. Archive and Modify timestamp already do this through NetWare
helpers. FinderInfo and AFP-only Hidden/System xattr writes are now gated
by the same trustee/effective-rights Modify policy before the AFP metadata
xattrs are updated.
- Continue moving AFP-visible NetWare attributes onto the existing NetWare
attribute store. Hidden, System, and Archive are mapped to `FILE_ATTR_H`, `FILE_ATTR_S`, and `FILE_ATTR_A`; ReadOnly,
ExecuteOnly, and Shareable still need either a real mapping
through existing attribute helpers or an explicit unsupported result.
- Extend Set File Information timestamps only through existing mars_nwe helpers:
Modify is routed through `nw_utime_node()`, Access through the existing
`st_atime`/`utime()` path, and Create/Backup through the existing
`nwarchive.c` metadata helpers.
- Normalize Get/Scan File Information so each field comes from the existing
mars_nwe source of truth where possible: NetWare attributes, file size,
timestamps, owner information, archive date/time, FinderInfo, resource-fork
size, and Entry ID/CNID metadata. AccessPrivileges are now derived from
`tru_get_eff_rights()` instead of static AFP masks and have readonly smoke
coverage under a temporary `[RF]` trustee assignment.
- Revisit Scan File Information after the resolver work and prefer mars_nwe's
existing directory/search machinery over the current AFP-local directory walk
for search attributes, namespace filtering, and multi-record replies.
- The current Get DOS Name From Entry ID path first uses the existing
`map_directory_number_to_path()` namespace/basehandle lookup and only falls
back to the legacy AFP metadata volume walk when necessary. Future CNID work
should plug into that same resolver order rather than reintroducing a
parallel path database.
AFP Set File Information metadata-rights convergence:
- AFP FinderInfo writes and AFP-only Hidden/System attribute xattr writes no
longer bypass NetWare policy just because their storage is AFP-specific.
`afp_set_file_information()` now checks the resolved file through the existing
trustee/effective-rights Modify policy before writing `org.mars-nwe.afp.*`
metadata.
- Archive continues to route through the NetWare attribute helper (`FILE_ATTR_A`),
and Modify timestamp continues to route through `nw_utime_node()`. The new
check only covers metadata that has to remain AFP-specific, keeping AFP as an
Apple-facing adapter over mars_nwe policy rather than a parallel file server.
- The Linux AFP smoke suite now has optional negative coverage for this policy
gate. With `--readonly-user NOPASSUSER --readonly-no-password`, the suite can
run FinderInfo, Hidden, and System writes as a user that is expected to lack
Modify rights and assert completion `0x8c`. With `--prepare-readonly-rights`,
the suite uses the existing ncpfs `nwgrant`/`nwrevoke` trustee utilities to
grant only read/file-scan rights (`[RF]` by default) before the negative probe
and revoke the explicit trustee assignment afterwards.
- Runtime status: the negative smoke has been verified with `NOPASSUSER` as a
no-password test user. The suite temporarily granted `[RF]` on
`SYS:PUBLIC/pmdflts.ini`, confirmed FinderInfo, Hidden, and System Set
File Information requests are rejected with completion `0x8c`, and then
successfully revoked the temporary trustee assignment. The same run ended
with `failures=0`, preserved the final `TEXT/MARS` FinderInfo xattr, kept
`org.mars-nwe.afp.attributes` clear after the attribute cleanup probes, and
left the Modify timestamp at the expected smoke value.
Endpoint order:
- First finish the non-destructive convergence work above.
- Then implement AFP Create File (`0x02`) and AFP 2.0 Create File (`0x15`) by
routing through the existing NetWare create/open path and testing only
explicit temporary smoke files with cleanup.
- Then implement AFP Create Directory (`0x01`) and AFP 2.0 Create Directory
(`0x14`) through the existing NetWare directory-create helper, again only on
temporary smoke paths.
- Then implement AFP Rename (`0x07`) through the existing NetWare rename/move
path, preserving FinderInfo/xattrs and checking Entry ID behavior.
- Keep AFP Delete (`0x03`) and Get Macintosh Info On Deleted File (`0x13`) for
last. Delete must only be enabled through the existing NetWare delete/erase
policy path and smoke-tested on self-created temporary files.
## 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.
### AFP attribute convergence correction
AFP Set/Get File Information attribute handling must follow the WebSDK attribute
word rather than the earlier low-bit smoke placeholders. The documented SetInfo
request bitmap uses `0x0100` for Attributes, `0x1000` for Modify Date/Time, and
`0x4000` for FinderInfo. The returned/set Attributes word uses `0x0200`
Hidden, `0x0400` System, and `0x2000` Archive. These are mapped through the
existing NetWare attribute store (`FILE_ATTR_H`, `FILE_ATTR_S`, `FILE_ATTR_A`)
so AFP does not keep parallel xattr-only copies for those NetWare attributes.
`--invisible` remains only a smoke-helper compatibility alias for Hidden.
Runtime status: the WebSDK attribute-bit smoke run is verified with `failures=0`.
The suite confirmed `Hidden` set/clear as `0x0200`/`0x0000`, `System`
set/clear as `0x0400`/`0x0000`, and `Archive` set/clear as
`0x2000`/`0x0000`. The same run confirmed the WebSDK SetInfo bitmaps
`0x0100` for Attributes, `0x1000` for Modify Date/Time, and `0x4000` for
FinderInfo. Because all tested attribute bits are now stored through the
NetWare attribute path, `user.org.mars-nwe.afp.attributes` may be absent in the
final xattr dump; this is expected and no longer counts as a smoke failure.
### AFP Backup Date/Time convergence
AFP Set File Information now treats the WebSDK `0x2000` request bitmap as the
Backup Date/Time field, distinct from the `0x2000` Archive attribute bit inside
the Attributes word. The timestamp payload is routed through the existing
`mars_nwe_set_archive_info()` helper in `nwarchive.c`, so the data is stored in
`org.mars-nwe.netware.archive` together with the NetWare archive date/time
metadata rather than in an AFP-specific xattr. AFP Get/Scan File Information
merge the stored archive date/time back into the 120-byte AFP information record.
This keeps the split explicit: Archive as an attribute is `FILE_ATTR_A` in the
NetWare attribute store; Backup Date/Time is archive metadata in
`nwarchive.c`; FinderInfo remains AFP metadata in `org.mars-nwe.afp.finder-info`.
The Linux smoke suite covers `--backup-time-only --backup-time-epoch` and dumps
`user.org.mars-nwe.netware.archive` so runtime reports show the underlying
mars_nwe storage path.
Runtime status: the Backup Date/Time smoke run is verified with `failures=0`.
The suite confirmed `AFP Set File Information Backup Timestamp` using bitmap
`0x2000` and reported `backup=0x576eb9aa` for epoch `1700000000`. The same
run confirmed the backing mars_nwe metadata xattr:
`user.org.mars-nwe.netware.archive=0x01036e57aab900000000`. That confirms the
intended split: Archive as a file attribute stays on the NetWare attribute path,
while Backup Date/Time is stored by `nwarchive.c`.
### AFP Create and Access Date/Time convergence
AFP Set File Information now accepts the WebSDK `0x0800` Create Date/Time
request bitmap and routes the payload through the existing
`mars_nwe_set_file_info()` helper in `nwarchive.c`. AFP Get/Scan File
Information read the same `mars_nwe_get_file_info()` metadata and fall back to
the historical Unix timestamp source when no NetWare file-info metadata is
stored. The backing xattr is `user.org.mars-nwe.netware.fileinfo`; no
AFP-specific xattr is introduced for this NetWare-semantic field.
AFP Set File Information also accepts the WebSDK `0x0400` Access Date/Time
request bitmap. Access timestamps are routed through the existing POSIX
`st_atime`/`utime()` path, preserving `st_mtime` and enforcing trustee Modify
rights before updating the file. This keeps Access Date/Time out of
`nwarchive.c` and out of AFP-only xattrs, matching the existing mars_nwe
NetWare file-info model.
Runtime status: the combined AFP timestamp smoke run is verified with
`failures=0`. The suite confirmed `AFP Set File Information Access Timestamp`
using bitmap `0x0400` and `AFP Set File Information Create Timestamp` using
bitmap `0x0800`, both for epoch `1700000000` with the returned AFP date
`0x576e`. The same run confirmed the Create Date/Time backing metadata xattr
`user.org.mars-nwe.netware.fileinfo=0x01036e57aab90000000000000000`, while
Access Date/Time remained on the normal file `atime` path and did not create an
AFP metadata xattr.
AFP Get/Scan AccessPrivileges convergence:
- AFP Get File Information and AFP Scan File Information now use the same
trustee/effective-rights source when filling the WebSDK AccessPrivileges
word. The old static file/directory masks have been replaced with mapping
from `tru_get_eff_rights()` to Read, Write, Open, Create, Delete, Parental,
Search, and Modify File Status Flags.
- File-level readonly attributes still suppress write/delete style AFP
privileges for file replies, while directories expose directory-appropriate
parental/search/status bits based on the effective trustee rights.
- Runtime status: the AFP smoke suite verified the mapping with
`--readonly-user NOPASSUSER --readonly-no-password --prepare-readonly-rights`.
The suite granted `[RF]` on `SYS:PUBLIC/pmdflts.ini`, confirmed the readonly
Get File Information probe reported `rights=0x0500`, checked that Read was
set and Write/Modify Status were clear, then revoked the temporary trustee
assignment. The same run ended with `failures=0`.