diff options
Diffstat (limited to 'core/src/model')
-rw-r--r-- | core/src/model/ipkg.lua | 140 | ||||
-rw-r--r-- | core/src/model/uci.lua | 92 | ||||
-rw-r--r-- | core/src/model/uci/libuci.lua | 193 | ||||
-rw-r--r-- | core/src/model/uci/wrapper.lua | 171 |
4 files changed, 596 insertions, 0 deletions
diff --git a/core/src/model/ipkg.lua b/core/src/model/ipkg.lua new file mode 100644 index 0000000000..3b149fb168 --- /dev/null +++ b/core/src/model/ipkg.lua @@ -0,0 +1,140 @@ +--[[ +FFLuCI - IPKG wrapper library + +Description: +Wrapper for the ipkg Package manager + +Any return value of false or nil can be interpreted as an error + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("ffluci.model.ipkg", package.seeall) +require("ffluci.sys") +require("ffluci.util") + +ipkg = "ipkg" + +-- Returns repository information +function info(pkg) + return _lookup("info", pkg) +end + +-- Returns a table with status information +function status(pkg) + return _lookup("status", pkg) +end + +-- Installs packages +function install(...) + return _action("install", ...) +end + +-- Returns whether a package is installed +function installed(pkg, ...) + local p = status(...)[pkg] + return (p and p.Status and p.Status.installed) +end + +-- Removes packages +function remove(...) + return _action("remove", ...) +end + +-- Updates package lists +function update() + return _action("update") +end + +-- Upgrades installed packages +function upgrade() + return _action("upgrade") +end + + +-- Internal action function +function _action(cmd, ...) + local pkg = "" + arg.n = nil + for k, v in pairs(arg) do + pkg = pkg .. " '" .. v:gsub("'", "") .. "'" + end + + local c = ipkg.." "..cmd.." "..pkg.." >/dev/null 2>&1" + local r = os.execute(c) + return (r == 0), r +end + +-- Internal lookup function +function _lookup(act, pkg) + local cmd = ipkg .. " " .. act + if pkg then + cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" + end + + return _parselist(ffluci.sys.exec(cmd .. " 2>/dev/null")) +end + +-- Internal parser function +function _parselist(rawdata) + if type(rawdata) ~= "string" then + error("IPKG: Invalid rawdata given") + end + + rawdata = ffluci.util.split(rawdata) + local data = {} + local c = {} + local l = nil + + for k, line in pairs(rawdata) do + if line:sub(1, 1) ~= " " then + local split = ffluci.util.split(line, ":", 1) + local key = nil + local val = nil + + if split[1] then + key = ffluci.util.trim(split[1]) + end + + if split[2] then + val = ffluci.util.trim(split[2]) + end + + if key and val then + if key == "Package" then + c = {Package = val} + data[val] = c + elseif key == "Status" then + c.Status = {} + for i, j in pairs(ffluci.util.split(val, " ")) do + c.Status[j] = true + end + else + c[key] = val + end + l = key + end + else + -- Multi-line field + c[l] = c[l] .. "\n" .. line:sub(2) + end + end + + return data +end
\ No newline at end of file diff --git a/core/src/model/uci.lua b/core/src/model/uci.lua new file mode 100644 index 0000000000..ca5b232eb3 --- /dev/null +++ b/core/src/model/uci.lua @@ -0,0 +1,92 @@ +--[[ +FFLuCI - UCI mpdel + +Description: +Generalized UCI model + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- +module("ffluci.model.uci", package.seeall) + +-- Default savedir +savedir = "/tmp/.uci" + +-- Test whether to load libuci-Wrapper or /sbin/uci-Wrapper +if pcall(require, "uci") then + Session = require("ffluci.model.uci.libuci").Session +else + Session = require("ffluci.model.uci.wrapper").Session +end + +-- The default Session +local default = Session() +local state = Session("/var/state") + +-- The state Session +function StateSession() + return state +end + + +-- Wrapper for "uci add" +function add(...) + return default:add(...) +end + + +-- Wrapper for "uci changes" +function changes(...) + return default:changes(...) +end + +-- Wrapper for "uci commit" +function commit(...) + return default:commit(...) +end + + +-- Wrapper for "uci del" +function del(...) + return default:del(...) +end + + +-- Wrapper for "uci get" +function get(...) + return default:get(...) +end + + +-- Wrapper for "uci revert" +function revert(...) + return default:revert(...) +end + + +-- Wrapper for "uci show" +function sections(...) + return default:sections(...) +end + + +-- Wrapper for "uci set" +function set(...) + return default:set(...) +end
\ No newline at end of file diff --git a/core/src/model/uci/libuci.lua b/core/src/model/uci/libuci.lua new file mode 100644 index 0000000000..b160dc10a3 --- /dev/null +++ b/core/src/model/uci/libuci.lua @@ -0,0 +1,193 @@ +--[[ +FFLuCI - UCI libuci wrapper + +Description: +Wrapper for the libuci Lua bindings + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +module("ffluci.model.uci.libuci", package.seeall) + +require("uci") +require("ffluci.util") +require("ffluci.sys") + +-- Session class +Session = ffluci.util.class() + +-- Session constructor +function Session.__init__(self, savedir) + self.ucicmd = savedir and "uci -P " .. savedir or "uci" + self.savedir = savedir or ffluci.model.uci.savedir +end + +function Session.add(self, config, section_type) + return self:_uci("add " .. _path(config) .. " " .. _path(section_type)) +end + +function Session.changes(self, config) + return self:_uci("changes " .. _path(config)) +end + +function Session.commit(self, config) + self:t_load(config) + return self:t_commit(config) +end + +function Session.del(self, config, section, option) + return self:_uci2("del " .. _path(config, section, option)) +end + +function Session.get(self, config, section, option) + self:t_load(config) + return self:t_get(config, section, option) +end + +function Session.revert(self, config) + self:t_load(config) + return self:t_revert(config) +end + +function Session.sections(self, config) + self:t_load(config) + return self:t_sections(config) +end + +function Session.set(self, config, section, option, value) + self:t_load(config) + return self:t_set(config, section, option, value) and self:t_save(config) +end + +function Session.synchronize(self) + return uci.set_savedir(self.savedir) +end + + +-- UCI-Transactions + +function Session.t_load(self, config) + return self:synchronize() and uci.load(config) +end + +function Session.t_save(self, config) + return uci.save(config) +end + +function Session.t_add(self, config, type) + self:t_save(config) + local r = self:add(config, type) + self:t_load(config) + return r +end + +function Session.t_commit(self, config) + return uci.commit(config) +end + +function Session.t_del(self, config, section, option) + self:t_save(config) + local r = self:del(config, section, option) + self:t_load(config) + return r +end + +function Session.t_get(self, config, section, option) + if option then + return uci.get(config, section, option) + else + return uci.get(config, section) + end +end + +function Session.t_revert(self, config) + return uci.revert(config) +end + +function Session.t_sections(self, config) + local raw = uci.get_all(config) + if not raw then + return nil + end + + local s = {} + local o = {} + + for i, sec in ipairs(raw) do + table.insert(o, sec.name) + + s[sec.name] = sec.options + s[sec.name][".type"] = sec.type + end + + return s, o +end + +function Session.t_set(self, config, section, option, value) + if option then + return uci.set(config.."."..section.."."..option.."="..value) + else + return uci.set(config.."."..section.."="..value) + end +end + +-- Internal functions -- + + +function Session._uci(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd) + + if res:len() == 0 then + return nil + else + return res:sub(1, res:len()-1) + end +end + +function Session._uci2(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd) + + if res:len() > 0 then + return false, res + else + return true + end +end + +-- Build path (config.section.option=value) and prevent command injection +function _path(...) + local result = "" + + -- Not using ipairs because it is not reliable in case of nil arguments + arg.n = nil + for k,v in pairs(arg) do + if v then + v = tostring(v) + if k == 1 then + result = "'" .. v:gsub("['.]", "") .. "'" + elseif k < 4 then + result = result .. ".'" .. v:gsub("['.]", "") .. "'" + elseif k == 4 then + result = result .. "='" .. v:gsub("'", "") .. "'" + end + end + end + return result +end
\ No newline at end of file diff --git a/core/src/model/uci/wrapper.lua b/core/src/model/uci/wrapper.lua new file mode 100644 index 0000000000..3aa3b5fd1d --- /dev/null +++ b/core/src/model/uci/wrapper.lua @@ -0,0 +1,171 @@ +--[[ +FFLuCI - UCI wrapper library + +Description: +Wrapper for the /sbin/uci application, syntax of implemented functions +is comparable to the syntax of the uci application + +Any return value of false or nil can be interpreted as an error + +FileId: +$Id$ + +License: +Copyright 2008 Steven Barth <steven@midlink.org> + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. + +]]-- + +module("ffluci.model.uci.wrapper", package.seeall) + +require("ffluci.util") +require("ffluci.sys") + +-- Session class +Session = ffluci.util.class() + +-- Session constructor +function Session.__init__(self, savedir) + self.ucicmd = savedir and "uci -P " .. savedir or "uci" +end + +function Session.add(self, config, section_type) + return self:_uci("add " .. _path(config) .. " " .. _path(section_type)) +end + +function Session.changes(self, config) + return self:_uci("changes " .. _path(config)) +end + +function Session.commit(self, config) + return self:_uci2("commit " .. _path(config)) +end + +function Session.del(self, config, section, option) + return self:_uci2("del " .. _path(config, section, option)) +end + +function Session.get(self, config, section, option) + return self:_uci("get " .. _path(config, section, option)) +end + +function Session.revert(self, config) + return self:_uci2("revert " .. _path(config)) +end + +function Session.sections(self, config) + if not config then + return nil + end + + local r1, r2 = self:_uci3("show " .. _path(config)) + if type(r1) == "table" then + return r1, r2 + else + return nil, r2 + end +end + +function Session.set(self, config, section, option, value) + return self:_uci2("set " .. _path(config, section, option, value)) +end + +function Session.synchronize(self) end + +-- Dummy transaction functions + +function Session.t_load(self) end +function Session.t_save(self) end + +Session.t_add = Session.add +Session.t_commit = Session.commit +Session.t_del = Session.del +Session.t_get = Session.get +Session.t_revert = Session.revert +Session.t_sections = Session.sections +Session.t_set = Session.set + + + + + +-- Internal functions -- + + +function Session._uci(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>/dev/null " .. cmd) + + if res:len() == 0 then + return nil + else + return res:sub(1, res:len()-1) + end +end + +function Session._uci2(self, cmd) + local res = ffluci.sys.exec(self.ucicmd .. " 2>&1 " .. cmd) + + if res:len() > 0 then + return false, res + else + return true + end +end + +function Session._uci3(self, cmd) + local res = ffluci.sys.execl(self.ucicmd .. " 2>&1 " .. cmd) + if res[1] and res[1]:sub(1, self.ucicmd:len()+1) == self.ucicmd..":" then + return nil, res[1] + end + + local tbl = {} + local ord = {} + + for k,line in pairs(res) do + c, s, t = line:match("^([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[s] = {} + table.insert(ord, s) + tbl[s][".type"] = t + end + + c, s, o, v = line:match("^([^.]-)%.([^.]-)%.([^.]-)=(.-)$") + if c then + tbl[s][o] = v + end + end + + return tbl, ord +end + +-- Build path (config.section.option=value) and prevent command injection +function _path(...) + local result = "" + + -- Not using ipairs because it is not reliable in case of nil arguments + arg.n = nil + for k,v in pairs(arg) do + if v then + v = tostring(v) + if k == 1 then + result = "'" .. v:gsub("['.]", "") .. "'" + elseif k < 4 then + result = result .. ".'" .. v:gsub("['.]", "") .. "'" + elseif k == 4 then + result = result .. "='" .. v:gsub("'", "") .. "'" + end + end + end + return result +end
\ No newline at end of file |