X-Git-Url: http://git.archive.openwrt.org/?a=blobdiff_plain;f=libs%2Fipkg%2Fluasrc%2Fmodel%2Fipkg.lua;h=d0d9788fd8be6c861a74aaead8ec23a06026608c;hb=f83cdb1b8bff33f47867af8941d4aabcda1575f4;hp=b06834510abb4ffb317ad2591206b06592385aae;hpb=dc494c838c15ef59a72927b9cf6f18878d06bd69;p=project%2Fluci.git diff --git a/libs/ipkg/luasrc/model/ipkg.lua b/libs/ipkg/luasrc/model/ipkg.lua index b06834510..d0d9788fd 100644 --- a/libs/ipkg/luasrc/model/ipkg.lua +++ b/libs/ipkg/luasrc/model/ipkg.lua @@ -1,7 +1,7 @@ --[[ LuCI - Lua Configuration Interface -(c) 2008 Jo-Philipp Wich +(c) 2008-2011 Jo-Philipp Wich (c) 2008 Steven Barth Licensed under the Apache License, Version 2.0 (the "License"); @@ -14,45 +14,54 @@ $Id$ ]]-- local os = require "os" +local io = require "io" +local fs = require "nixio.fs" local util = require "luci.util" local type = type local pairs = pairs local error = error +local table = table -local ipkg = "opkg" +local ipkg = "opkg --force-removal-of-dependent-packages --force-overwrite" +local icfg = "/etc/opkg.conf" ---- LuCI IPKG/OPKG call abstraction library +--- LuCI OPKG call abstraction library module "luci.model.ipkg" -- Internal action function local function _action(cmd, ...) local pkg = "" - arg.n = nil - for k, v in pairs(arg) do + for k, v in pairs({...}) do pkg = pkg .. " '" .. v:gsub("'", "") .. "'" end - - local c = ipkg.." "..cmd.." "..pkg.." >/dev/null 2>&1" + + local c = "%s %s %s >/tmp/opkg.stdout 2>/tmp/opkg.stderr" %{ ipkg, cmd, pkg } local r = os.execute(c) - return (r == 0), r + local e = fs.readfile("/tmp/opkg.stderr") + local o = fs.readfile("/tmp/opkg.stdout") + + fs.unlink("/tmp/opkg.stderr") + fs.unlink("/tmp/opkg.stdout") + + return r, o or "", e or "" end -- Internal parser function -local function _parselist(rawdata) +local function _parselist(rawdata) if type(rawdata) ~= "function" then - error("IPKG: Invalid rawdata given") + error("OPKG: Invalid rawdata given") end - + local data = {} local c = {} local l = nil - + for line in rawdata do if line:sub(1, 1) ~= " " then local key, val = line:match("(.-): ?(.*)%s*") - + if key and val then if key == "Package" then c = {Package = val} @@ -72,7 +81,7 @@ local function _parselist(rawdata) c[l] = c[l] .. "\n" .. line end end - + return data end @@ -82,8 +91,16 @@ local function _lookup(act, pkg) if pkg then cmd = cmd .. " '" .. pkg:gsub("'", "") .. "'" end - - return _parselist(util.execi(cmd .. " 2>/dev/null")) + + -- OPKG sometimes kills the whole machine because it sucks + -- Therefore we have to use a sucky approach too and use + -- tmpfiles instead of directly reading the output + local tmpfile = os.tmpname() + os.execute(cmd .. (" >%s 2>/dev/null" % tmpfile)) + + local data = _parselist(io.lines(tmpfile)) + os.remove(tmpfile) + return data end @@ -104,7 +121,7 @@ end --- Install one or more packages. -- @param ... List of packages to install -- @return Boolean indicating the status of the action --- @return IPKG return code +-- @return OPKG return code, STDOUT and STDERR function install(...) return _action("install", ...) end @@ -120,22 +137,97 @@ end --- Remove one or more packages. -- @param ... List of packages to install -- @return Boolean indicating the status of the action --- @return IPKG return code +-- @return OPKG return code, STDOUT and STDERR function remove(...) return _action("remove", ...) end --- Update package lists. -- @return Boolean indicating the status of the action --- @return IPKG return code +-- @return OPKG return code, STDOUT and STDERR function update() return _action("update") end --- Upgrades all installed packages. -- @return Boolean indicating the status of the action --- @return IPKG return code +-- @return OPKG return code, STDOUT and STDERR function upgrade() return _action("upgrade") end +-- List helper +function _list(action, pat, cb) + local fd = io.popen(ipkg .. " " .. action .. + (pat and (" '%s'" % pat:gsub("'", "")) or "")) -- .. " | grep -vE '^ '") + + if fd then + local name, version, desc + while true do + local line = fd:read("*l") + if not line then break end + + if line:sub(1,1) ~= " " then + name, version, desc = line:match("^(.-) %- (.-) %- (.+)") + + if not name then + name, version = line:match("^(.-) %- (.+)") + desc = "" + end + + cb(name, version, desc) + + name = nil + version = nil + desc = nil + end + end + + fd:close() + end +end + +--- List all packages known to opkg. +-- @param pat Only find packages matching this pattern, nil lists all packages +-- @param cb Callback function invoked for each package, receives name, version and description as arguments +-- @return nothing +function list_all(pat, cb) + _list("list", pat, cb) +end + +--- List installed packages. +-- @param pat Only find packages matching this pattern, nil lists all packages +-- @param cb Callback function invoked for each package, receives name, version and description as arguments +-- @return nothing +function list_installed(pat, cb) + _list("list_installed", pat, cb) +end + +--- Determines the overlay root used by opkg. +-- @return String containing the directory path of the overlay root. +function overlay_root() + local od = "/" + local fd = io.open(icfg, "r") + + if fd then + local ln + + repeat + ln = fd:read("*l") + if ln and ln:match("^%s*option%s+overlay_root%s+") then + od = ln:match("^%s*option%s+overlay_root%s+(%S+)") + + local s = fs.stat(od) + if not s or s.type ~= "dir" then + od = "/" + end + + break + end + until not ln + + fd:close() + end + + return od +end