Route every conf writer through the guarded path

Eleven call sites wrote master.conf with tmp+rename and nothing else — no backup, no
parse check, no audit — including the two toggles the UI uses most and the raw editor
that installs a whole hand-edited file.
This commit is contained in:
Gmer4Lfe
2026-08-09 19:07:28 -04:00
parent d9f917ecef
commit 67eabdc17c
10 changed files with 174 additions and 121 deletions
+27 -22
View File
@@ -51,6 +51,7 @@
// Reads/writes HOST*_DOCKER_FOLDER_MAP in host*.conf (used by onboard scripts)
require_once __DIR__ . '/config.php';
require_once __DIR__ . '/confform.php';
define('VV_DOCKER_JSON', SCRIPTS_DIR . '/docker_folders.json');
define('VV_FV3_JSON', '/boot/config/plugins/folder.view3/docker.json');
@@ -344,17 +345,19 @@ function vv_dk_rename_folder(string $folderId, string $newName): array {
$data[$folderId]['name'] = $newName;
if (!vv_dk_write_json($data)) return ['ok' => false, 'error' => 'JSON write failed'];
// Update conf: replace old folder name with new name in the map
// Update conf: replace old folder name with new name in the map.
// The rebuild is a pure function of the current contents, so it runs inside vv_conf_edit()'s
// lock rather than against a copy read beforehand — there is no window to lose an edit in.
$currentHost = vv_detect_host();
$myId = strtoupper($currentHost);
$raw = vv_read_conf_raw($currentHost . '.conf');
$map = vv_dk_read_conf_map($raw, $myId);
foreach ($map as &$v) {
if ($v === $oldName) $v = $newName;
}
unset($v);
$updated = vv_dk_write_conf_map($raw, $myId, $map);
vv_write_conf_raw($currentHost . '.conf', $updated);
vv_conf_edit($currentHost . '.conf', function (string $raw) use ($myId, $oldName, $newName): string {
$map = vv_dk_read_conf_map($raw, $myId);
foreach ($map as &$v) {
if ($v === $oldName) $v = $newName;
}
unset($v);
return vv_dk_write_conf_map($raw, $myId, $map);
}, [], ["{$myId}_DOCKER_FOLDER_MAP"]);
return ['ok' => true];
}
@@ -367,14 +370,14 @@ function vv_dk_delete_folder(string $folderId): array {
unset($data[$folderId]);
if (!vv_dk_write_json($data)) return ['ok' => false, 'error' => 'JSON write failed'];
// Remove from conf map
// Remove from conf map — rebuilt inside the lock, see vv_dk_rename_folder() above.
$currentHost = vv_detect_host();
$myId = strtoupper($currentHost);
$raw = vv_read_conf_raw($currentHost . '.conf');
$map = vv_dk_read_conf_map($raw, $myId);
$map = array_filter($map, fn($v) => $v !== $folderName);
$updated = vv_dk_write_conf_map($raw, $myId, $map);
vv_write_conf_raw($currentHost . '.conf', $updated);
vv_conf_edit($currentHost . '.conf', function (string $raw) use ($myId, $folderName): string {
$map = vv_dk_read_conf_map($raw, $myId);
$map = array_filter($map, fn($v) => $v !== $folderName);
return vv_dk_write_conf_map($raw, $myId, $map);
}, [], ["{$myId}_DOCKER_FOLDER_MAP"]);
return ['ok' => true];
}
@@ -421,22 +424,24 @@ function vv_dk_sync_json_to_conf(): array {
$data = vv_dk_read_json();
$currentHost = vv_detect_host();
$myId = strtoupper($currentHost);
$raw = vv_read_conf_raw($currentHost . '.conf');
_vv_dk_sync_conf_from_json($data, $raw, $currentHost, $myId);
_vv_dk_sync_conf_from_json($data, $currentHost, $myId);
return ['ok' => true];
}
// Internal: rebuild conf map from current json state and write it
function _vv_dk_sync_conf_from_json(array $data, string $raw = '', string $host = '', string $id = ''): void {
// Internal: rebuild conf map from current json state and write it.
// The contents to splice into are read inside vv_conf_edit()'s lock. The caller used to be able
// to hand in a copy it had already read; that was only ever an optimisation, and passing a stale
// copy would have written the rest of the conf back as it looked before the lock was taken.
function _vv_dk_sync_conf_from_json(array $data, string $host = '', string $id = ''): void {
if (!$host) $host = vv_detect_host();
if (!$id) $id = strtoupper($host);
if (!$raw) $raw = vv_read_conf_raw($host . '.conf');
$map = [];
foreach ($data as $f) {
$name = $f['name'] ?? '';
foreach ($f['containers'] ?? [] as $c) $map[$c] = $name;
}
$updated = vv_dk_write_conf_map($raw, $id, $map);
vv_write_conf_raw($host . '.conf', $updated);
vv_conf_edit($host . '.conf', fn(string $raw): string => vv_dk_write_conf_map($raw, $id, $map),
[], ["{$id}_DOCKER_FOLDER_MAP"]);
}