salvage: drop stale sidecars when payload is missing

This commit is contained in:
ai
2026-06-01 08:03:13 +00:00
committed by Mario Fetka
parent 0c21cd07d8
commit 094f24224e
5 changed files with 48 additions and 18 deletions

7
AI.md
View File

@@ -71,9 +71,16 @@ use, the current project status that the user pasted into the chat.
`0x12`.
- Keep `0x57` subfunction dispatch in `handle_func_0x57()` / namespace code,
not as a second subfunction switch in `nwconn.c`.
- 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.
- 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.
- Append salvage endpoint tests to `tests/salvage/salvage_smoke_suite.sh` rather

21
TODO.md
View File

@@ -247,20 +247,21 @@ Current status:
- The runtime configuration uses low `nw.ini` sections `51-59`. Section `53`
maps Samba-style behaviour flags (`k`, `v`, `t`, `m`), and sections
`55-58` cover size filters, exclude, exclude_dir, and noversions lists.
- NCP delete, Samba-compatible history naming, and the initial `87/16` salvage
scan are covered by the combined smoke suite in `tests/salvage/`.
- NCP delete, Samba-compatible history naming, `87/16` scan, `87/17` recover,
and `87/18` purge are covered by the combined smoke suite in `tests/salvage/`.
- The legacy old salvage calls `22/27`, `22/28`, and `22/29` are adapters over
the same shared backend, not a second deleted-entry implementation.
- Samba-compatible history naming is the literal English `Copy #n of NAME`
format used by `vfs_recycle`; it is not localized.
- `NCP 0x2222 / 87 / 16` has a backend-backed scanner that reads `.salvage`
JSON entries and returns one salvageable entry per call.
JSON entries and returns one salvageable entry per call. Stale JSON sidecars
whose `.recycle` payload has disappeared are not returned and are removed by
the scan path.
Follow-up:
- Continue the normal NetWare salvage family on top of the shared backend:
- `NCP 0x2222 / 87 / 17` - Recover Salvageable File
- `NCP 0x2222 / 87 / 18` - Purge Salvageable File
- optional legacy `NCP 0x2222 / 22 / 27` - Scan Salvageable File (old)
- Append endpoint-level recover/purge checks to `tests/salvage/salvage_smoke_suite.sh`.
- Add cleanup coverage for stale `.salvage` JSON when the matching `.recycle`
payload has been manually removed.
- Add explicit endpoint coverage for stale `.salvage` cleanup after manually or
externally removing the matching `.recycle` payload.
### AFP / Mac namespace backend

View File

@@ -1853,6 +1853,7 @@ static int nwsalvage_scan_metadata_dir(const char *metadata_dir,
char metadata_path[NWSALVAGE_PATH_MAX];
char recycle_path[NWSALVAGE_PATH_MAX];
struct nwsalvage_metadata_entry entry;
struct stat st;
size_t len;
if (de->d_name[0] == '.')
@@ -1879,6 +1880,20 @@ static int nwsalvage_scan_metadata_dir(const char *metadata_dir,
entry.recycle_relative_path) < 0)
continue;
/*
* The .salvage JSON is only a sidecar for the real payload below
* .recycle. Samba, an administrator, or filesystem cleanup may remove
* the payload behind our back. Do not return such stale metadata from
* NCP 87/16 scans; remove the orphaned sidecar and keep scanning.
*/
if (stat(recycle_path, &st) < 0) {
if (errno == ENOENT)
(void)unlink(metadata_path);
continue;
}
if (!S_ISREG(st.st_mode))
continue;
memset(result, 0, sizeof(*result));
result->scan_sequence = *match_index;
result->scan_volume = (unsigned long)atoi(volume_name); /* overwritten below */

View File

@@ -19,15 +19,19 @@ The current salvage tests cover:
- local layout contract for `.recycle` payloads and `.salvage` JSON metadata,
- NCP create/delete capture through the normal server delete path,
- Samba-compatible history naming with `Copy #1 of NAME`,
- NCP `87/16` Scan Salvageable Files through the official `ncpfs` helper API,
- Samba-compatible, non-localized history naming with `Copy #1 of NAME`,
- NCP `87/16` scan, `87/17` recover, and `87/18` purge through the official
`ncpfs` helper API,
- stale `.salvage` sidecars are ignored and cleaned when their `.recycle`
payload is externally removed,
- report-file generation with `--out FILE`.
`tests/salvage/salvage_smoke_suite.sh` is the single NCP integration entry
point. It creates and deletes the same file twice, then appends the `87/16` scan check,
so one report covers delete capture, history/versioning, and scan visibility.
The scan check expects duplicate sequence entries for the original deleted name;
the `Copy #1 of ...` history path is validated through the JSON sidecars.
point. It creates multiple versions of the same file through NCP, deletes them
through NCP, scans salvageable entries, recovers the oldest sequence, and checks
the restored payload through NCP read. The scan check expects duplicate
sequence entries for the original deleted name; backend history paths stay
hidden behind the salvage endpoints.
The NCP smoke suite is intended to run as the same Unix user that normally runs
the test client, not necessarily as root. Pre-clean of old `.recycle` or

View File

@@ -87,7 +87,8 @@ SYS/.salvage/SUPERVISOR/PUBLIC/Copy #1 of SLVGCHK.TXT.json
If `v` is not enabled, or a file matches the `noversions` list, the old recycle
payload/metadata is replaced instead of creating a `Copy #x of ...` history
entry.
entry. The `Copy #n of ...` prefix is intentionally not localized; it follows
Samba `vfs_recycle` literally and should be stable across server locales.
## Layout smoke
@@ -99,7 +100,9 @@ require a running mars_nwe server and does not use NCP.
```
It verifies the basic `.recycle`/`.salvage` directory contract and stale JSON
detection.
detection. Runtime scans also treat `.salvage` JSON as a sidecar for the
matching `.recycle` payload: if the payload is removed externally, the entry
must disappear from `87/16` scan results and the stale JSON should be cleaned.
## NCP path visibility