150 lines
3.5 KiB
Lua
150 lines
3.5 KiB
Lua
|
usrmerge = { debug = nil } -- package
|
||
|
|
||
|
require("usrmerge_files")
|
||
|
|
||
|
-- for testing outside rpm
|
||
|
if posix == nil then
|
||
|
posix = require("posix")
|
||
|
function _symlink(old, new)
|
||
|
os.execute("ln -vs " .. old .. " " .. new)
|
||
|
end
|
||
|
posix.symlink = _symlink
|
||
|
end
|
||
|
|
||
|
function _log(msg)
|
||
|
if usrmerge.debug then
|
||
|
print(usrmerge.debug .. ": " .. msg)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function rootpath(path)
|
||
|
_, _, p = string.find(path, "^/usr(/.*)")
|
||
|
return p
|
||
|
end
|
||
|
|
||
|
function dirname(path)
|
||
|
_, _, d, b = string.find(path, "^(.*)/([^/]*)")
|
||
|
return d
|
||
|
end
|
||
|
|
||
|
function usrmerge._add(rp, relpath)
|
||
|
if not usrmerge_files[rp] then return end
|
||
|
if posix.stat(dirname(rp), "type") ~= "directory" then return end
|
||
|
|
||
|
createit = false
|
||
|
t = posix.stat(rp, "type")
|
||
|
if t == nil then
|
||
|
createit = true
|
||
|
elseif t == "link" then
|
||
|
dst = posix.readlink(rp)
|
||
|
if dst ~= relpath then
|
||
|
_log(rp .. ": fixing incorrect symlink (" .. dst .. " -> " .. relpath)
|
||
|
os.remove(rp)
|
||
|
createit = true
|
||
|
end
|
||
|
else
|
||
|
_log(rp .. " exist but is no link, skipping")
|
||
|
end
|
||
|
if createit then
|
||
|
_log("creating " .. rp .. " -> " .. relpath)
|
||
|
posix.symlink(relpath, rp)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function usrmerge.add(path)
|
||
|
rp = rootpath(path)
|
||
|
usrmerge._add(rp, ".." .. path)
|
||
|
end
|
||
|
|
||
|
-- if a legacy package with a file in /bin gets upgraded, it would
|
||
|
-- remove the link/file in /bin on uninstall. So we have to check
|
||
|
-- there and restore.
|
||
|
function usrmerge.add_postun(rp)
|
||
|
if posix.stat("/usr" .. rp, "type") then
|
||
|
usrmerge._add(rp, "../usr" .. rp)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
-- needed for the build system to install all links of packages that got
|
||
|
-- installed via rpm2cpio so didn't call triggers
|
||
|
function usrmerge.addexisting()
|
||
|
for rp in pairs(usrmerge_files) do
|
||
|
usrmerge.add_postun(rp)
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function usrmerge.remove(path)
|
||
|
rp = rootpath(path)
|
||
|
if not usrmerge_files[rp] then return end
|
||
|
if posix.stat(dirname(rp), "type") ~= "directory" then return end
|
||
|
|
||
|
t = posix.stat(path, "type")
|
||
|
if t then
|
||
|
_log(path .. " still exists, skipping")
|
||
|
return
|
||
|
end
|
||
|
|
||
|
t = posix.stat(rp, "type")
|
||
|
if t == "link" then
|
||
|
relpath = ".." .. path
|
||
|
dst = posix.readlink(rp)
|
||
|
if dst == relpath then
|
||
|
_log("remove " .. rp .. " -> " .. relpath)
|
||
|
os.remove(rp)
|
||
|
else
|
||
|
_log(rp .. " incorrect link (".. dst .."), skipping")
|
||
|
end
|
||
|
elseif t then
|
||
|
_log(rp .. " exist but is no link (".. t .."), skipping")
|
||
|
end
|
||
|
end
|
||
|
|
||
|
function usrmerge.migrate(d)
|
||
|
local errors = 0
|
||
|
for i, name in ipairs(posix.dir(d)) do
|
||
|
if name ~= '.' and name ~= '..' then
|
||
|
local p = d .. "/" .. name
|
||
|
local up = "/usr" .. p
|
||
|
local t = posix.stat(p, "type")
|
||
|
local ut = posix.stat(up, "type")
|
||
|
if ut == nil or (ut == "link" and t ~= "link") then
|
||
|
local f = posix.link
|
||
|
if t == "directory" then
|
||
|
-- can't hardlink dirs so move it
|
||
|
f = posix.rename
|
||
|
end
|
||
|
if ut ~= nil then
|
||
|
_log(" removing " .. up)
|
||
|
posix.unlink(up)
|
||
|
end
|
||
|
local ok, err, e = f(p, up)
|
||
|
if ok == nil then
|
||
|
print("FAILED " .. p .. " -> " .. up .. ": " .. err)
|
||
|
errors = errors + 1
|
||
|
else
|
||
|
_log(p .. " -> " .. up)
|
||
|
end
|
||
|
else
|
||
|
if t == "directory" then
|
||
|
print("BAD " .. p .. " is a directory but " .. up .. "exists")
|
||
|
errors = errors + 1
|
||
|
else
|
||
|
_log("skipped " .. p)
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
end
|
||
|
if errors > 0 then
|
||
|
print("have to continue despire errors")
|
||
|
end
|
||
|
local ok, err, e = posix.rename(d, d .. ".merged")
|
||
|
if ok == nil then
|
||
|
print("FAILED to move " .. d .. " out of the way")
|
||
|
else
|
||
|
ok, err, e = posix.symlink("usr" ..d, d)
|
||
|
if ok == nil then
|
||
|
print("FAILED to recreate " .. d .. " as link. Now we're in deep shit, sorry :-/")
|
||
|
end
|
||
|
end
|
||
|
end
|