8414fadc42e737e4527ebd63b90e34dc1d22de66
[project/luci.git] / core / src / ffluci / model / uci / libuci.lua
1 --[[
2 FFLuCI - UCI libuci wrapper
3
4 Description:
5 Wrapper for the libuci Lua bindings
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
27 module("ffluci.model.uci.libuci", package.seeall)
28
29 require("ffluci.util")
30 require("ffluci.fs")
31 require("ffluci.sys")
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 function Session.add(self, config, section_type)
50 return self:_uci("add " .. _path(config) .. " " .. _path(section_type))
51 end
52
53 function Session.changes(self, config)
54 return self:_uci("changes " .. _path(config))
55 end
56
57 function Session.commit(self, config)
58 return self:_uci2("commit " .. _path(config))
59 end
60
61 function Session.del(self, config, section, option)
62 return self:_uci2("del " .. _path(config, section, option))
63 end
64
65 function Session.get(self, config, section, option)
66 return self:_uci("get " .. _path(config, section, option))
67 end
68
69 function Session.revert(self, config)
70 return self:_uci2("revert " .. _path(config))
71 end
72
73 function Session.sections(self, config)
74 if not config then
75 return nil
76 end
77
78 local r1, r2 = self:_uci3("show " .. _path(config))
79 if type(r1) == "table" then
80 return r1[config]
81 else
82 return nil, r2
83 end
84 end
85
86 function Session.set(self, config, section, option, value)
87 return self:_uci2("set " .. _path(config, section, option, value))
88 end
89
90
91
92 -- Internal functions --
93
94
95 function Session._uci(self, cmd)
96 local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd)
97
98 if res:len() == 0 then
99 return nil
100 else
101 return res:sub(1, res:len()-1)
102 end
103 end
104
105 function Session._uci2(self, cmd)
106 local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd)
107
108 if res:len() > 0 then
109 return false, res
110 else
111 return true
112 end
113 end
114
115 function Session._uci3(self, cmd)
116 local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd)
117 if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then
118 return nil, res[1]
119 end
120
121 tbl = {}
122
123 for k,line in pairs(res) do
124 c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$")
125 if c then
126 tbl[c] = tbl[c] or {}
127 tbl[c][".order"] = tbl[c][".order"] or {}
128
129 tbl[c][s] = {}
130 table.insert(tbl[c][".order"], s)
131 tbl[c][s][".type"] = t
132 end
133
134 c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$")
135 if c then
136 tbl[c][s][o] = v
137 end
138 end
139
140 return tbl
141 end
142
143 -- Build path (config.section.option=value) and prevent command injection
144 function _path(...)
145 local result = ""
146
147 -- Not using ipairs because it is not reliable in case of nil arguments
148 arg.n = nil
149 for k,v in pairs(arg) do
150 if v then
151 v = tostring(v)
152 if k == 1 then
153 result = "'" .. v:gsub("['.]", "") .. "'"
154 elseif k < 4 then
155 result = result .. ".'" .. v:gsub("['.]", "") .. "'"
156 elseif k == 4 then
157 result = result .. "='" .. v:gsub("'", "") .. "'"
158 end
159 end
160 end
161 return result
162 end