From 930b3d673df8120d1499df47ca9080bb935ec8e0 Mon Sep 17 00:00:00 2001 From: Alexander Larsson Date: Wed, 2 Oct 2019 15:15:36 +0200 Subject: [PATCH] Fix detection of exported dbus-services with dbus-broker Rather than unlinking and symlinking the new value we symling into a temporary name and then atomically renames on top of the (possibly) pre-existing file. This has two advantages. First it is atomic, whereas the previous code could end up removing the old code without creating the new one, and secondly this will generate a move inotify event which is what dbus-broker uses to detect changes in the services file directory. Fixes https://github.com/flatpak/flatpak/issues/3145 --- common/flatpak-dir.c | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/common/flatpak-dir.c b/common/flatpak-dir.c index e876b762..640c346f 100644 --- a/common/flatpak-dir.c +++ b/common/flatpak-dir.c @@ -7091,20 +7091,31 @@ export_dir (int source_parent_fd, } else if (S_ISREG (stbuf.st_mode)) { + g_autofree char *symlink_name = g_strdup (".export-symlink-XXXXXX"); g_autofree gchar *target = NULL; target = g_build_filename (source_symlink_prefix, dent->d_name, NULL); - if (unlinkat (destination_dfd, dent->d_name, 0) != 0 && errno != ENOENT) + for (int count = 0; count < 100; count++) { - glnx_set_error_from_errno (error); - goto out; - } + glnx_gen_temp_name (symlink_name); - if (symlinkat (target, destination_dfd, dent->d_name) != 0) - { - glnx_set_error_from_errno (error); - goto out; + if (symlinkat (target, destination_dfd, symlink_name) != 0) + { + if (errno == EEXIST) + continue; + + glnx_set_error_from_errno (error); + goto out; + } + + if (renameat (destination_dfd, symlink_name, destination_dfd, dent->d_name) != 0) + { + glnx_set_error_from_errno (error); + goto out; + } + + break; } } }