* CBI: updates
[project/luci.git] / src / ffluci / model / uci.lua
1 --[[
2 FFLuCI - UCI wrapper library
3
4 Description:
5 Wrapper for the /sbin/uci application, syntax of implemented functions
6 is comparable to the syntax of the uci application
7
8 Any return value of false or nil can be interpreted as an error
9
10 FileId:
11 $Id$
12
13 License:
14 Copyright 2008 Steven Barth <steven@midlink.org>
15
16 Licensed under the Apache License, Version 2.0 (the "License");
17 you may not use this file except in compliance with the License.
18 You may obtain a copy of the License at
19
20 http://www.apache.org/licenses/LICENSE-2.0
21
22 Unless required by applicable law or agreed to in writing, software
23 distributed under the License is distributed on an "AS IS" BASIS,
24 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
25 See the License for the specific language governing permissions and
26 limitations under the License.
27
28 ]]--
29 module("ffluci.model.uci", package.seeall)
30 require("ffluci.util")
31 require("ffluci.fs")
32
33 -- The OS uci command
34 ucicmd = "uci"
35
36 -- Session class
37 Session = ffluci.util.class()
38
39 -- Session constructor
40 function Session.__init__(self, path, uci)
41 uci = uci or ucicmd
42 if path then
43 self.ucicmd = uci .. " -P " .. path
44 else
45 self.ucicmd = uci
46 end
47 end
48
49 -- The default Session
50 local default = Session()
51
52 -- Wrapper for "uci add"
53 function Session.add(self, config, section_type)
54 return self:_uci("add " .. _path(config) .. " " .. _path(section_type))
55 end
56
57 function add(...)
58 return default:add(...)
59 end
60
61
62 -- Wrapper for "uci changes"
63 function Session.changes(self, config)
64 return self:_uci3("changes " .. _path(config))
65 end
66
67 function change(...)
68 return default:change(...)
69 end
70
71
72 -- Wrapper for "uci commit"
73 function Session.commit(self, config)
74 return self:_uci2("commit " .. _path(config))
75 end
76
77 function commit(...)
78 return default:commit(...)
79 end
80
81
82 -- Wrapper for "uci del"
83 function Session.del(self, config, section, option)
84 return self:_uci2("del " .. _path(config, section, option))
85 end
86
87 function del(...)
88 return default:del(...)
89 end
90
91
92 -- Wrapper for "uci get"
93 function Session.get(self, config, section, option)
94 return self:_uci("get " .. _path(config, section, option))
95 end
96
97 function get(...)
98 return default:get(...)
99 end
100
101
102 -- Wrapper for "uci revert"
103 function Session.revert(self, config)
104 return self:_uci2("revert " .. _path(config))
105 end
106
107 function revert(...)
108 return self:revert(...)
109 end
110
111
112 -- Wrapper for "uci show"
113 function Session.show(self, config)
114 return self:_uci3("show " .. _path(config))
115 end
116
117 function show(...)
118 return default:show(...)
119 end
120
121
122 -- Wrapper for "uci set"
123 function Session.set(self, config, section, option, value)
124 return self:_uci2("set " .. _path(config, section, option, value))
125 end
126
127 function set(...)
128 return default:set(...)
129 end
130
131
132 -- Internal functions --
133
134 function Session._uci(self, cmd)
135 local res = ffluci.util.exec(self.ucicmd .. " 2>/dev/null " .. cmd)
136
137 if res:len() == 0 then
138 return nil
139 else
140 return res:sub(1, res:len()-1)
141 end
142 end
143
144 function Session._uci2(self, cmd)
145 local res = ffluci.util.exec(self.ucicmd .. " 2>&1 " .. cmd)
146
147 if res:len() > 0 then
148 return false, res
149 else
150 return true
151 end
152 end
153
154 function Session._uci3(self, cmd)
155 local res = ffluci.util.execl(self.ucicmd .. " 2>&1 " .. cmd)
156 if res[1]:sub(1, ucicmd:len() + 1) == ucicmd .. ":" then
157 return nil, res[1]
158 end
159
160 table = {}
161
162 for k,line in pairs(res) do
163 c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$")
164 if c then
165 table[c] = table[c] or {}
166 table[c][s] = {}
167 table[c][s][".type"] = t
168 end
169
170 c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$")
171 if c then
172 table[c][s][o] = v
173 end
174 end
175
176 return table
177 end
178
179 -- Build path (config.section.option=value) and prevent command injection
180 function _path(...)
181 local result = ""
182
183 -- Not using ipairs because it is not reliable in case of nil arguments
184 arg.n = nil
185 for k,v in pairs(arg) do
186 if v then
187 v = tostring(v)
188 if k == 1 then
189 result = "'" .. v:gsub("['.]", "") .. "'"
190 elseif k < 4 then
191 result = result .. ".'" .. v:gsub("['.]", "") .. "'"
192 elseif k == 4 then
193 result = result .. "='" .. v:gsub("'", "") .. "'"
194 end
195 end
196 end
197 return result
198 end