summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--dbus/dbus-userdb-util.c107
1 files changed, 98 insertions, 9 deletions
diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
index 8361fcf3..f4d1f0c9 100644
--- a/dbus/dbus-userdb-util.c
+++ b/dbus/dbus-userdb-util.c
@@ -35,6 +35,28 @@
* @{
*/
+#if defined(HAVE_CONSOLEKIT_DATABASE)
+static DBusDesktopFile *ckit_database = NULL;
+static DBusHashTable *ckit_cache = NULL;
+
+static void
+ckit_cleanup(void *data)
+{
+ if (ckit_database)
+ {
+ _dbus_desktop_file_free(ckit_database);
+ ckit_database = NULL;
+ }
+
+ if (ckit_cache)
+ {
+ _dbus_hash_table_unref(ckit_cache);
+ ckit_cache = NULL;
+ }
+}
+
+#endif
+
/**
* Checks to see if the UID sent in is the console user
*
@@ -49,19 +71,68 @@ _dbus_is_console_user (dbus_uid_t uid,
#if defined(HAVE_CONSOLEKIT_DATABASE)
- DBusDesktopFile *f;
+
const char *section;
dbus_bool_t found = FALSE;
DBusString fn;
unsigned i = 0;
+ void *e;
_dbus_string_init_const(&fn, DBUS_CONSOLEKIT_DATABASE);
- f = _dbus_desktop_file_load(&fn, error);
- if (!f)
- return FALSE;
+ _dbus_user_database_lock_system ();
+
+ /* Flush database if it changed */
+ if (ckit_database &&
+ _dbus_desktop_file_changed(ckit_database, &fn))
+ {
+ _dbus_desktop_file_free(ckit_database);
+ ckit_database = NULL;
+
+ if (ckit_cache)
+ _dbus_hash_table_remove_all(ckit_cache);
+ }
+
+ /* Initialize cache */
+ if (!ckit_cache)
+ {
+ ckit_cache = _dbus_hash_table_new(DBUS_HASH_ULONG, NULL, NULL);
+ if (!ckit_cache)
+ {
+ _dbus_user_database_unlock_system ();
+ _DBUS_SET_OOM(error);
+ return FALSE;
+ }
+
+ if (!_dbus_register_shutdown_func(ckit_cleanup, NULL))
+ {
+ ckit_cleanup(NULL);
+ _dbus_user_database_unlock_system ();
+ _DBUS_SET_OOM(error);
+ return FALSE;
+ }
+ }
+
+ /* Load database */
+ if (!ckit_database)
+ {
+ ckit_database = _dbus_desktop_file_load(&fn, error);
+ if (!ckit_database)
+ {
+ _dbus_user_database_unlock_system ();
+ return FALSE;
+ }
+ }
+
+ /* Check cache first */
+ e = _dbus_hash_table_lookup_ulong(ckit_cache, (unsigned long) uid);
+ if (e)
+ {
+ _dbus_user_database_unlock_system ();
+ return _DBUS_POINTER_TO_INT(e) > 0;
+ }
- while ((section = _dbus_desktop_file_get_section(f, i++)))
+ while ((section = _dbus_desktop_file_get_section(ckit_database, i++)))
{
const char *val;
char *e = NULL;
@@ -70,7 +141,7 @@ _dbus_is_console_user (dbus_uid_t uid,
if (strncmp(section, "Session ", 8))
continue;
- if (!_dbus_desktop_file_get_raw(f, section, "uid", &val))
+ if (!_dbus_desktop_file_get_raw(ckit_database, section, "uid", &val))
continue;
errno = 0;
@@ -85,7 +156,11 @@ _dbus_is_console_user (dbus_uid_t uid,
}
}
- _dbus_desktop_file_free(f);
+ /* Cache for later. We don't care if that worked. If it didn't the
+ only price we pay is that we have to recheck next time */
+ _dbus_hash_table_insert_ulong(ckit_cache, (unsigned long) uid, _DBUS_INT_TO_POINTER(found ? 1 : -1));
+
+ _dbus_user_database_unlock_system ();
return found;
#elif defined(HAVE_CONSOLE_OWNER_FILE)
@@ -486,8 +561,22 @@ _dbus_userdb_test (const char *test_data_dir)
printf ("\n");
dbus_error_init(&error);
- printf ("Is Console user: %i\n",
- _dbus_is_console_user(uid, &error));
+ printf ("1000 is Console user: %i\n", _dbus_is_console_user(1000, &error));
+ printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
+ dbus_error_free(&error);
+
+ dbus_error_init(&error);
+ printf ("0 is Console user: %i\n", _dbus_is_console_user(0, &error));
+ printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
+ dbus_error_free(&error);
+
+ dbus_error_init(&error);
+ printf ("1001 is Console user: %i\n", _dbus_is_console_user(1001, &error));
+ printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
+ dbus_error_free(&error);
+
+ dbus_error_init(&error);
+ printf ("1000 is Console user: %i\n", _dbus_is_console_user(1000, &error));
printf ("Invocation was OK: %s\n", error.message ? error.message : "yes");
dbus_error_free(&error);