File lightdm-ignore-known-symlink-sessions.patch of Package lightdm
From: Fabian Vogt <fvogt@suse.com>
Subject: Do not show symlinked session files more than once
References: boo#1030873
If a session file is a symlink that points into the currently
searched directory, ignore it.
Special take needs to be taken care to map the default-session
hint passed to the greeter correctly. As symlinked sessions
are not available anymore, the target of those needs to be
passed as session name instead.
Index: lightdm-1.30.0/liblightdm-gobject/session.c
===================================================================
--- lightdm-1.30.0.orig/liblightdm-gobject/session.c
+++ lightdm-1.30.0/liblightdm-gobject/session.c
@@ -8,6 +8,10 @@
* See http://www.gnu.org/copyleft/lgpl.html the full text of the license.
*/
+#define _GNU_SOURCE
+#include <libgen.h>
+#include <stdlib.h>
+
#include <string.h>
#include <gio/gdesktopappinfo.h>
@@ -137,6 +141,23 @@ load_sessions_dir (GList *sessions, cons
g_autofree gchar *path = g_build_filename (sessions_dir, filename, NULL);
+ /* Ignore symlinks that point to files we will visit manually later. */
+ if (g_file_test (path, G_FILE_TEST_IS_SYMLINK))
+ {
+ gboolean skip = FALSE;
+
+ char *ltarget = canonicalize_file_name ((char *) path),
+ *ltarget_dir = ltarget == NULL ? NULL : dirname(ltarget);
+
+ /* Link target is absolute -> compare with sessions_dir. */
+ skip = g_strcmp0 (ltarget_dir, sessions_dir) == 0;
+
+ free (ltarget);
+
+ if (skip)
+ continue;
+ }
+
g_autoptr(GKeyFile) key_file = g_key_file_new ();
g_autoptr(GError) e = NULL;
gboolean result = g_key_file_load_from_file (key_file, path, G_KEY_FILE_NONE, &e);
Index: lightdm-1.30.0/src/seat.c
===================================================================
--- lightdm-1.30.0.orig/src/seat.c
+++ lightdm-1.30.0/src/seat.c
@@ -9,6 +9,8 @@
* license.
*/
+#define _GNU_SOURCE
+#include <libgen.h>
#include <stdlib.h>
#include <string.h>
#include <sys/wait.h>
@@ -552,11 +554,87 @@ find_resettable_greeter (Seat *seat)
return NULL;
}
+/* Returns basename of the .desktop file at the specified path.
+ * Returned string needs to be g_free'd. */
+static char *
+desktop_basename (const char *path)
+{
+ if (!path)
+ return NULL;
+
+ char *filename = g_path_get_basename (path);
+ if (!filename)
+ return NULL;
+
+ unsigned int len = strlen(filename);
+ if (len >= 8) /* strlen(".desktop") */
+ filename[len - 8] = '\0';
+
+ return filename;
+}
+
+static char *
+find_session_file (Seat *seat, const char *sessions_dir, const char *session_name)
+{
+ char **dirs;
+ char *ret_path = NULL;
+ int i;
+
+ g_return_val_if_fail (sessions_dir != NULL, NULL);
+ g_return_val_if_fail (session_name != NULL, NULL);
+
+ dirs = g_strsplit (sessions_dir, ":", -1);
+ for (i = 0; dirs[i]; i++)
+ {
+ g_autofree char *filename;
+ char *path;
+
+ filename = g_strdup_printf ("%s.desktop", session_name);
+ path = g_build_filename (dirs[i], filename, NULL);
+ if (g_file_test (path, G_FILE_TEST_EXISTS))
+ {
+ ret_path = path;
+ break;
+ }
+ else
+ g_free (path);
+ }
+ g_strfreev (dirs);
+
+ return ret_path;
+}
+
static void
set_greeter_hints (Seat *seat, Greeter *greeter)
{
greeter_clear_hints (greeter);
- greeter_set_hint (greeter, "default-session", seat_get_string_property (seat, "user-session"));
+
+ /* The user-session might be a symlink to the actual default-session. */
+ const char *user_session = seat_get_string_property (seat, "user-session");
+ char *default_session = NULL;
+
+ const char *sessions_dir = config_get_string (config_get_instance (), "LightDM", "sessions-directory");
+ g_autofree char *user_session_path = find_session_file (seat, sessions_dir, user_session);
+ if (g_file_test (user_session_path, G_FILE_TEST_IS_SYMLINK))
+ {
+ char *ltarget = canonicalize_file_name ((char*) user_session_path);
+
+ /* TODO: Check that the link target points into a valid session_dir. */
+
+ if (g_str_has_suffix (ltarget, ".desktop"))
+ default_session = desktop_basename (ltarget);
+
+ free(ltarget);
+ }
+
+ if (default_session)
+ {
+ greeter_set_hint (greeter, "default-session", default_session);
+ g_free (default_session);
+ }
+ else
+ greeter_set_hint (greeter, "default-session", user_session);
+
greeter_set_hint (greeter, "hide-users", seat_get_boolean_property (seat, "greeter-hide-users") ? "true" : "false");
greeter_set_hint (greeter, "show-manual-login", seat_get_boolean_property (seat, "greeter-show-manual-login") ? "true" : "false");
greeter_set_hint (greeter, "show-remote-login", seat_get_boolean_property (seat, "greeter-show-remote-login") ? "true" : "false");