696e2f2
From bfcaa19428a32234356fde460ef556c23bf80f4a Mon Sep 17 00:00:00 2001
696e2f2
From: =?UTF-8?q?Zbigniew=20J=C4=99drzejewski-Szmek?= <zbyszek@in.waw.pl>
696e2f2
Date: Sat, 13 Aug 2016 01:27:21 -0400
696e2f2
Subject: [PATCH] shared/install: when creating symlinks, keep existing
696e2f2
 relative symlinks
696e2f2
MIME-Version: 1.0
696e2f2
Content-Type: text/plain; charset=UTF-8
696e2f2
Content-Transfer-Encoding: 8bit
696e2f2
696e2f2
Running preset-all on a system installed from rpms or even created
696e2f2
using make install would remove and recreate a lot of symlinks, changing
696e2f2
relative to absolute symlinks. In general relative symlinks are nicer,
696e2f2
so there is no reason to change them, and those spurious changes were
696e2f2
obscuring more interesting stuff.
696e2f2
696e2f2
$ make install DESTDIR=/var/tmp/inst1
696e2f2
696e2f2
$ systemctl preset-all --root=/var/tmp/inst1
696e2f2
(before)
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target → /usr/lib/systemd/system/remote-fs.target.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket → /usr/lib/systemd/system/systemd-networkd.socket.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service → /usr/lib/systemd/system/getty@.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service → /usr/lib/systemd/system/systemd-timesyncd.service.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /usr/lib/systemd/system/systemd-resolved.service.
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service → /usr/lib/systemd/system/systemd-networkd.service.
696e2f2
696e2f2
(after)
696e2f2
Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket.
696e2f2
Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service.
696e2f2
696e2f2
(cherry picked from commit 25ea92778d5f4339e07c152a99d16223f43ad681)
696e2f2
---
696e2f2
 src/shared/install.c | 23 +++++++++++++++++++++--
696e2f2
 1 file changed, 21 insertions(+), 2 deletions(-)
696e2f2
696e2f2
diff --git a/src/shared/install.c b/src/shared/install.c
696e2f2
index 8c45725f5a..9ce8e4d390 100644
696e2f2
--- a/src/shared/install.c
696e2f2
+++ b/src/shared/install.c
696e2f2
@@ -393,6 +393,21 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
696e2f2
                 log_error_errno(r, "Failed to %s: %m.", verb);
696e2f2
 }
696e2f2
 
696e2f2
+/**
696e2f2
+ * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
696e2f2
+ * wc should be the full path in the host file system.
696e2f2
+ */
696e2f2
+static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) {
696e2f2
+        assert(path_is_absolute(wd));
696e2f2
+
696e2f2
+        /* This will give incorrect results if the paths are relative and go outside
696e2f2
+         * of the chroot. False negatives are possible. */
696e2f2
+
696e2f2
+        a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
696e2f2
+        b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
696e2f2
+        return path_equal_or_files_same(a, b);
696e2f2
+}
696e2f2
+
696e2f2
 static int create_symlink(
696e2f2
                 const LookupPaths *paths,
696e2f2
                 const char *old_path,
696e2f2
@@ -401,7 +416,7 @@ static int create_symlink(
696e2f2
                 UnitFileChange **changes,
696e2f2
                 unsigned *n_changes) {
696e2f2
 
696e2f2
-        _cleanup_free_ char *dest = NULL;
696e2f2
+        _cleanup_free_ char *dest = NULL, *dirname = NULL;
696e2f2
         const char *rp;
696e2f2
         int r;
696e2f2
 
696e2f2
@@ -442,7 +457,11 @@ static int create_symlink(
696e2f2
                 return r;
696e2f2
         }
696e2f2
 
696e2f2
-        if (path_equal(dest, old_path))
696e2f2
+        dirname = dirname_malloc(new_path);
696e2f2
+        if (!dirname)
696e2f2
+                return -ENOMEM;
696e2f2
+
696e2f2
+        if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path))
696e2f2
                 return 1;
696e2f2
 
696e2f2
         if (!force) {
696e2f2
-- 
696e2f2
2.9.0
696e2f2