summaryrefslogtreecommitdiff
path: root/src/shared/install.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-08-13 01:27:21 -0400
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2016-08-19 09:55:54 -0400
commit25ea92778d5f4339e07c152a99d16223f43ad681 (patch)
tree01c0b516a67f1a57da18087a0f2b5a34c523bbde /src/shared/install.c
parent60bec8e4031367869520280350fa1523625d682b (diff)
shared/install: when creating symlinks, keep existing relative symlinks
Running preset-all on a system installed from rpms or even created using make install would remove and recreate a lot of symlinks, changing relative to absolute symlinks. In general relative symlinks are nicer, so there is no reason to change them, and those spurious changes were obscuring more interesting stuff. $ make install DESTDIR=/var/tmp/inst1 $ systemctl preset-all --root=/var/tmp/inst1 (before) Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service. Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/remote-fs.target → /usr/lib/systemd/system/remote-fs.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket. Removed /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-networkd.socket → /usr/lib/systemd/system/systemd-networkd.socket. Removed /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service. Created symlink /var/tmp/inst1/etc/systemd/system/getty.target.wants/getty@tty1.service → /usr/lib/systemd/system/getty@.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service. Removed /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service. Created symlink /var/tmp/inst1/etc/systemd/system/sysinit.target.wants/systemd-timesyncd.service → /usr/lib/systemd/system/systemd-timesyncd.service. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-resolved.service → /usr/lib/systemd/system/systemd-resolved.service. Removed /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-networkd.service → /usr/lib/systemd/system/systemd-networkd.service. (after) Removed /var/tmp/inst1/etc/systemd/system/network-online.target.wants/systemd-networkd-wait-online.service. Created symlink /var/tmp/inst1/etc/systemd/system/ctrl-alt-del.target → /usr/lib/systemd/system/exit.target. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/machines.target → /usr/lib/systemd/system/machines.target. Created symlink /var/tmp/inst1/etc/systemd/system/sockets.target.wants/systemd-journal-remote.socket → /usr/lib/systemd/system/systemd-journal-remote.socket. Created symlink /var/tmp/inst1/etc/systemd/system/multi-user.target.wants/systemd-journal-upload.service → /usr/lib/systemd/system/systemd-journal-upload.service.
Diffstat (limited to 'src/shared/install.c')
-rw-r--r--src/shared/install.c23
1 files changed, 21 insertions, 2 deletions
diff --git a/src/shared/install.c b/src/shared/install.c
index ad2e619237..6c7eb9b2ef 100644
--- a/src/shared/install.c
+++ b/src/shared/install.c
@@ -393,6 +393,21 @@ void unit_file_dump_changes(int r, const char *verb, const UnitFileChange *chang
log_error_errno(r, "Failed to %s: %m.", verb);
}
+/**
+ * Checks if two paths or symlinks from wd are the same, when root is the root of the filesystem.
+ * wc should be the full path in the host file system.
+ */
+static bool chroot_symlinks_same(const char *root, const char *wd, const char *a, const char *b) {
+ assert(path_is_absolute(wd));
+
+ /* This will give incorrect results if the paths are relative and go outside
+ * of the chroot. False negatives are possible. */
+
+ a = strjoina(path_is_absolute(a) ? root : wd, "/", a);
+ b = strjoina(path_is_absolute(b) ? root : wd, "/", b);
+ return path_equal_or_files_same(a, b);
+}
+
static int create_symlink(
const LookupPaths *paths,
const char *old_path,
@@ -401,7 +416,7 @@ static int create_symlink(
UnitFileChange **changes,
unsigned *n_changes) {
- _cleanup_free_ char *dest = NULL;
+ _cleanup_free_ char *dest = NULL, *dirname = NULL;
const char *rp;
int r;
@@ -442,7 +457,11 @@ static int create_symlink(
return r;
}
- if (path_equal(dest, old_path))
+ dirname = dirname_malloc(new_path);
+ if (!dirname)
+ return -ENOMEM;
+
+ if (chroot_symlinks_same(paths->root_dir, dirname, dest, old_path))
return 1;
if (!force) {