|
|
ece282 |
From dee5f443807fee3b5b279d0488df617eeed52230 Mon Sep 17 00:00:00 2001
|
|
|
ece282 |
From: Robert Ancell <robert.ancell@canonical.com>
|
|
|
ece282 |
Date: Thu, 6 Sep 2018 14:37:39 +1200
|
|
|
ece282 |
Subject: [PATCH] daemon: Fix warnings about type-punning
|
|
|
ece282 |
|
|
|
ece282 |
---
|
|
|
ece282 |
src/daemon.c | 26 +++++++++++++++-----------
|
|
|
ece282 |
1 file changed, 15 insertions(+), 11 deletions(-)
|
|
|
ece282 |
|
|
|
ece282 |
diff --git a/src/daemon.c b/src/daemon.c
|
|
|
ece282 |
index 2587b8a..00dff51 100644
|
|
|
ece282 |
--- a/src/daemon.c
|
|
|
ece282 |
+++ b/src/daemon.c
|
|
|
ece282 |
@@ -232,117 +232,118 @@ entry_generator_fgetpwent (Daemon *daemon,
|
|
|
ece282 |
pwent = fgetpwent (generator_state->fp);
|
|
|
ece282 |
if (pwent != NULL) {
|
|
|
ece282 |
shadow_entry_buffers = g_hash_table_lookup (generator_state->users, pwent->pw_name);
|
|
|
ece282 |
|
|
|
ece282 |
if (shadow_entry_buffers != NULL) {
|
|
|
ece282 |
*spent = &shadow_entry_buffers->spbuf;
|
|
|
ece282 |
}
|
|
|
ece282 |
return pwent;
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Last iteration */
|
|
|
ece282 |
fclose (generator_state->fp);
|
|
|
ece282 |
g_hash_table_unref (generator_state->users);
|
|
|
ece282 |
g_free (generator_state);
|
|
|
ece282 |
*state = NULL;
|
|
|
ece282 |
|
|
|
ece282 |
return NULL;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static struct passwd *
|
|
|
ece282 |
entry_generator_cachedir (Daemon *daemon,
|
|
|
ece282 |
GHashTable *users,
|
|
|
ece282 |
gpointer *state,
|
|
|
ece282 |
struct spwd **shadow_entry)
|
|
|
ece282 |
{
|
|
|
ece282 |
struct passwd *pwent;
|
|
|
ece282 |
g_autoptr(GError) error = NULL;
|
|
|
ece282 |
gboolean regular;
|
|
|
ece282 |
GHashTableIter iter;
|
|
|
ece282 |
- const gchar *name;
|
|
|
ece282 |
- User *user;
|
|
|
ece282 |
+ gpointer key, value;
|
|
|
ece282 |
GDir *dir;
|
|
|
ece282 |
|
|
|
ece282 |
/* First iteration */
|
|
|
ece282 |
if (*state == NULL) {
|
|
|
ece282 |
*state = g_dir_open (USERDIR, 0, &error);
|
|
|
ece282 |
if (error != NULL) {
|
|
|
ece282 |
if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
|
|
|
ece282 |
g_warning ("couldn't list user cache directory: %s", USERDIR);
|
|
|
ece282 |
return NULL;
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Every iteration */
|
|
|
ece282 |
|
|
|
ece282 |
/*
|
|
|
ece282 |
* Use names of files of regular type to lookup information
|
|
|
ece282 |
* about each user. Loop until we find something valid.
|
|
|
ece282 |
*/
|
|
|
ece282 |
dir = *state;
|
|
|
ece282 |
while (TRUE) {
|
|
|
ece282 |
const gchar *name;
|
|
|
ece282 |
g_autofree gchar *filename = NULL;
|
|
|
ece282 |
|
|
|
ece282 |
name = g_dir_read_name (dir);
|
|
|
ece282 |
if (name == NULL)
|
|
|
ece282 |
break;
|
|
|
ece282 |
|
|
|
ece282 |
/* Only load files in this directory */
|
|
|
ece282 |
filename = g_build_filename (USERDIR, name, NULL);
|
|
|
ece282 |
regular = g_file_test (filename, G_FILE_TEST_IS_REGULAR);
|
|
|
ece282 |
|
|
|
ece282 |
if (regular) {
|
|
|
ece282 |
errno = 0;
|
|
|
ece282 |
pwent = getpwnam (name);
|
|
|
ece282 |
if (pwent != NULL) {
|
|
|
ece282 |
*shadow_entry = getspnam (pwent->pw_name);
|
|
|
ece282 |
|
|
|
ece282 |
return pwent;
|
|
|
ece282 |
} else if (errno == 0) {
|
|
|
ece282 |
g_debug ("user '%s' in cache dir but not present on system, removing", name);
|
|
|
ece282 |
remove_cache_files (name);
|
|
|
ece282 |
}
|
|
|
ece282 |
else {
|
|
|
ece282 |
g_warning ("failed to check if user '%s' in cache dir is present on system: %s",
|
|
|
ece282 |
name, g_strerror (errno));
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Last iteration */
|
|
|
ece282 |
g_dir_close (dir);
|
|
|
ece282 |
|
|
|
ece282 |
/* Update all the users from the files in the cache dir */
|
|
|
ece282 |
g_hash_table_iter_init (&iter, users);
|
|
|
ece282 |
- while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&user)) {
|
|
|
ece282 |
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
|
ece282 |
+ const gchar *name = key;
|
|
|
ece282 |
+ User *user = value;
|
|
|
ece282 |
g_autofree gchar *filename = NULL;
|
|
|
ece282 |
g_autoptr(GKeyFile) key_file = NULL;
|
|
|
ece282 |
|
|
|
ece282 |
filename = g_build_filename (USERDIR, name, NULL);
|
|
|
ece282 |
key_file = g_key_file_new ();
|
|
|
ece282 |
if (g_key_file_load_from_file (key_file, filename, 0, NULL))
|
|
|
ece282 |
user_update_from_keyfile (user, key_file);
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
*state = NULL;
|
|
|
ece282 |
return NULL;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static struct passwd *
|
|
|
ece282 |
entry_generator_requested_users (Daemon *daemon,
|
|
|
ece282 |
GHashTable *users,
|
|
|
ece282 |
gpointer *state,
|
|
|
ece282 |
struct spwd **shadow_entry)
|
|
|
ece282 |
{
|
|
|
ece282 |
struct passwd *pwent;
|
|
|
ece282 |
GList *node;
|
|
|
ece282 |
|
|
|
ece282 |
/* First iteration */
|
|
|
ece282 |
if (*state == NULL) {
|
|
|
ece282 |
*state = daemon->priv->explicitly_requested_users;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Every iteration */
|
|
|
ece282 |
|
|
|
ece282 |
if (g_hash_table_size (users) < MAX_LOCAL_USERS) {
|
|
|
ece282 |
@@ -423,129 +424,131 @@ load_entries (Daemon *daemon,
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
if (!explicitly_requested) {
|
|
|
ece282 |
user_set_cached (user, TRUE);
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Generator should have cleaned up */
|
|
|
ece282 |
g_assert (generator_state == NULL);
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static GHashTable *
|
|
|
ece282 |
create_users_hash_table (void)
|
|
|
ece282 |
{
|
|
|
ece282 |
return g_hash_table_new_full (g_str_hash,
|
|
|
ece282 |
g_str_equal,
|
|
|
ece282 |
g_free,
|
|
|
ece282 |
g_object_unref);
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static void
|
|
|
ece282 |
reload_users (Daemon *daemon)
|
|
|
ece282 |
{
|
|
|
ece282 |
AccountsAccounts *accounts = ACCOUNTS_ACCOUNTS (daemon);
|
|
|
ece282 |
gboolean had_no_users, has_no_users, had_multiple_users, has_multiple_users;
|
|
|
ece282 |
GHashTable *users;
|
|
|
ece282 |
GHashTable *old_users;
|
|
|
ece282 |
GHashTable *local;
|
|
|
ece282 |
GHashTableIter iter;
|
|
|
ece282 |
gsize number_of_normal_users = 0;
|
|
|
ece282 |
- gpointer name;
|
|
|
ece282 |
- User *user;
|
|
|
ece282 |
+ gpointer name, value;
|
|
|
ece282 |
|
|
|
ece282 |
/* Track the users that we saw during our (re)load */
|
|
|
ece282 |
users = create_users_hash_table ();
|
|
|
ece282 |
|
|
|
ece282 |
/*
|
|
|
ece282 |
* NOTE: As we load data from all the sources, notifies are
|
|
|
ece282 |
* frozen in load_entries() and then thawed as we process
|
|
|
ece282 |
* them below.
|
|
|
ece282 |
*/
|
|
|
ece282 |
|
|
|
ece282 |
/* Load the local users into our hash table */
|
|
|
ece282 |
load_entries (daemon, users, FALSE, entry_generator_fgetpwent);
|
|
|
ece282 |
local = g_hash_table_new (g_str_hash, g_str_equal);
|
|
|
ece282 |
g_hash_table_iter_init (&iter, users);
|
|
|
ece282 |
while (g_hash_table_iter_next (&iter, &name, NULL))
|
|
|
ece282 |
g_hash_table_add (local, name);
|
|
|
ece282 |
|
|
|
ece282 |
/* and add users to hash table that were explicitly requested */
|
|
|
ece282 |
load_entries (daemon, users, TRUE, entry_generator_requested_users);
|
|
|
ece282 |
|
|
|
ece282 |
/* Now add/update users from other sources, possibly non-local */
|
|
|
ece282 |
load_entries (daemon, users, FALSE, entry_generator_cachedir);
|
|
|
ece282 |
|
|
|
ece282 |
wtmp_helper_update_login_frequencies (users);
|
|
|
ece282 |
|
|
|
ece282 |
/* Count the non-system users. Mark which users are local, which are not. */
|
|
|
ece282 |
g_hash_table_iter_init (&iter, users);
|
|
|
ece282 |
- while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
|
|
|
ece282 |
+ while (g_hash_table_iter_next (&iter, &name, &value)) {
|
|
|
ece282 |
+ User *user = value;
|
|
|
ece282 |
if (!user_get_system_account (user))
|
|
|
ece282 |
number_of_normal_users++;
|
|
|
ece282 |
user_update_local_account_property (user, g_hash_table_lookup (local, name) != NULL);
|
|
|
ece282 |
}
|
|
|
ece282 |
g_hash_table_destroy (local);
|
|
|
ece282 |
|
|
|
ece282 |
had_no_users = accounts_accounts_get_has_no_users (accounts);
|
|
|
ece282 |
has_no_users = number_of_normal_users == 0;
|
|
|
ece282 |
|
|
|
ece282 |
if (had_no_users != has_no_users)
|
|
|
ece282 |
accounts_accounts_set_has_no_users (accounts, has_no_users);
|
|
|
ece282 |
|
|
|
ece282 |
had_multiple_users = accounts_accounts_get_has_multiple_users (accounts);
|
|
|
ece282 |
has_multiple_users = number_of_normal_users > 1;
|
|
|
ece282 |
|
|
|
ece282 |
if (had_multiple_users != has_multiple_users)
|
|
|
ece282 |
accounts_accounts_set_has_multiple_users (accounts, has_multiple_users);
|
|
|
ece282 |
|
|
|
ece282 |
/* Swap out the users */
|
|
|
ece282 |
old_users = daemon->priv->users;
|
|
|
ece282 |
daemon->priv->users = users;
|
|
|
ece282 |
|
|
|
ece282 |
/* Remove all the old users */
|
|
|
ece282 |
g_hash_table_iter_init (&iter, old_users);
|
|
|
ece282 |
- while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
|
|
|
ece282 |
+ while (g_hash_table_iter_next (&iter, &name, &value)) {
|
|
|
ece282 |
+ User *user = value;
|
|
|
ece282 |
User *refreshed_user;
|
|
|
ece282 |
|
|
|
ece282 |
refreshed_user = g_hash_table_lookup (users, name);
|
|
|
ece282 |
|
|
|
ece282 |
if (!refreshed_user || (user_get_cached (user) && !user_get_cached (refreshed_user))) {
|
|
|
ece282 |
accounts_accounts_emit_user_deleted (ACCOUNTS_ACCOUNTS (daemon),
|
|
|
ece282 |
user_get_object_path (user));
|
|
|
ece282 |
user_unregister (user);
|
|
|
ece282 |
}
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
/* Register all the new users */
|
|
|
ece282 |
g_hash_table_iter_init (&iter, users);
|
|
|
ece282 |
- while (g_hash_table_iter_next (&iter, &name, (gpointer *)&user)) {
|
|
|
ece282 |
+ while (g_hash_table_iter_next (&iter, &name, &value)) {
|
|
|
ece282 |
+ User *user = value;
|
|
|
ece282 |
User *stale_user;
|
|
|
ece282 |
|
|
|
ece282 |
stale_user = g_hash_table_lookup (old_users, name);
|
|
|
ece282 |
|
|
|
ece282 |
if (!stale_user || (!user_get_cached (stale_user) && user_get_cached (user))) {
|
|
|
ece282 |
user_register (user);
|
|
|
ece282 |
accounts_accounts_emit_user_added (ACCOUNTS_ACCOUNTS (daemon),
|
|
|
ece282 |
user_get_object_path (user));
|
|
|
ece282 |
}
|
|
|
ece282 |
g_object_thaw_notify (G_OBJECT (user));
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
g_hash_table_destroy (old_users);
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static gboolean
|
|
|
ece282 |
reload_users_timeout (Daemon *daemon)
|
|
|
ece282 |
{
|
|
|
ece282 |
reload_users (daemon);
|
|
|
ece282 |
daemon->priv->reload_id = 0;
|
|
|
ece282 |
|
|
|
ece282 |
return FALSE;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static gboolean load_autologin (Daemon *daemon,
|
|
|
ece282 |
gchar **name,
|
|
|
ece282 |
gboolean *enabled,
|
|
|
ece282 |
GError **error);
|
|
|
ece282 |
|
|
|
ece282 |
static gboolean
|
|
|
ece282 |
@@ -932,69 +935,70 @@ typedef struct {
|
|
|
ece282 |
} ListUserData;
|
|
|
ece282 |
|
|
|
ece282 |
|
|
|
ece282 |
static ListUserData *
|
|
|
ece282 |
list_user_data_new (Daemon *daemon,
|
|
|
ece282 |
GDBusMethodInvocation *context)
|
|
|
ece282 |
{
|
|
|
ece282 |
ListUserData *data;
|
|
|
ece282 |
|
|
|
ece282 |
data = g_new0 (ListUserData, 1);
|
|
|
ece282 |
|
|
|
ece282 |
data->daemon = g_object_ref (daemon);
|
|
|
ece282 |
data->context = context;
|
|
|
ece282 |
|
|
|
ece282 |
return data;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static void
|
|
|
ece282 |
list_user_data_free (ListUserData *data)
|
|
|
ece282 |
{
|
|
|
ece282 |
g_object_unref (data->daemon);
|
|
|
ece282 |
g_free (data);
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static gboolean
|
|
|
ece282 |
finish_list_cached_users (gpointer user_data)
|
|
|
ece282 |
{
|
|
|
ece282 |
ListUserData *data = user_data;
|
|
|
ece282 |
g_autoptr(GPtrArray) object_paths = NULL;
|
|
|
ece282 |
GHashTableIter iter;
|
|
|
ece282 |
- const gchar *name;
|
|
|
ece282 |
- User *user;
|
|
|
ece282 |
+ gpointer key, value;
|
|
|
ece282 |
uid_t uid;
|
|
|
ece282 |
const gchar *shell;
|
|
|
ece282 |
|
|
|
ece282 |
object_paths = g_ptr_array_new ();
|
|
|
ece282 |
|
|
|
ece282 |
g_hash_table_iter_init (&iter, data->daemon->priv->users);
|
|
|
ece282 |
- while (g_hash_table_iter_next (&iter, (gpointer *)&name, (gpointer *)&user)) {
|
|
|
ece282 |
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
|
|
|
ece282 |
+ const gchar *name = key;
|
|
|
ece282 |
+ User *user = value;
|
|
|
ece282 |
uid = user_get_uid (user);
|
|
|
ece282 |
shell = user_get_shell (user);
|
|
|
ece282 |
|
|
|
ece282 |
if (!user_classify_is_human (uid, name, shell, NULL)) {
|
|
|
ece282 |
g_debug ("user %s %ld excluded", name, (long) uid);
|
|
|
ece282 |
continue;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
if (!user_get_cached (user)) {
|
|
|
ece282 |
g_debug ("user %s %ld not cached", name, (long) uid);
|
|
|
ece282 |
continue;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
g_debug ("user %s %ld not excluded", name, (long) uid);
|
|
|
ece282 |
g_ptr_array_add (object_paths, (gpointer) user_get_object_path (user));
|
|
|
ece282 |
}
|
|
|
ece282 |
g_ptr_array_add (object_paths, NULL);
|
|
|
ece282 |
|
|
|
ece282 |
accounts_accounts_complete_list_cached_users (NULL, data->context, (const gchar * const *) object_paths->pdata);
|
|
|
ece282 |
|
|
|
ece282 |
list_user_data_free (data);
|
|
|
ece282 |
|
|
|
ece282 |
return FALSE;
|
|
|
ece282 |
}
|
|
|
ece282 |
|
|
|
ece282 |
static gboolean
|
|
|
ece282 |
daemon_list_cached_users (AccountsAccounts *accounts,
|
|
|
ece282 |
GDBusMethodInvocation *context)
|
|
|
ece282 |
{
|
|
|
ece282 |
Daemon *daemon = (Daemon*)accounts;
|
|
|
ece282 |
--
|
|
|
ece282 |
2.17.1
|
|
|
ece282 |
|