Opennet Firmware
uci.sh
gehe zur Dokumentation dieser Datei
1 ## @defgroup uci UCI
2 ## @brief Hilfreiche Funktionen zum lesenden und schreibenden Zugriff auf die UCI-basierte Konfiguration.
3 # Beginn der Doku-Gruppe
4 ## @{
5 
6 
7 uci_is_true() {
8  uci_is_false "$1" && trap "" EXIT && return 1
9  return 0
10 }
11 
12 
13 uci_is_false() {
14  local token="$1"
15  # synchron halten mit "uci_to_bool" (lua-Module)
16  if [ "$token" = "0" ] || [ "$token" = "no" ] || [ "$token" = "n" ] \
17  || [ "$token" = "off" ] || [ "$token" = "false" ]; then
18  return 0
19  else
20  trap "" EXIT && return 1
21  fi
22 }
23 
24 
25 # "uci -q get ..." endet mit einem Fehlercode falls das Objekt nicht existiert
26 # Dies erschwert bei strikter Fehlerpruefung (set -e) die Abfrage von uci-Werten.
27 # Die Funktion "uci_get" liefert bei fehlenden Objekten einen leeren String zurueck
28 # oder den gegebenen Standardwert zurueck.
29 # Der Exitcode signalisiert immer Erfolg.
30 # Syntax:
31 # uci_get firewall.zone_free.masq 1
32 # Der abschließende Standardwert (zweiter Parameter) ist optional.
33 uci_get() {
34  trap 'error_trap uci_get "$*"' EXIT
35  local key="$1"
36  local default="${2:-}"
37  if uci -q get "$key"; then
38  return 0
39  else
40  [ -n "$default" ] && echo "$default"
41  return 0
42  fi
43 }
44 
45 
46 ## @fn uci_add_list()
47 ## @brief Füge einen neuen Wert zu einer UCI-Liste hinzu und achte dabei auf Einmaligkeit.
48 ## @param uci_path Der UCI-Pfad des Listenelements.
49 ## @param new_item Der neue Wert, der zur Liste hinzugefügt werden soll.
50 ## @details Die Funktion ist vergleichbar mit "uci add_list". Es werden jedoch keine doppelten Einträge erzeugt.
51 ## Somit entfällt die Prüfung auf Vorhandensein des Eintrags.
52 uci_add_list() {
53  trap 'error_trap uci_add_list "$*"' EXIT
54  local uci_path="$1"
55  local new_item="$2"
56  local index
57  # ist der Eintrag bereits vorhanden?
58  uci_is_in_list "$uci_path" "$new_item" && return 0
59  uci add_list "$uci_path=$new_item"
60 }
61 
62 
63 ## @fn uci_get_list()
64 ## @brief Liefere alle einzelnen Elemente einer UCI-Liste zurück.
65 ## @param uci_path Der UCI-Pfad eines Elements.
66 ## @returns Die Einträge sind zeilenweise voneinander getrennt.
67 uci_get_list() {
68  trap 'error_trap uci_get_list "$*"' EXIT
69  local uci_path="$1"
70  # falls es den Schlüssel nicht gibt, liefert "uci show" eine Fehlermeldung und Müll - das wollen wir abfangen
71  [ -z "$(uci_get "$uci_path")" ] && return 0
72  # ansonsten: via "uci show" mit speziellem Trenner abfragen und zeilenweise separieren
73  uci -q -d "_=_=_=_=_" show "$uci_path" | cut -f 2- -d = | sed 's/_=_=_=_=_/\n/g' | sed "s/^'"'\(.*\)'"'"'$/\1/'
74 }
75 
76 
77 ## @fn uci_get_list_index()
78 ## @brief Ermittle die ID eines UCI-Listenelements.
79 ## @param uci_path Der UCI-Pfad der Liste.
80 ## @param value Der Inhalt des zu suchenden Elements.
81 ## @returns Die ID des Listenelements (beginnend bei Null) wird zurückgeliefert.
82 ## @details Falls das Element nicht gefunden wird, ist das Ergebnis leer.
84  trap 'error_trap uci_get_list_index "$*"' EXIT
85  local uci_path="$1"
86  local value="$2"
87  local current
88  local index=0
89  for current in $(uci_get_list "$uci_path"); do
90  [ "$current" = "$value" ] && echo "$index" && break
91  index=$((index + 1))
92  done
93 }
94 
95 
96 ## @fn uci_is_in_list()
97 ## @param uci_path Der UCI-Pfad der Liste.
98 ## @param item Das zu suchende Element.
99 ## @brief Prüfe ob ein Element in einer Liste vorkommt.
100 uci_is_in_list() {
101  trap 'error_trap uci_is_in_list "$*"' EXIT
102  local uci_path="$1"
103  local value="$2"
104  [ -n "$(uci_get_list_index "$uci_path" "$value")" ] && return 0
105  trap "" EXIT && return 1
106 }
107 
108 
109 ## @fn uci_delete_list()
110 ## @brief Lösche ein Element einer UCI-Liste
111 ## @param uci_path Der UCI-Pfad der Liste.
112 ## @param value Der Inhalt des zu löschenden Elements. Es findet ein Vergleich auf Identität (kein Muster) statt.
113 ## @details Falls das Element nicht existiert, endet die Funktion stillschweigend ohne Fehlermeldung.
114 uci_delete_list() {
115  trap 'error_trap uci_delete_list "$*"' EXIT
116  local uci_path="$1"
117  local value="$2"
118  local index
119  index=$(uci_get_list_index "$uci_path" "$value")
120  [ -n "$index" ] && uci_delete "${uci_path}=${index}"
121  return 0
122 }
123 
124 
125 ## @fn uci_replace_list()
126 ## @brief Replace the items in a list. Wanted items are expected via stdin (one per line).
127 ## @param uci_path The path of the UCI list.
128 ## @details This function is idempotent. Thus it takes care to avoid unnecessary changes (e.g. an
129 ## existing list being replaced with all of its current members). This works around UCI's
130 ## behaviour of not detecting (and discarding) no-change-operations. The list is removed if no
131 ## items were supplied. Some processes may rely on the avoidance of unnecessary changes.
133  local uci_path="$1"
134  local current_list_items
135  local wanted_list_items
136  current_list_items=$(uci_get_list "$uci_path" | sort)
137  wanted_list_items=$(sort)
138  if [ "$current_list_items" != "$wanted_list_items" ]; then
139  uci_delete "$uci_path"
140  echo "$wanted_list_items" | while read -r item; do
141  uci_add_list "$uci_path" "$item"
142  done
143  fi
144 }
145 
146 
147 ## @fn uci_delete()
148 ## @brief Lösche ein UCI-Element.
149 ## @param uci_path Der UCI-Pfad des Elements.
150 ## @details Keine Fehlermeldung, falls das Element nicht existiert.
151 uci_delete() {
152  local uci_path="$1"
153  uci -q delete "$uci_path" || true
154 }
155 
156 
157 # Finde eine uci-Sektion mit gewuenschten Eigenschaften.
158 # Dies ist hilfreich beim Auffinden von olsrd.@LoadPlugin, sowie firewall-Zonen und aehnlichem.
159 # Parameter config: Name der uci-config-Datei
160 # Parameter stype: Typ der Sektion (z.B. "zone" oder "LoadPlugin")
161 # Parameter Bedingugen:
162 find_all_uci_sections() {
163  _find_uci_sections 0 "$@"
164 }
165 
166 
167 # Ermittle den ersten Treffer einer uci-Sektionssuche (siehe find_all_uci_sections)
168 find_first_uci_section() {
169  _find_uci_sections 1 "$@"
170 }
171 
172 
173 ## @fn filter_uci_show_value_quotes()
174 ## @brief Entferne fuehrende und abschliessende Quotes um die Werte der "uci show"-Ausgabe herum.
175 ## @details Seit Chaos Calmer liefert 'uci show' die Werte (nach dem "=") mit Single-Quotes zurück.
176 ## Dies ist schön für die Splittung von Listen, aber nervig für unsere Bedingungsprüfung.
177 ## Wir entfernen die Quotes daher.
178 ## @attention Das Ergebnis ist fuer die Verarbeitung von Listen-Elemente unbrauchbar, da diese separiert
179 ## von Quotes umgeben sind.
181  sed 's/^\([^=]\+\)='"'"'\(.*\)'"'"'$/\1=\2/'
182 }
183 
184 
185 # Aus Performance-Gruenden brechen wir frueh ab, falls die gewuenschte Anzahl an Ergebnissen erreicht ist.
186 # Die meisten Anfragen suchen nur einen Treffer ("find_first_uci_section") - daher koennen wir hier viel Zeit sparen.
187 _find_uci_sections() {
188  trap 'error_trap _find_uci_sections "$*"' EXIT
189  local max_num="$1"
190  local config="$2"
191  local stype="$3"
192  shift 3
193  local counter=0
194  local section
195  local condition
196  # Der Cache beschleunigt den Vorgang wesentlich.
197  uci_cache=$(uci -X -q show "$config" | filter_uci_show_value_quotes)
198  for section in $(echo "$uci_cache" | grep "^$config"'\.[^.]\+='"$stype$" | cut -f 1 -d = | cut -f 2 -d .); do
199  for condition in "$@"; do
200  # diese Sektion ueberspringen, falls eine der Bedingungen fehlschlaegt
201  echo "$uci_cache" | grep -q "^$config"'\.'"$section"'\.'"$condition$" || continue 2
202  done
203  # alle Bedingungen trafen zu
204  echo "$config.$section"
205  counter=$((counter + 1))
206  [ "$max_num" != 0 ] && [ "$counter" -ge "$max_num" ] && break
207  true
208  done | sort
209 }
210 
211 
212 # Erzeuge die notwendigen on-core-Einstellungen fuer uci, falls sie noch nicht existieren.
213 # Jede Funktion, die im on-core-Namensraum Einstellungen schreiben moechte, moege diese
214 # Funktion zuvor aufrufen.
215 prepare_on_uci_settings() {
216  trap 'error_trap prepare_on_uci_settings "$*"' EXIT
217  local section
218  # on-core-Konfiguration erzeugen, falls noetig
219  [ -e /etc/config/on-core ] || touch /etc/config/on-core
220  # shellcheck disable=SC2043
221  for section in settings; do
222  uci show | grep -q '^on-core\.'"${section}"'\.' || uci set "on-core.${section}=$section"
223  done
224 }
225 
226 
227 ## @fn create_uci_section_if_missing
228 ## @brief Prüfe, ob eine definierte UCI-Sektion existiert und lege sie andernfalls an.
229 ## @returns Sektion wurde angelegt (True) oder war bereits vorhanden (false).
231  trap 'error_trap create_uci_section_if_missing "$*"' EXIT
232  local config="$1"
233  local stype="$2"
234  local key_value
235  local uci_prefix
236  shift 2
237  # liefere "falsch" zurück (Sektion war bereits vorhanden)
238  [ -n "$(find_first_uci_section "$config" "$stype" "$@")" ] && { trap "" EXIT; return 1; }
239  # uci-Sektion fehlt -> anlegen
240  uci_prefix="$config.$(uci add "$config" "$stype")"
241  for key_value in "$@"; do
242  uci set "$uci_prefix.$key_value"
243  done
244  # liefere "wahr" zurück (Sektion wurde angelegt)
245  return 0
246 }
247 
248 # Ende der Doku-Gruppe
249 ## @}
uci_get_list_index(uci_path, value)
Ermittle die ID eines UCI-Listenelements.
Definition: uci.sh:22
uci_delete(uci_path)
Lösche ein UCI-Element.
Definition: uci.sh:46
uci_is_in_list(uci_path, item)
Prüfe ob ein Element in einer Liste vorkommt.
Definition: uci.sh:27
while read r key value
Definition: core.sh:85
uci_add_list(uci_path, new_item)
Füge einen neuen Wert zu einer UCI-Liste hinzu und achte dabei auf Einmaligkeit.
Definition: uci.sh:10
uci_replace_list()
Replace the items in a list. Wanted items are expected via stdin (one per line, uci_path).
Definition: uci.sh:41
create_uci_section_if_missing()
Prüfe, ob eine definierte UCI-Sektion existiert und lege sie andernfalls an.
Definition: uci.sh:58
local key
Definition: core.sh:85
uci_delete_list(uci_path, value)
Lösche ein Element einer UCI-Liste.
Definition: uci.sh:33
uci_get_list(uci_path)
Liefere alle einzelnen Elemente einer UCI-Liste zurück.
Definition: uci.sh:15
set eu on function print_services services log for dir in etc on services d var on services volatile d
Definition: services:13
filter_uci_show_value_quotes()
Entferne fuehrende und abschliessende Quotes um die Werte der "uci show"-Ausgabe herum.
Definition: uci.sh:54
shift
Definition: core.sh:85
done
Definition: core.sh:85
do echo n $value
Definition: core.sh:85