fix(lib): ini_set n'écrase plus app.ini si awk échoue, insertion avant les lignes vides
Deux corrections dans ini_set() suite à la review de #24 : - Le mv s'exécutait même si awk avait échoué en cours de route (OOM, signal, valeur exotique) : $tmp, créé par la redirection avant qu'awk ne tourne, pouvait être tronqué ou vide et venait quand même écraser le fichier original. mv est maintenant gaté sur le code de retour d'awk : en cas d'échec, $tmp est supprimé, une erreur est logguée, et la fonction retourne 1 sans toucher au fichier d'origine. - L'insertion d'une clé juste avant l'en-tête de section suivante atterrissait après la ou les lignes vides de fin de section plutôt qu'avant, rendant le fichier plus difficile à lire au fil des appels répétés. Les lignes vides rencontrées section active/clé pas encore trouvée sont désormais bufferisées et réémises juste après la clé insérée (ou en fin de fichier si la section n'est jamais refermée), sans toucher à l'ordre dans tous les autres cas.
This commit is contained in:
+35
-5
@@ -159,12 +159,27 @@ ini_set() {
|
||||
chmod "$(stat -c '%a' "$file")" "$tmp" 2>/dev/null || true
|
||||
chown "$(stat -c '%u:%g' "$file")" "$tmp" 2>/dev/null || true
|
||||
|
||||
awk -v section="$section" -v key="$key" -v value="$value" '
|
||||
# awk writes into $tmp regardless of its own exit status — a mid-stream
|
||||
# death (OOM, signal, an exotic value tripping the regex) would still
|
||||
# leave a truncated-but-nonempty $tmp for `mv` to install over $file.
|
||||
# Gate the mv on awk's exit code so a failure leaves the original config
|
||||
# untouched instead of silently destroying it.
|
||||
if ! awk -v section="$section" -v key="$key" -v value="$value" '
|
||||
# Blank lines are buffered rather than printed immediately while a
|
||||
# section is still awaiting insertion: without this, a key inserted
|
||||
# right before the next section header lands *after* that section'"'"'s
|
||||
# trailing blank line(s) instead of before them. Flushed as soon as
|
||||
# either a non-blank line or the insertion itself happens, so this
|
||||
# never reorders anything except relative to that pending insertion.
|
||||
function flush_blanks() {
|
||||
while (blank_count > 0) { print ""; blank_count-- }
|
||||
}
|
||||
/^\[.*\]$/ {
|
||||
if (in_section && !done) {
|
||||
printf "%s = %s\n", key, value
|
||||
done = 1
|
||||
}
|
||||
flush_blanks()
|
||||
cur = $0
|
||||
gsub(/^\[|\]$/, "", cur)
|
||||
in_section = (cur == section)
|
||||
@@ -173,9 +188,19 @@ ini_set() {
|
||||
next
|
||||
}
|
||||
{
|
||||
if (in_section && !done && match($0, "^[ \t]*" key "[ \t]*=")) {
|
||||
printf "%s = %s\n", key, value
|
||||
done = 1
|
||||
if (in_section && !done) {
|
||||
if (match($0, "^[ \t]*" key "[ \t]*=")) {
|
||||
flush_blanks()
|
||||
printf "%s = %s\n", key, value
|
||||
done = 1
|
||||
next
|
||||
}
|
||||
if ($0 ~ /^[ \t]*$/) {
|
||||
blank_count++
|
||||
next
|
||||
}
|
||||
flush_blanks()
|
||||
print
|
||||
next
|
||||
}
|
||||
print
|
||||
@@ -185,13 +210,18 @@ ini_set() {
|
||||
printf "%s = %s\n", key, value
|
||||
done = 1
|
||||
}
|
||||
flush_blanks()
|
||||
if (!section_found) {
|
||||
if (NR > 0) print ""
|
||||
printf "[%s]\n", section
|
||||
printf "%s = %s\n", key, value
|
||||
}
|
||||
}
|
||||
' "$file" > "$tmp"
|
||||
' "$file" > "$tmp"; then
|
||||
rm -f "$tmp"
|
||||
log_error "ini_set: awk failed on ${file} (${section}.${key}), config left untouched."
|
||||
return 1
|
||||
fi
|
||||
|
||||
mv "$tmp" "$file"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user