michael@428: -- michael@428: -- rpmlua -- OpenPKG RPM Lua Script michael@428: -- Copyright (c) 2000-2012 OpenPKG GmbH michael@428: -- michael@428: -- This software is property of the OpenPKG GmbH, DE MUC HRB 160208. michael@428: -- All rights reserved. Licenses which grant limited permission to use, michael@428: -- copy, modify and distribute this software are available from the michael@428: -- OpenPKG GmbH. michael@428: -- michael@428: -- THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESSED OR IMPLIED michael@428: -- WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF michael@428: -- MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. michael@428: -- IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR michael@428: -- CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, michael@428: -- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT michael@428: -- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF michael@428: -- USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND michael@428: -- ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, michael@428: -- OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT michael@428: -- OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF michael@428: -- SUCH DAMAGE. michael@428: -- michael@428: michael@428: -- michael@428: -- The purpose of this Lua script is to extend the default Lua functions michael@428: -- in the OpenPKG RPM installation for the @l_prefix@ hierarchy. michael@428: -- michael@428: michael@428: -- provide namespace michael@428: openpkg = {} michael@428: michael@428: -- small wrapper around the realpath(3) call provided by RPM michael@428: function openpkg.realpath(path) michael@428: if posix.stat(path) ~= nil then michael@428: -- path exists, so resolve as a whole michael@428: path = rpm.realpath(path) michael@428: else michael@428: -- path not exists, so recursively resolve only prefix michael@428: local s, _, m = util.rmatch(path, "^(.+?)/([^/]+)/?$") michael@428: if s ~= nil then michael@428: local prefix = openpkg.realpath(m[1]) michael@428: if util.rmatch(prefix, "/$") == nil then michael@428: prefix = prefix .. "/" michael@428: end michael@428: path = prefix .. m[2] michael@428: end michael@428: end michael@428: return path michael@428: end michael@428: michael@428: -- try to reduce real path to symbolic one (if posssible) michael@428: function openpkg.unrealpath(path, prefix_unreal) michael@428: local prefix_real = openpkg.realpath(prefix_unreal) michael@428: if prefix_real ~= prefix_unreal then michael@428: if string.sub(path, 1, string.len(prefix_real)) == prefix_real then michael@428: path = prefix_unreal .. string.sub(path, string.len(prefix_real)+1) michael@428: end michael@428: end michael@428: return path michael@428: end michael@428: michael@428: -- canonicalize filesystem path as good as possible michael@428: function openpkg.canonicalize(path) michael@428: path = openpkg.unrealpath(path, os.getenv("PWD")) michael@428: path = openpkg.unrealpath(path, rpm.expand("%{l_prefix}")) michael@428: return path michael@428: end michael@428: michael@428: -- temporary directory determination michael@428: function openpkg.tmpdir() michael@428: local tmpdir = os.getenv("TMPDIR") michael@428: if tmpdir ~= nil then michael@428: tmpdir = openpkg.canonicalize(openpkg.realpath(tmpdir)) michael@428: else michael@428: tmpdir = "/tmp" michael@428: end michael@428: tmpdir = tmpdir .. "/openpkg" michael@428: return tmpdir michael@428: end michael@428: michael@428: -- layout determination: RPM Lua based implementation michael@428: function openpkg.layout(args) michael@428: local dir = "" michael@428: michael@428: -- parse arguments michael@428: local arg = { michael@428: variable = "", michael@428: layout = "", michael@428: macrosfile = "", michael@428: basedir = "", michael@428: shared = "no", michael@428: debug = "no", michael@428: specdir = "", michael@428: sourcedir = "", michael@428: builddir = "", michael@428: tmppath = "", michael@428: rpmdir = "", michael@428: srcrpmdir = "" michael@428: } michael@428: local arg_map_fwd = { michael@428: binrpmdir = "rpmdir", michael@428: tmpdir = "tmppath" michael@428: } michael@428: local arg_map_rev = { michael@428: rpmdir = "binrpmdir", michael@428: tmppath = "tmpdir" michael@428: } michael@428: if rpm.debug() then michael@428: arg.debug = "yes" michael@428: end michael@428: util.rsubst(args, "(?s)\\s*([a-z_][a-zA-Z0-9_-]*)=(?:\"((?:\\\\.|[^\"])*)\"|(\\S*))", michael@428: function (key, _, value1, value2) michael@428: if arg_map_fwd[key] ~= nil then michael@428: key = arg_map_fwd[key] michael@428: end michael@428: if arg[key] == nil then michael@428: io.stderr:write("rpm: invalid parameter \"" .. key .. "\" on call to \"openpkg.layout()\"\n") michael@428: else michael@428: if value1 ~= nil then arg[key] = value1 else arg[key] = value2 end michael@428: end michael@428: return false michael@428: end michael@428: ) michael@428: if arg.variable == "" then michael@428: io.stderr:write("rpm: missing \"variable\" parameter on call to \"openpkg.layout()\"\n") michael@428: return "" michael@428: end michael@428: if arg.layout == "" then michael@428: io.stderr:write("rpm: missing \"layout\" parameter on call to \"openpkg.layout()\"\n") michael@428: return "" michael@428: end michael@428: if arg.macrosfile == "" and arg.basedir == "" then michael@428: io.stderr:write("rpm: missing \"macrosfile\" or \"basedir\" parameter on call to \"openpkg.layout()\"\n") michael@428: return "" michael@428: end michael@428: michael@428: -- determine base directory michael@428: if arg.basedir == "" then michael@428: if util.rmatch(arg.macrosfile, "^.*/\.openpkg/rpmmacros$") ~= nil then michael@428: arg.basedir = openpkg.canonicalize(openpkg.realpath( michael@428: util.rsubst( michael@428: openpkg.realpath(arg.macrosfile), michael@428: "/[^/]+$", "/.." michael@428: ) michael@428: )) michael@428: else michael@428: arg.basedir = rpm.expand("%{l_prefix}") michael@428: end michael@428: end michael@428: michael@428: -- temporarily define "__openpkg_basedir" macro michael@428: rpm.define("__openpkg_basedir " .. arg.basedir) michael@428: michael@428: -- temporarily define "__openpkg_shared" macro michael@428: if arg.shared == "yes" then michael@428: rpm.define("__openpkg_shared yes") michael@428: end michael@428: michael@428: -- determine layout directory list michael@428: local list = "" michael@428: if arg[arg.variable] ~= nil and arg[arg.variable] ~= "" then michael@428: list = arg[arg.variable] michael@428: else michael@428: list = rpm.expand( michael@428: "%{?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. "}" .. michael@428: "%{!?__openpkg_layout_" .. arg.layout .. "_" .. arg.variable .. ":" .. michael@428: "%{__openpkg_layout_global_" .. arg.variable .. "}}" michael@428: ) michael@428: end michael@428: michael@428: -- remove temporarily defined "__openpkg_basedir" macro michael@428: rpm.undefine("__openpkg_basedir") michael@428: michael@428: -- remove temporarily defined "__openpkg_shared" macro michael@428: if arg.shared == "yes" then michael@428: rpm.undefine("__openpkg_shared") michael@428: end michael@428: michael@428: -- iterate over all directory specifications michael@428: local dirs = util.rsplit(list, "(?s)\\s+") michael@428: local k = table.maxn(dirs) michael@428: for i, _ in ipairs(dirs) do michael@428: -- parse specification into path to check and optionally path to make michael@428: local path_check = dirs[i] michael@428: local path_append = false michael@428: local path_make = path_check michael@428: local s, _, m = util.rmatch(path_check, "^(.+):(\\+?)(.*)$") michael@428: if s ~= nil then michael@428: path_check = m[1] michael@428: path_append = (m[2] == "+") michael@428: path_make = m[3] michael@428: end michael@428: -- check whether path should be taken (last path is always taken) michael@428: if posix.stat(path_check) ~= nil or i == k then michael@428: if path_append then michael@428: -- special case: simply append a suffix michael@428: dir = path_check .. path_make michael@428: else michael@428: -- regular case: use full path to make michael@428: dir = path_make michael@428: end michael@428: break michael@428: end michael@428: end michael@428: if dir ~= "" then michael@428: -- make sure path really exists and resolve to absolute path michael@428: if posix.stat(dir) == nil then michael@428: io.stderr:write("rpm: creating \"" .. arg.variable .. "\" directory \"" .. dir .. "\"\n") michael@428: if posix.mkdir(dir) ~= 0 then michael@428: io.stderr:write("rpm: failed to create directory \"" .. dir .. "\"\n") michael@428: end michael@428: end michael@428: dir = openpkg.canonicalize(openpkg.realpath(dir)) michael@428: end michael@428: michael@428: -- debugging michael@428: if arg.debug == "yes" then michael@428: local variable = arg.variable michael@428: if arg_map_rev[variable] ~= nil then michael@428: variable = arg_map_rev[variable] michael@428: end michael@428: io.stderr:write(string.format("rpm: openpkg: layout: [%s] %s = \"%s\"\n", arg.layout, variable, dir)) michael@428: end michael@428: michael@428: -- provide result directory michael@428: return dir michael@428: end michael@428: