User Tools

Site Tools



This shows you the differences between two versions of the page.

Link to this comparison view

Both sides previous revision Previous revision
Next revision
Previous revision
doc:techref:uci [2013/07/03 11:05]
doc:techref:uci [2016/02/04 15:19] (current)
karlp replace refs with
Line 1: Line 1:
 +====== UCI (Unified Configuration Interface) – Technical Reference ======
 +  * [[http://​​p=project/​uci.git;​a=summary|Project'​s git: UCI (Unified Configuration Interface) library and utility]]
 +  * UCI is available in OpenWrt since [[https://​​changeset/​10367|R10367 (trunk)]]
 +  * Use ''​git''​ on your local GNU/Linux installation to retrieve the source code:<​code bash>
 +git clone https://​​project/​uci.git
 +  * This is the Technical Reference. Please see **[[doc/​uci|UCI (Unified Configuration Interface) – Usage]]**
 +==== What is UCI? ====
 +''​UCI''​ is a small utility written in [[wp>C (programming language)|C]] (a [[wp>​shell script]]-wrapper is available as well) and is intended to //​centralize//​ the whole configuration of a device running OpenWrt. UCI is the successor of the NVRAM based configuration found in the historical OpenWrt branch [[about:​history|White Russian]] and a wrapper for the standard configuration files programs bring with them, like e.g. ''/​etc/​network/​interfaces'',​ ''/​etc/​exports'',​ ''/​etc/​dnsmasq.conf'',​ ''/​etc/​samba/​samba.conf''​ etc.
 +| {{:​meta:​icons:​tango:​dialog-information.png?​nolink}} | UCI configuration files are located ​ in the directory **''/​etc/​config/''​**\\ Their documentation can be accessed online in the OpenWrt-Wiki under [[doc:​uci|UCI configuration files]]. |
 +They can be altered with any text editor or with the command line utility program ''​uci''​ or through various programming APIs (like Shell, Lua and C). The WUI [[doc:​techref:​LuCI]] e.g. uses Lua to manipulate them.
 +==== Dependencies of UCI ====
 +  * ''​libuci''​ a small library for UCI written in [[wp>C (programming language)|C]]
 +    * ''​libuci-lua''​ is a libuci-plugin for [[wp>Lua (programming language)|Lua]] which is utilized by e.g. [[doc:​techref:​LuCI]]
 +Both are maintained in the same git as UCI.
 +===== Packages =====
 +The functionality is provided by the two packages ''​uci''​ and ''​libuci''​. The package ''​libuci-lua''​ is also available.
 +^ Name    ^ Size in Bytes ^ Description ^
 +| uci        |   7196 | Utility for the Unified Configuration Interface (UCI)    |
 +| libuci ​    ​| ​ 18765 | C library for the Unified Configuration Interface (UCI)  |
 +| libuci-lua |  ~6000 | libuci-plugin for [[wp>Lua (programming language)|Lua]],​ e.g. [[doc:​techref:​LuCI]] makes use of it  |
 +==== Installed Files ====
 +=== uci ===
 +^ path/​file ​                ^ file type ^ Description ​ ^
 +| /​sbin/​uci ​                ​| ​ binary ​       | uci executable ​ |
 +| /​lib/​config/​ ​       |  shell script ​ | Shell script compatibility wrappers for ''/​sbin/​uci'' ​ |
 +=== libuci ===
 +^ path/​file ​                 ^ file type ^ Description ​ ^
 +| /​lib/​ ​            ​| ​ symlink ​ | symlink to ​ |
 +| /​lib/​ ​ |  binary ​  | Library ​ |
 +=== libuci-lua ===
 +^ path/​file ​                 ^ file type ^ Description ​ ^
 +| /​usr/​lib/​lua/​ ​       |  binary ​ | Library ​ |
 +===== Lua Bindings for UCI =====
 +For those who like lua, UCI can be accessed in your code via the package libuci-lua. ​ Just install the package then, in your lua code do <code lua>​require("​uci"​)</​code>​
 +===== API =====
 +The api is quite simple
 +==== top level entry point ===
 +uci.cursor() ​ (that instantiates a uci context instance)
 +e.g. <code lua>x = uci.cursor()</​code>​ or <code lua>x = uci.cursor(nil,​ "/​var/​state"​)</​code>​
 +if you want to involve state vars
 +==== on that you can call the usual operations ====
 +<code lua>​x:​get("​config",​ "​sectionname",​ "​option"​)</​code>​
 +returns string or nil for not found
 +<code lua>​x:​set("​config",​ "​sectionname",​ "​option",​ "​value"​)</​code>​
 +sets simple string value
 +<code lua>​x:​set("​config",​ "​sectionname",​ "​option",​ { "​foo",​ "​bar"​ })</​code>​
 +sets list value
 +<code lua>​x:​delete("​config",​ "​section",​ "​option"​)</​code>​
 +deletes option
 +<code lua>​x:​delete("​config",​ "​section"​)</​code>​
 +deletes section
 +<code lua>​x:​add("​config",​ "​type"​)</​code>​
 +adds new anon section "​type"​ and returns its name
 +<code lua>​x:​set("​config",​ "​name",​ "​type"​)</​code>​
 +adds new section "​name"​ with type "​type"​
 +<code lua>​x:​foreach("​config",​ "​type",​ function(s) ... end)</​code>​
 +iterates over all sections of type "​type"​ and invokes callback function for each "​s"​ within the callback.  ​
 +s is a table containing all options and two special properties  ​
 +   * s['​.type'​] -> section type
 +   * s['​.name'​] ​ -> section name
 +If the callback function returns ''​false''​ [NB: __not__ ''​nil''​!],​ ''​foreach()''​ will terminate at that point without iterating over any remaining sections.
 +''​foreach()''​ returns ''​true''​ if at least one section exists and the callback function didn't raise an error for it; ''​false''​ otherwise.
 +<code lua>​x:​reorder("​config",​ "​sectionname",​ position)</​code>​
 +Move a section to another position. Position starts at 0. 
 +This is for example handy to change the wireless config order (changing priority). ​
 +<code lua>​x:​revert("​config"​)</​code>​
 +discards any changes made to the configuration,​ that have not yet been committed
 +<code lua>​x:​commit("​config"​)</​code>​
 +commits (saves) the changed configuration to the corresponding file in /etc/config
 +That's basically all you need
 +=== About uci structure ===
 +It took me some time to understand the difference between "​section"​ and "​type"​. Let's start with an example:
 +<​code>#​uci show system
 +Here, x:​get("​system","​@rdate[0]","​server"​) won't work. rdate is a type, not a section.
 +Here is the return of x:​get_all("​system"​):​
 +<code lua>{
 + ​cfg02f02f={["​.name"​]="​cfg02f02f",​["​.type"​]="​system",​hostname="​OpenWrt",​["​.index"​]=0,​["​.anonymous"​]=true,​timezone="​UTC"​},​
 + ​cfg04e10c={["​.name"​]="​cfg04e10c",​["​.type"​]="​rdate",​["​.index"​]=1,​["​.anonymous"​]=true,​server={"​","​","​","​","​","​","​"​}}
 +["​.type"​] gives the type of the section
 +["​.name"​] gives the real name of the section. You can see here, that these names are generated.
 +["​.index"​] is the index of the list (+1)
 +From what I know, there seem to be no way to access "​@rdate[0]"​ directly. You have to iterate with x:foreach to list all the elements of a given type.
 +I use the following function:
 +function getConfType(conf,​type)
 +   local curs=uci.cursor()
 +   local ifce={}
 +   ​curs:​foreach(conf,​type,​function(s) ifce[s["​.index"​]]=s end)
 +   ​return ifce
 +getConfType("​system","​rdate"​) returns:
 +So if you want to modify system.@rdate[0].server you need to iterate the type then retreive the section name (["​.name"​]) then call x:​set("​system","​cfg04e10c","​server","​"​)
 +Hope this helps
 +(Luci has however a [[http://​​api/​luci/​modules/​luci.model.uci.html#​Cursor.get_first|Cursor:​get_first]] function that is similiar to get except it takes a type instead as section as second argument.)
 +===== Additional Information =====
 +See also [[http://​​api/​luci/​modules/​luci.model.uci.html|LuCI UCI model functions]]. Thats what LuCI uses. It extends the uci cursor class with a few more convenience functions.
 +===== Usage outside of  OpenWrt =====
 +If you want to use the libuci apart from OpenWrt (for e.g. you are developing an application in C on your host computer) then prepare as follows:
 +Grab the source.
 +<​code>​git clone https://​​project/​uci.git
 +Go to the source directory (where the CMakeLists.txt lives) and optionally configure the build without Lua bindings:
 +<​code>​cd uci/; cmake [-D BUILD_LUA:​BOOL=OFF] .</​code>​
 +Build and install uci as root (this will install uci into /​usr/​local/,​ see this thread on how to install and use uci without root permissions in your home directory: https://​​viewtopic.php?​id=40547):​
 +<​code>​make install</​code>​
 +Open /​etc/​ and add the place where you installed the uci library:
 +<​code>​vi /​etc/​</​code>​
 +Add this line somewhere to /​etc/​
 +Execute ldconfig as root to apply the changes to /​etc/​
 +To compile your application you have to link it against the uci library. Append -luci in your Makefile:
 +<​code>​$(CC) test.o -o test -luci</​code>​
 +And examples on how to use UCI in C can be found in this thread: https://​​viewtopic.php?​pid=183335#​p183335
 +To get more examples look into the source directory of uci which you got by git clone and open cli.c or ucimap-example.c
 +===== Functioning =====
 +All ''​uci set'',​ ''​uci add'',​ ''​uci rename''​ and ''​uci delete''​ commands are staged in ''/​tmp''​ and written to flash at once with ''​uci commit''​.
 +This obviously does not apply to people using text editors, but to scripts, guis and other programs working with uci files.