Files
mars-nwe/tests/salvage

Salvage smoke tests

Status: finished for the current NetWare salvage compatibility slice.

This directory contains the shared mars_nwe NetWare salvage/deleted-entry tests and the single remaining salvage documentation file for this test group. The previous backend-design notes have been folded into this README so the salvage test directory has one Markdown entry point.

The backend is shared by the NetWare NCP salvage calls and AFP 0x13 Get Macintosh Info On Deleted Files. AFP must remain a thin adapter over this backend and must not grow a parallel deleted-file scanner.

Configuration covered by the tests

The active salvage configuration block is intentionally in a low nwserv.conf / nw.ini range:

51 1
52 .recycle .salvage
53 kv
54 0700 0700
55 0 0
56 -
57 -
58 -
59 -

Section meanings:

  • 51 enables or disables salvage.
  • 52 names the recycle payload repository and the salvage metadata repository.
  • 53 is a compact Samba vfs_recycle-style behaviour flag string:
    • k = keeptree,
    • v = versions,
    • t = touch,
    • m = touch_mtime.
  • 54 reserves directory/subdirectory modes for generated repositories.
  • 55 is minsize maxsize. Values may be raw bytes or case-insensitive kb, mb, or gb units.
  • 56 is the exclude pattern list. Matching files are deleted directly.
  • 57 is the exclude_dir pattern list. Matching directories bypass salvage.
  • 58 is the noversions pattern list. Matching files are recycled, but old recycle names are replaced instead of getting Copy #x of NAME history.
  • 59 is reserved for cleanup/history policy.

Repository layout and metadata

With keeptree enabled, a deleted SYS:PUBLIC/PMDFLTS.INI owned by SUPERVISOR is expected to produce:

SYS/.recycle/SUPERVISOR/PUBLIC/PMDFLTS.INI
SYS/.salvage/SUPERVISOR/PUBLIC/PMDFLTS.INI.json

The .recycle tree contains deleted payload files. The .salvage tree contains one JSON sidecar per deleted object. There is no large per-directory index file.

The sidecar JSON preserves the mars_nwe server metadata needed for exact recover, including NetWare archive/fileinfo xattrs, AFP metadata from nwatalk when present, inherited rights, explicit trustee object/right pairs, and the selected recycle/salvage relative paths. finder_info_hex is serialized as a fixed 32-byte AFP FinderInfo block encoded as 64 hex characters. If mars_nwe has no FinderInfo xattr for the deleted object, the JSON stores the all-zero 32-byte FinderInfo value.

Samba-compatible version naming

With the v flag enabled, mars_nwe follows Samba vfs_recycle naming on collision:

SYS/.recycle/SUPERVISOR/PUBLIC/SLVGCHK.TXT
SYS/.recycle/SUPERVISOR/PUBLIC/Copy #1 of SLVGCHK.TXT
SYS/.recycle/SUPERVISOR/PUBLIC/Copy #2 of SLVGCHK.TXT

The .salvage sidecar uses the same selected payload name plus .json:

SYS/.salvage/SUPERVISOR/PUBLIC/SLVGCHK.TXT.json
SYS/.salvage/SUPERVISOR/PUBLIC/Copy #1 of SLVGCHK.TXT.json

If versioning is disabled, or a file matches the noversions list, the previous recycled payload/metadata is replaced instead of creating a Copy #x of ... history entry. The Copy #n of ... prefix is intentionally not localized; it follows Samba vfs_recycle literally and should be stable across server locales.

NCP endpoint scope

The current NetWare 3.x salvage slice is implemented and covered by the smoke suite:

NCP 0x2222 / 87 / 16  Scan Salvageable Files
NCP 0x2222 / 87 / 17  Recover Salvageable File
NCP 0x2222 / 87 / 18  Purge Salvageable File
NCP 0x2222 / 22 / 27  Scan Salvageable Files (old bridge)
NCP 0x2222 / 22 / 28  Recover Salvageable File (old bridge)
NCP 0x2222 / 22 / 29  Purge Salvageable File (old bridge)

The old 22/* calls remain thin adapters over the same shared backend. Later NetWare 4.11+ list variants and UTF-8 extensions remain outside this slice:

NCP 0x2222 / 87 / 41  Scan Salvageable File List
NCP 0x2222 / 87 / 42  Purge Salvageable File List
NCP 0x2222 / 89 / 16  UTF-8 / extended Scan Salvageable Files

Stale metadata cleanup

Samba or an administrator may delete files from .recycle while .salvage metadata is still present. That is a real backend state, not a protocol error. Runtime scans treat each .salvage JSON file as a sidecar for the matching .recycle payload: if the payload is gone, 87/16 must not return the stale entry and should remove the JSON. The server log should contain a greppable line like:

WARN SALVAGE 87/16 STALE ...

NCP path visibility

.recycle and .salvage are backend repository directories. They are not ordinary user-visible NetWare paths. The classic mars_nwe path resolver treats leading-dot path components as special ./.. syntax and rejects names such as .recycle or .salvage with invalid path (0x899c). Dot files/directories are also hidden by default in the NetWare attribute layer.

Smoke tests therefore must not validate backend payloads by opening SYS:.recycle/... or SYS:.salvage/... through normal NCP file calls. The correct NCP-level checks are:

  • create/write/read the live file through NCP;
  • delete the live file through NCP;
  • use salvage scan 87/16 to confirm that a salvageable entry exists;
  • use recover 87/17 or purge 87/18 on the scan sequence;
  • read the restored live file through NCP to verify payload content.

Local filesystem layout tests may still inspect .recycle and .salvage directly when they intentionally test backend layout and run with suitable Unix permissions.

Local layout smoke

salvage_layout_smoke.sh is a local filesystem-only contract test. It does not require a running mars_nwe server and does not use NCP.

./tests/salvage/salvage_layout_smoke.sh

It verifies the basic .recycle/.salvage directory contract and stale JSON detection.

NCP smoke suite

salvage_smoke_suite.sh is the single integration entry point for the server-side delete hook, Samba-compatible history behaviour, scan, recover, purge, hidden repository behaviour, stale sidecar cleanup, and report-file generation.

Example:

./tests/salvage/salvage_smoke_suite.sh \
  -S MARS -U SUPERVISOR -P secret \
  --path SYS:PUBLIC/SLVGCHK.TXT \
  --unix-path /var/mars_nwe/SYS/public/SLVGCHK.TXT \
  --volume-root /var/mars_nwe/SYS \
  --out /tmp/mars-salvage-report.txt

The suite creates multiple versions of the same file through NCP, deletes them through NCP, scans salvageable entries, verifies duplicate sequence entries for the original deleted name, purges selected entries, recovers the oldest sequence, and checks the restored payload through NCP read. Backend history paths remain hidden behind the salvage endpoints.

The suite includes a manual stale-payload pause: it prints a sudo rm -f command for the backend .recycle payload, then waits for Enter. Remove that payload in a second shell and continue; the next scan should clean the stale sidecar and the log grep should find WARN SALVAGE 87/16 STALE.

Best-effort pre-clean of stale test artifacts may warn when existing .recycle or .salvage files are owned by the server user or root. Those warnings do not fail the smoke by themselves. For cleanest results, use a fresh test filename or run cleanup with the same Unix account that owns the mars_nwe volume files.

Completion status

The salvage test group is complete for the current compatibility slice. The combined suite now covers NCP write/read payloads, delete capture, versioned history naming, 87/16 scan, 87/17 recover, 87/18 purge, old 22/27 to 22/29 bridges, hidden backend repository behaviour, stale sidecar cleanup, and report-file generation.

Future salvage checks should be appended to salvage_smoke_suite.sh rather than creating unrelated top-level smoke scripts. New helper binaries are acceptable when the suite starts them directly.