659cd62543b763f252a1890398142ccc9468d9a3
[project/luci.git] / libs / uci / luasrc / model / uci.lua
1 --[[
2 LuCI - UCI model
3
4 Description:
5 Generalized UCI model
6
7 FileId:
8 $Id$
9
10 License:
11 Copyright 2008 Steven Barth <steven@midlink.org>
12
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
16
17         http://www.apache.org/licenses/LICENSE-2.0
18
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
24
25 ]]--
26 local os    = require "os"
27 local uci   = require "uci"
28 local util  = require "luci.util"
29 local table = require "table"
30
31
32 local setmetatable, rawget, rawset = setmetatable, rawget, rawset
33 local error, pairs, ipairs, tostring = error, pairs, ipairs, tostring
34 local require, getmetatable, type = require, getmetatable, type
35
36 --- LuCI UCI model library.
37 -- @cstyle      instance
38 module "luci.model.uci"
39
40 --- Create a new UCI-Cursor.
41 -- @class function
42 -- @name cursor
43 -- @return      UCI-Cursor
44 cursor = uci.cursor
45
46 APIVERSION = uci.APIVERSION
47
48 --- Create a new Cursor initialized to the state directory.
49 -- @return UCI cursor
50 function cursor_state()
51         return cursor(nil, "/var/state")
52 end
53
54
55 local Cursor = getmetatable(cursor())
56
57 --- Applies the new config
58 -- @param config                UCI config
59 function Cursor.apply(self, config)
60         local conf = require "luci.config"
61         return conf.uci_oncommit[config] and
62          os.execute(conf.uci_oncommit[config] .. " >/dev/null 2>&1")
63 end
64
65 --- Delete all sections of a given type that match certain criteria.
66 -- @param config                UCI config
67 -- @param type                  UCI section type
68 -- @param comparator    Function that will be called for each section and
69 -- returns a boolean whether to delete the current section (optional)
70 function Cursor.delete_all(self, config, stype, comparator)
71         local del = {}
72         
73         if type(comparator) == "table" then
74                 local tbl = comparator
75                 comparator = function(section)
76                         for k, v in pairs(tbl) do
77                                 if not section[k] == v then
78                                         return false
79                                 end
80                         end 
81                         return true
82                 end
83         end
84         
85         local function helper (section)
86
87                 if not comparator or comparator(section) then
88                         table.insert(del, section[".name"])
89                 end
90         end
91
92         self:foreach(config, stype, helper)
93
94         for i, j in ipairs(del) do
95                 self:delete(config, j)
96         end
97 end
98
99 --- Create a new section and initialize it with data.
100 -- @param config        UCI config
101 -- @param type          UCI section type
102 -- @param name          UCI section name (optional)
103 -- @param values        Table of key - value pairs to initialize the section with
104 -- @return                      Name of created section
105 function Cursor.section(self, config, type, name, values)
106         local stat = true
107         if name then
108                 stat = self:set(config, name, type)
109         else
110                 name = self:add(config, type)
111                 stat = name and true
112         end
113
114         if stat and values then
115                 stat = self:tset(config, name, values)
116         end
117
118         return stat and name
119 end
120
121 --- Updated the data of a section using data from a table.
122 -- @param config        UCI config
123 -- @param section       UCI section name (optional)
124 -- @param values        Table of key - value pairs to update the section with
125 function Cursor.tset(self, config, section, values)
126         local stat = true
127         for k, v in pairs(values) do
128                 if k:sub(1, 1) ~= "." then
129                         stat = stat and self:set(config, section, k, v)
130                 end
131         end
132         return stat
133 end
134
135 --- Get an option or list and return values as table.
136 -- @param config        UCI config
137 -- @param section       UCI section name
138 -- @param option        UCI option
139 -- @return                      UCI value
140 function Cursor.get_list(self, config, section, option)
141         if config and section and option then
142                 local val = self:get(config, section, option)
143                 return ( type(val) == "table" and val or { val } )
144         end
145         return nil
146 end
147
148 --- Set given values as list.
149 -- @param config        UCI config
150 -- @param section       UCI section name
151 -- @param option        UCI option
152 -- @param value         UCI value
153 -- @return                      Boolean whether operation succeeded
154 function Cursor.set_list(self, config, section, option, value)
155         if config and section and option then
156                 return self:set(
157                         config, section, option,
158                         ( type(value) == "table" and value or { value } )
159                 )
160         end
161         return false
162 end
163
164
165 Cursor._changes = Cursor.changes
166 function Cursor.changes(self, config)
167         if config then
168                 return Cursor._changes(self, config)
169         else
170                 local changes = Cursor._changes(self)
171                 util.copcall(function()
172                         for k,v in pairs(require "luci.fs".dir(self:get_savedir())) do
173                                 if v ~= "." and v ~= ".." then
174                                         util.update(changes, Cursor._changes(self, v))
175                                 end
176                         end
177                 end)
178                 return changes
179         end
180 end
181
182
183 --- Add an anonymous section.
184 -- @class function
185 -- @name Cursor.add
186 -- @param config        UCI config
187 -- @param type          UCI section type
188 -- @return                      Name of created section
189
190 --- Get a table of unsaved changes.
191 -- @class function
192 -- @name Cursor.changes
193 -- @param config        UCI config
194 -- @return                      Table of changes
195
196 --- Commit unsaved changes.
197 -- @class function
198 -- @name Cursor.commit
199 -- @param config        UCI config
200 -- @return                      Boolean whether operation succeeded
201 -- @see Cursor.revert
202
203 --- Deletes a section or an option.
204 -- @class function
205 -- @name Cursor.delete
206 -- @param config        UCI config
207 -- @param section       UCI section name
208 -- @param option        UCI option (optional)
209 -- @return                      Boolean whether operation succeeded
210
211 --- Call a function for every section of a certain type.
212 -- @class function
213 -- @name Cursor.foreach
214 -- @param config        UCI config
215 -- @param type          UCI section type
216 -- @param callback      Function to be called
217 -- @return                      Boolean whether operation succeeded
218
219 --- Get a section type or an option
220 -- @class function
221 -- @name Cursor.get
222 -- @param config        UCI config
223 -- @param section       UCI section name
224 -- @param option        UCI option (optional)
225 -- @return                      UCI value
226
227 --- Get all sections of a config or all values of a section.
228 -- @class function
229 -- @name Cursor.get_all
230 -- @param config        UCI config
231 -- @param section       UCI section name (optional)
232 -- @return                      Table of UCI sections or table of UCI values
233
234 --- Manually load a config.
235 -- @class function
236 -- @name Cursor.load
237 -- @param config        UCI config
238 -- @return                      Boolean whether operation succeeded
239 -- @see Cursor.save
240 -- @see Cursor.unload
241
242 --- Revert unsaved changes.
243 -- @class function
244 -- @name Cursor.revert
245 -- @param config        UCI config
246 -- @return                      Boolean whether operation succeeded
247 -- @see Cursor.commit
248
249 --- Saves changes made to a config to make them committable.
250 -- @class function
251 -- @name Cursor.save
252 -- @param config        UCI config
253 -- @return                      Boolean whether operation succeeded
254 -- @see Cursor.load
255 -- @see Cursor.unload
256
257 --- Set a value or create a named section.
258 -- @class function
259 -- @name Cursor.set
260 -- @param config        UCI config
261 -- @param section       UCI section name
262 -- @param option        UCI option or UCI section type
263 -- @param value         UCI value or nil if you want to create a section
264 -- @return                      Boolean whether operation succeeded
265
266 --- Get the configuration directory.
267 -- @class function
268 -- @name Cursor.get_confdir
269 -- @return                      Configuration directory
270
271 --- Get the directory for uncomitted changes.
272 -- @class function
273 -- @name Cursor.get_savedir
274 -- @return                      Save directory
275
276 --- Set the configuration directory.
277 -- @class function
278 -- @name Cursor.set_confdir
279 -- @param directory     UCI configuration directory
280 -- @return                      Boolean whether operation succeeded
281
282 --- Set the directory for uncommited changes.
283 -- @class function
284 -- @name Cursor.set_savedir
285 -- @param directory     UCI changes directory
286 -- @return                      Boolean whether operation succeeded
287
288 --- Discard changes made to a config.
289 -- @class function
290 -- @name Cursor.unload
291 -- @param config        UCI config
292 -- @return                      Boolean whether operation succeeded
293 -- @see Cursor.load
294 -- @see Cursor.save