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:
@@ -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"]);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user