Files
apLukov/roles/gekmihesg.openwrt/library/openwrt_lineinfile.sh
2024-10-30 01:50:38 +01:00

123 lines
3.5 KiB
Bash

#!/bin/sh
# Copyright (c) 2017 Markus Weippert
# GNU General Public License v3.0 (see https://www.gnu.org/licenses/gpl-3.0.txt)
PARAMS="
backrefs/bool//false
create/bool//false
insertafter/str
insertbefore/str
line=value/str
path=dest=destfile=name/str/r
regex=regexp/str
state/str//present
$FILE_PARAMS
"
RESPONSE_VARS=""
escape_slash() {
echo "$1" | sed -e 's|^/|\\/|;:a;s|\([^\]\(\\\\\)*\)/|\1\\/|g;ta;q'
}
escape_chars() {
echo "$1" | sed 's|['"${2:-}"'\]|\\&|g;q'
}
get_last_match() {
echo "$2" | sed -nre "/$1/=" | sed '$!d'
}
save_changes() {
[ -n "$_ansible_check_mode" -o -z "$CHANGED" ] ||
echo "$1" > "$path" 2>/dev/null ||
fail "path $path not writeable"
}
line_present() {
local index old new mode tmp
[ -f "$path" ] && {
old="$(cat "$path")" || fail "path $path not readable"
} || {
[ -n "$create" ] || fail "path $path does not exist"
[ -n "$_ansible_check_mode" ] ||
mkdir -p "$(dirname "$path")"
old=""
}
index="$(get_last_match "$line_match" "$old")"
[ -n "$index" ] && {
tmp="$(echo "$old" | sed -n "${index}{p;q}")"
[ -z "$backrefs" ] || line="$(echo "$tmp" |
sed -re "s/$line_match/$(escape_slash "$line")/")"
[ "$tmp" = "$line" ] || {
new="$(echo "$old" | sed "${index}c $(escape_chars "$line" |
sed 's|^\s|\\&|;q')")"
changed
}
} || [ -n "$backrefs" ] || {
[ -n "${insertafter#[EB]OF}" ] && {
index="$(get_last_match "$(escape_slash "$insertafter")" "$old")"
mode="a"
} || [ -z "${insertbefore#BOF}" ] || {
index="$(get_last_match "$(escape_slash "$insertbefore")" "$old")"
mode="i"
}
[ -n "$index" ] && {
new="$(echo "$old" | sed "$index$mode $(escape_chars "$line" |
sed 's|^\s|\\&|;q')")"
} || {
[ "$insertafter" = "BOF" -o "$insertbefore" = "BOF" ] &&
new="$line$N$old" || {
tmp="$(echo "$old" | sed '${/^$/d}')"
new="$tmp${tmp:+$N}$line"
}
}
changed
}
[ -z "$CHANGED" ] || {
[ -z "$_ansible_diff" ] || set_diff "$old" "$new" "$path" "$path"
[ -n "$_ansible_check_mode" ] || save_changes "$new"
}
}
line_absent() {
local index new old
[ -f "$path" ] || return 0
old="$(cat "$path")" || fail "path $path not readable"
index="$(get_last_match "$line_match" "$old")"
[ -z "$index" ] || {
new="$(echo "$old" | sed -re "/$line_match/d")"
changed
}
[ -z "$_ansible_diff" ] || set_diff "$old" "$new" "$path" "$path"
[ -n "$_ansible_check_mode" -o -z "$CHANGED" ] || save_changes "$new"
}
main() {
case "$state" in
absent|present) :;;
*) fail "state must be absent or present";;
esac
[ -n "$regex" ] &&
line_match="$(escape_slash "$regex")" ||
line_match="^$(escape_chars "$line" '/.[*^$()+?{|')\$"
[ ! -d "$file" ] || fail "path $path is a directory"
case "$state" in
present)
[ -z "$backrefs" -o -n "$regex" ] ||
fail "regexp is required with backrefs"
[ -n "$line" ] || fail "line is required with state present"
line_present;;
absent)
[ -n "$line" -o -n "$regex" ] ||
fail "line or regexp is required with state absent"
line_absent;;
esac
set_file_attributes "$path" "" "y"
}