[mojosetup] Patch: Fix handling of dead symbolic links on upgrades.

Francois Gouget fgouget at codeweavers.com
Fri Mar 6 10:49:39 EST 2015


MojoSetup.platform.exists() will return false for dead symbolic links. 
Yet they still have to be moved out of the way on upgrade, or deleted if 
they are no longer relevant.

There are two scenarios where symbolic links are mishandled.
The first scenario typically happens for regular release -> 
nightly -> regular release roundtrips.
 * Initially the install has a valid lib/libfoo.so.8 symbolic link to 
   libfoo.so.8.1.0.

 * During the upgrade libfoo.so.8.1.0 is replaced with libfoo.so.9.0.0. 
   So libfoo.so.8.1.0 gets deleted by the 'Move away obsolete files' 
   loop.

 * That loop then considers the 'lib/libfoo.so.8' symbolic link. However 
   it is now broken so MojoSetup.platform.exists() returns false, so 
   backup_file() is not called and lib/libfoo.so.8 is left intact except 
   now it's not tracked by MojoSetup anymore.

 * If the user then downgrades, MojoSetup will think this was a user 
   created file and ask whether it is ok to overwrite it. The user does 
   not know anything about this file and is confused.

The second scenario is as follows:
 * For whatever reason the file the lib/libfoo.so.8 symbolic link points 
   to was deleted. Maybe the user messed with his install or whatever.

 * The user then tries to reinstall/upgrade the product to fix things.

 * install_archive_entry() is called to (re)create the lib/libfoo.so.8 
   symbolic link.

 * In turn it calls permit_write() which return true without doing 
   anything because MojoSetup.platform.exists() returns false on broken 
   symbolic links.

 * install_archive_entry() then calls install_archive_entity() which 
   calls install_symlink() which calls MojoSetup.platform.symlink() 
   which fails because the symbolic link already exists.

 * This causes the reinstall/upgrade to fail and roll things back.

The patch below prevents both scenarios from happening.


diff --git a/scripts/mojosetup_mainline.lua b/scripts/mojosetup_mainline.lua
index 4602220..b151627 100644
--- a/scripts/mojosetup_mainline.lua
+++ b/scripts/mojosetup_mainline.lua
@@ -551,7 +551,7 @@ end
 
 local function permit_write(dest, filename, type, file)
     local allowoverwrite = true
-    if MojoSetup.platform.exists(dest) then
+    if MojoSetup.platform.exists(dest) or MojoSetup.platform.issymlink(dest) then
         if type == "dir" then
             allowoverwrite = true
         else
@@ -1908,10 +1908,10 @@ local function do_install(install)
         --  that's ok because we will recreate them if the installation
         --  succeeds, and restore them if it fails.
         for path,file in pairs(MojoSetup.oldfiles) do
-            if file.seen == nil and file.type == 'file' then
+            if file.seen == nil and (file.type == 'file' or file.type == 'symlink') then
                 local fullpath = MojoSetup.destination .. "/" .. path
-                if MojoSetup.platform.exists(fullpath) then
-                    MojoSetup.loginfo("Obsoleting file '" .. path .. "'")
+                if MojoSetup.platform.exists(fullpath) or MojoSetup.platform.issymlink(fullpath) then
+                    MojoSetup.loginfo("Obsoleting " .. file.type .. " '" .. path .. "'")
                     backup_file(fullpath)
                 end
             end


-- 
Francois Gouget <fgouget at codeweavers.com>


More information about the mojosetup mailing list