summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-05-07 16:42:15 +0200
committerThomas Haller <thaller@redhat.com>2019-05-07 16:42:15 +0200
commit7a5bf59e5f5133cedc8d06080cc47392e2e7afc4 (patch)
treefd4283279e5f0daf66de8c7e2e0b7ed21f98692d
parent4a078d5065b7c771bf71f79432a645798e5536e3 (diff)
parent8a78493de1c33d879082e55edca1ee6e672efc40 (diff)
downloadNetworkManager-7a5bf59e5f5133cedc8d06080cc47392e2e7afc4.tar.gz
core: merge branch 'th/cache-state-keyfiles'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/134
-rw-r--r--Makefile.am2
-rw-r--r--libnm-core/nm-keyfile-utils.c2
-rw-r--r--shared/meson.build1
-rw-r--r--shared/nm-glib-aux/nm-keyfile-aux.c413
-rw-r--r--shared/nm-glib-aux/nm-keyfile-aux.h78
-rw-r--r--shared/nm-glib-aux/nm-logging-fwd.h17
-rw-r--r--shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h20
-rw-r--r--src/devices/nm-device.c2
-rw-r--r--src/devices/wifi/nm-iwd-manager.c2
-rw-r--r--src/main.c2
-rw-r--r--src/nm-active-connection.c2
-rw-r--r--src/nm-checkpoint.c8
-rw-r--r--src/nm-logging.c9
-rw-r--r--src/nm-manager.c2
-rw-r--r--src/settings/nm-settings-connection.c293
-rw-r--r--src/settings/nm-settings-connection.h13
-rw-r--r--src/settings/nm-settings.c157
-rw-r--r--src/settings/nm-settings.h2
18 files changed, 794 insertions, 231 deletions
diff --git a/Makefile.am b/Makefile.am
index 993ee9781d..1de743030f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -347,6 +347,8 @@ shared_nm_glib_aux_libnm_glib_aux_la_SOURCES = \
shared/nm-glib-aux/nm-io-utils.c \
shared/nm-glib-aux/nm-io-utils.h \
shared/nm-glib-aux/nm-jansson.h \
+ shared/nm-glib-aux/nm-keyfile-aux.c \
+ shared/nm-glib-aux/nm-keyfile-aux.h \
shared/nm-glib-aux/nm-logging-fwd.h \
shared/nm-glib-aux/nm-macros-internal.h \
shared/nm-glib-aux/nm-obj.h \
diff --git a/libnm-core/nm-keyfile-utils.c b/libnm-core/nm-keyfile-utils.c
index e243150d02..a7d50e2216 100644
--- a/libnm-core/nm-keyfile-utils.c
+++ b/libnm-core/nm-keyfile-utils.c
@@ -415,7 +415,7 @@ _keyfile_key_encode (const char *name,
/* See g_key_file_is_key_name().
*
- * GKeyfile allows all UTF-8 characters (even non-well formed sequences),
+ * GKeyFile allows all UTF-8 characters (even non-well formed sequences),
* except:
* - no empty keys
* - no leading/trailing ' '
diff --git a/shared/meson.build b/shared/meson.build
index ba4c28c3fd..a63068eca5 100644
--- a/shared/meson.build
+++ b/shared/meson.build
@@ -144,6 +144,7 @@ shared_nm_glib_aux = static_library(
'nm-glib-aux/nm-errno.c',
'nm-glib-aux/nm-hash-utils.c',
'nm-glib-aux/nm-io-utils.c',
+ 'nm-glib-aux/nm-keyfile-aux.c',
'nm-glib-aux/nm-random-utils.c',
'nm-glib-aux/nm-secret-utils.c',
'nm-glib-aux/nm-shared-utils.c',
diff --git a/shared/nm-glib-aux/nm-keyfile-aux.c b/shared/nm-glib-aux/nm-keyfile-aux.c
new file mode 100644
index 0000000000..0257bcca7f
--- /dev/null
+++ b/shared/nm-glib-aux/nm-keyfile-aux.c
@@ -0,0 +1,413 @@
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2019 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+
+#include "nm-keyfile-aux.h"
+
+#include <syslog.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+
+#include "nm-io-utils.h"
+
+/*****************************************************************************/
+
+struct _NMKeyFileDB {
+ NMKeyFileDBLogFcn log_fcn;
+ NMKeyFileDBGotDirtyFcn got_dirty_fcn;
+ gpointer user_data;
+ const char *group_name;
+ GKeyFile *kf;
+ guint ref_count;
+
+ bool is_started:1;
+ bool dirty:1;
+ bool destroyed:1;
+
+ char filename[];
+};
+
+#define _NMLOG(self, \
+ syslog_level, \
+ fmt, \
+ ...) \
+ G_STMT_START { \
+ NMKeyFileDB *_self = (self); \
+ \
+ nm_assert (_self); \
+ nm_assert (!_self->destroyed); \
+ \
+ if (_self->log_fcn) { \
+ _self->log_fcn (_self, \
+ (syslog_level), \
+ _self->user_data, \
+ ""fmt"", \
+ ##__VA_ARGS__); \
+ }; \
+ } G_STMT_END
+
+#define _LOGD(...) _NMLOG (self, LOG_DEBUG, __VA_ARGS__)
+
+static gboolean
+_IS_KEY_FILE_DB (NMKeyFileDB *self, gboolean require_is_started, gboolean allow_destroyed)
+{
+ if (self == NULL)
+ return FALSE;
+ if (self->ref_count <= 0) {
+ nm_assert_not_reached ();
+ return FALSE;
+ }
+ if ( require_is_started
+ && !self->is_started)
+ return FALSE;
+ if ( !allow_destroyed
+ && self->destroyed)
+ return FALSE;
+ return TRUE;
+}
+
+/*****************************************************************************/
+
+NMKeyFileDB *
+nm_key_file_db_new (const char *filename,
+ const char *group_name,
+ NMKeyFileDBLogFcn log_fcn,
+ NMKeyFileDBGotDirtyFcn got_dirty_fcn,
+ gpointer user_data)
+{
+ NMKeyFileDB *self;
+ gsize l_filename;
+ gsize l_group;
+
+ g_return_val_if_fail (filename && filename[0], NULL);
+ g_return_val_if_fail (group_name && group_name[0], NULL);
+
+ l_filename = strlen (filename);
+ l_group = strlen (group_name);
+
+ self = g_malloc0 (sizeof (NMKeyFileDB) + l_filename + 1 + l_group + 1);
+ self->ref_count = 1;
+ self->log_fcn = log_fcn;
+ self->got_dirty_fcn = got_dirty_fcn;
+ self->user_data = user_data;
+ self->kf = g_key_file_new ();
+ g_key_file_set_list_separator (self->kf, ',');
+ memcpy (self->filename, filename, l_filename + 1);
+ self->group_name = &self->filename[l_filename + 1];
+ memcpy ((char *) self->group_name, group_name, l_group + 1);
+
+ return self;
+}
+
+NMKeyFileDB *
+nm_key_file_db_ref (NMKeyFileDB *self)
+{
+ if (!self)
+ return NULL;
+
+ g_return_val_if_fail (_IS_KEY_FILE_DB (self, FALSE, TRUE), NULL);
+
+ nm_assert (self->ref_count <= G_MAXUINT);
+ self->ref_count++;
+ return self;
+}
+
+void
+nm_key_file_db_unref (NMKeyFileDB *self)
+{
+ if (!self)
+ return;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, FALSE, TRUE));
+
+ if (--self->ref_count > 0)
+ return;
+
+ g_key_file_unref (self->kf);
+
+ g_free (self);
+}
+
+/* destroy() is like unref, but it also makes the instance unusable.
+ * All changes afterwards fail with an assertion.
+ *
+ * The point is that NMKeyFileDB is ref-counted in principle. But there
+ * is a primary owner who also provides the log_fcn().
+ *
+ * When the primary owner goes out of scope and gives up the reference, it does
+ * not want to receive any log notifications anymore.
+ *
+ * The way NMKeyFileDB is intended to be used is in a very strict context:
+ * NMSettings owns the NMKeyFileDB instance and receives logging notifications.
+ * It's also the last one to persist the data to disk. Afterwards, no other user
+ * is supposed to be around and do anything with NMKeyFileDB. But since NMKeyFileDB
+ * is ref-counted it's hard to ensure that this is truly honored. So we start
+ * asserting at that point.
+ */
+void
+nm_key_file_db_destroy (NMKeyFileDB *self)
+{
+ if (!self)
+ return;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, FALSE, FALSE));
+ g_return_if_fail (!self->destroyed);
+
+ self->destroyed = TRUE;
+ nm_key_file_db_unref (self);
+}
+
+/*****************************************************************************/
+
+/* nm_key_file_db_start() is supposed to be called right away, after creating the
+ * instance.
+ *
+ * It's not done as separate step after nm_key_file_db_new(), because we want to log,
+ * and the log_fcn returns the self pointer (which we should not expose before
+ * nm_key_file_db_new() returns. */
+void
+nm_key_file_db_start (NMKeyFileDB *self)
+{
+ int r;
+ gs_free char *contents = NULL;
+ gsize contents_len;
+ gs_free_error GError *error = NULL;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, FALSE, FALSE));
+ g_return_if_fail (!self->is_started);
+
+ self->is_started = TRUE;
+
+ r = nm_utils_file_get_contents (-1,
+ self->filename,
+ 20*1024*1024,
+ NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
+ &contents,
+ &contents_len,
+ &error);
+ if (r < 0) {
+ _LOGD ("failed to read \"%s\": %s", self->filename, error->message);
+ return;
+ }
+
+ if (!g_key_file_load_from_data (self->kf,
+ contents,
+ contents_len,
+ G_KEY_FILE_KEEP_COMMENTS,
+ &error)) {
+ _LOGD ("failed to load keyfile \"%s\": %s", self->filename, error->message);
+ return;
+ }
+
+ _LOGD ("loaded keyfile-db for \"%s\"", self->filename);
+}
+
+/*****************************************************************************/
+
+const char *
+nm_key_file_db_get_filename (NMKeyFileDB *self)
+{
+ g_return_val_if_fail (_IS_KEY_FILE_DB (self, FALSE, TRUE), NULL);
+
+ return self->filename;
+}
+
+gboolean
+nm_key_file_db_is_dirty (NMKeyFileDB *self)
+{
+ g_return_val_if_fail (_IS_KEY_FILE_DB (self, FALSE, TRUE), FALSE);
+
+ return self->dirty;
+}
+
+/*****************************************************************************/
+
+char *
+nm_key_file_db_get_value (NMKeyFileDB *self,
+ const char *key)
+{
+ g_return_val_if_fail (_IS_KEY_FILE_DB (self, TRUE, TRUE), NULL);
+
+ return g_key_file_get_value (self->kf, self->group_name, key, NULL);
+}
+
+char **
+nm_key_file_db_get_string_list (NMKeyFileDB *self,
+ const char *key,
+ gsize *out_len)
+{
+ g_return_val_if_fail (_IS_KEY_FILE_DB (self, TRUE, TRUE), NULL);
+
+ return g_key_file_get_string_list (self->kf, self->group_name, key, out_len, NULL);
+}
+
+/*****************************************************************************/
+
+static void
+_got_dirty (NMKeyFileDB *self,
+ const char *key)
+{
+ nm_assert (_IS_KEY_FILE_DB (self, TRUE, FALSE));
+ nm_assert (!self->dirty);
+
+ _LOGD ("updated entry for %s.%s", self->group_name, key);
+
+ self->dirty = TRUE;
+ if (self->got_dirty_fcn)
+ self->got_dirty_fcn (self, self->user_data);
+}
+
+/*****************************************************************************/
+
+void
+nm_key_file_db_remove_key (NMKeyFileDB *self,
+ const char *key)
+{
+ gboolean got_dirty = FALSE;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, TRUE, FALSE));
+
+ if (!key)
+ return;
+
+ if (!self->dirty) {
+ gs_free_error GError *error = NULL;
+
+ g_key_file_has_key (self->kf, self->group_name, key, &error);
+ got_dirty = (error != NULL);
+ }
+ g_key_file_remove_key (self->kf, self->group_name, key, NULL);
+
+ if (got_dirty)
+ _got_dirty (self, key);
+}
+
+void
+nm_key_file_db_set_value (NMKeyFileDB *self,
+ const char *key,
+ const char *value)
+{
+ gs_free char *old_value = NULL;
+ gboolean got_dirty = FALSE;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, TRUE, FALSE));
+ g_return_if_fail (key);
+
+ if (!value) {
+ nm_key_file_db_remove_key (self, key);
+ return;
+ }
+
+ if (!self->dirty) {
+ gs_free_error GError *error = NULL;
+
+ old_value = g_key_file_get_value (self->kf, self->group_name, key, &error);
+ if (error)
+ got_dirty = TRUE;
+ }
+
+ g_key_file_set_value (self->kf, self->group_name, key, value);
+
+ if ( !self->dirty
+ && !got_dirty) {
+ gs_free_error GError *error = NULL;
+ gs_free char *new_value = NULL;
+
+ new_value = g_key_file_get_value (self->kf, self->group_name, key, &error);
+ if ( error
+ || !new_value
+ || !nm_streq0 (old_value, new_value))
+ got_dirty = TRUE;
+ }
+
+ if (got_dirty)
+ _got_dirty (self, key);
+}
+
+void
+nm_key_file_db_set_string_list (NMKeyFileDB *self,
+ const char *key,
+ const char *const*value,
+ gssize len)
+{
+ gs_free char *old_value = NULL;
+ gboolean got_dirty = FALSE;;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, TRUE, FALSE));
+ g_return_if_fail (key);
+
+ if (!value) {
+ nm_key_file_db_remove_key (self, key);
+ return;
+ }
+
+ if (!self->dirty) {
+ gs_free_error GError *error = NULL;
+
+ old_value = g_key_file_get_value (self->kf, self->group_name, key, &error);
+ if (error)
+ got_dirty = TRUE;
+ }
+
+ if (len < 0)
+ len = NM_PTRARRAY_LEN (value);
+
+ g_key_file_set_string_list (self->kf, self->group_name, key, value, len);
+
+ if ( !self->dirty
+ && !got_dirty) {
+ gs_free_error GError *error = NULL;
+ gs_free char *new_value = NULL;
+
+ new_value = g_key_file_get_value (self->kf, self->group_name, key, &error);
+ if ( error
+ || !new_value
+ || !nm_streq0 (old_value, new_value))
+ got_dirty = TRUE;
+ }
+
+ if (got_dirty)
+ _got_dirty (self, key);
+}
+
+/*****************************************************************************/
+
+void
+nm_key_file_db_to_file (NMKeyFileDB *self,
+ gboolean force)
+{
+ gs_free_error GError *error = NULL;
+
+ g_return_if_fail (_IS_KEY_FILE_DB (self, TRUE, FALSE));
+
+ if ( !force
+ && !self->dirty)
+ return;
+
+ self->dirty = FALSE;
+
+ if (!g_key_file_save_to_file (self->kf,
+ self->filename,
+ &error)) {
+ _LOGD ("failure to write keyfile \"%s\": %s", self->filename, error->message);
+ } else
+ _LOGD ("write keyfile: \"%s\"", self->filename);
+}
diff --git a/shared/nm-glib-aux/nm-keyfile-aux.h b/shared/nm-glib-aux/nm-keyfile-aux.h
new file mode 100644
index 0000000000..8563f4d186
--- /dev/null
+++ b/shared/nm-glib-aux/nm-keyfile-aux.h
@@ -0,0 +1,78 @@
+/* NetworkManager -- Network link manager
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * (C) Copyright 2019 Red Hat, Inc.
+ */
+
+#ifndef __NM_KEYFILE_AUX_H__
+#define __NM_KEYFILE_AUX_H__
+
+/*****************************************************************************/
+
+typedef struct _NMKeyFileDB NMKeyFileDB;
+
+typedef void (*NMKeyFileDBLogFcn) (NMKeyFileDB *self,
+ int syslog_level,
+ gpointer user_data,
+ const char *fmt,
+ ...) G_GNUC_PRINTF (4, 5);
+
+typedef void (*NMKeyFileDBGotDirtyFcn) (NMKeyFileDB *self,
+ gpointer user_data);
+
+NMKeyFileDB *nm_key_file_db_new (const char *filename,
+ const char *group,
+ NMKeyFileDBLogFcn log_fcn,
+ NMKeyFileDBGotDirtyFcn got_dirty_fcn,
+ gpointer user_data);
+
+void nm_key_file_db_start (NMKeyFileDB *self);
+
+NMKeyFileDB *nm_key_file_db_ref (NMKeyFileDB *self);
+void nm_key_file_db_unref (NMKeyFileDB *self);
+
+void nm_key_file_db_destroy (NMKeyFileDB *self);
+
+const char *nm_key_file_db_get_filename (NMKeyFileDB *self);
+
+gboolean nm_key_file_db_is_dirty (NMKeyFileDB *self);
+
+char *nm_key_file_db_get_value (NMKeyFileDB *self,
+ const char *key);
+
+char **nm_key_file_db_get_string_list (NMKeyFileDB *self,
+ const char *key,
+ gsize *out_len);
+
+void nm_key_file_db_remove_key (NMKeyFileDB *self,
+ const char *key);
+
+void nm_key_file_db_set_value (NMKeyFileDB *self,
+ const char *key,
+ const char *value);
+
+void nm_key_file_db_set_string_list (NMKeyFileDB *self,
+ const char *key,
+ const char *const*value,
+ gssize len);
+
+void nm_key_file_db_to_file (NMKeyFileDB *self,
+ gboolean force);
+
+/*****************************************************************************/
+
+#endif /* __NM_KEYFILE_AUX_H__ */
diff --git a/shared/nm-glib-aux/nm-logging-fwd.h b/shared/nm-glib-aux/nm-logging-fwd.h
index 900dfff812..693803f9d4 100644
--- a/shared/nm-glib-aux/nm-logging-fwd.h
+++ b/shared/nm-glib-aux/nm-logging-fwd.h
@@ -110,4 +110,21 @@ void _nm_log_impl (const char *file,
const char *fmt,
...) _nm_printf (10, 11);
+static inline NMLogLevel
+nm_log_level_from_syslog (int syslog_level)
+{
+ switch (syslog_level) {
+ case 0 /* LOG_EMERG */ : return LOGL_ERR;
+ case 1 /* LOG_ALERT */ : return LOGL_ERR;
+ case 2 /* LOG_CRIT */ : return LOGL_ERR;
+ case 3 /* LOG_ERR */ : return LOGL_ERR;
+ case 4 /* LOG_WARNING */ : return LOGL_WARN;
+ case 5 /* LOG_NOTICE */ : return LOGL_INFO;
+ case 6 /* LOG_INFO */ : return LOGL_DEBUG;
+ case 7 /* LOG_DEBUG */ : return LOGL_TRACE;
+ default:
+ return syslog_level >= 0 ? LOGL_TRACE : LOGL_ERR;
+ }
+}
+
#endif /* __NM_LOGGING_DEFINES_H__ */
diff --git a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h
index a285c3cdc5..d38a39b15a 100644
--- a/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h
+++ b/shared/systemd/sd-adapt-shared/nm-sd-adapt-shared.h
@@ -21,8 +21,6 @@
#include "nm-default.h"
-#include <syslog.h>
-
#include "nm-glib-aux/nm-logging-fwd.h"
/*****************************************************************************/
@@ -32,32 +30,18 @@
/*****************************************************************************/
-static inline NMLogLevel
-_slog_level_to_nm (int slevel)
-{
- switch (LOG_PRI (slevel)) {
- case LOG_DEBUG: return LOGL_DEBUG;
- case LOG_WARNING: return LOGL_WARN;
- case LOG_CRIT:
- case LOG_ERR: return LOGL_ERR;
- case LOG_INFO:
- case LOG_NOTICE:
- default: return LOGL_INFO;
- }
-}
-
static inline int
_nm_log_get_max_level_realm (void)
{
/* inline function, to avoid coverity warning about constant expression. */
- return LOG_DEBUG;
+ return 7 /* LOG_DEBUG */;
}
#define log_get_max_level_realm(realm) _nm_log_get_max_level_realm ()
#define log_internal_realm(level, error, file, line, func, format, ...) \
({ \
const int _nm_e = (error); \
- const NMLogLevel _nm_l = _slog_level_to_nm ((level)); \
+ const NMLogLevel _nm_l = nm_log_level_from_syslog (LOG_PRI (level)); \
\
if (_nm_log_enabled_impl (!(NM_THREAD_SAFE_ON_MAIN_THREAD), _nm_l, LOGD_SYSTEMD)) { \
const char *_nm_location = strrchr ((""file), '/'); \
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 62d2e57836..26bcc2c840 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -15121,7 +15121,7 @@ _set_state_full (NMDevice *self,
* and those we haven't tried yet (no timestamp).
*/
if (sett_conn && !nm_settings_connection_get_timestamp (sett_conn, NULL))
- nm_settings_connection_update_timestamp (sett_conn, (guint64) 0, TRUE);
+ nm_settings_connection_update_timestamp (sett_conn, (guint64) 0);
/* Schedule the transition to DISCONNECTED. The device can't transition
* immediately because we can't change states again from the state
diff --git a/src/devices/wifi/nm-iwd-manager.c b/src/devices/wifi/nm-iwd-manager.c
index 494fca321f..3f973090f3 100644
--- a/src/devices/wifi/nm-iwd-manager.c
+++ b/src/devices/wifi/nm-iwd-manager.c
@@ -900,7 +900,7 @@ nm_iwd_manager_init (NMIwdManager *self)
g_signal_connect (priv->manager, NM_MANAGER_DEVICE_ADDED,
G_CALLBACK (device_added), self);
- priv->settings = g_object_ref (nm_settings_get ());
+ priv->settings = g_object_ref (NM_SETTINGS_GET);
g_signal_connect (priv->settings, NM_SETTINGS_SIGNAL_CONNECTION_REMOVED,
G_CALLBACK (connection_removed), self);
diff --git a/src/main.c b/src/main.c
index 9f979cf4dc..02a4210532 100644
--- a/src/main.c
+++ b/src/main.c
@@ -458,6 +458,8 @@ done:
nm_dns_manager_stop (nm_dns_manager_get ());
+ nm_settings_kf_db_write (NM_SETTINGS_GET);
+
done_no_manager:
if (global_opt.pidfile && wrote_pidfile)
unlink (global_opt.pidfile);
diff --git a/src/nm-active-connection.c b/src/nm-active-connection.c
index 17568c30b5..d28588c989 100644
--- a/src/nm-active-connection.c
+++ b/src/nm-active-connection.c
@@ -285,7 +285,7 @@ nm_active_connection_set_state (NMActiveConnection *self,
if ( new_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED
|| old_state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (priv->settings_connection.obj,
- (guint64) time (NULL), TRUE);
+ (guint64) time (NULL));
}
if (priv->device) {
diff --git a/src/nm-checkpoint.c b/src/nm-checkpoint.c
index f715eea611..3a1693d26e 100644
--- a/src/nm-checkpoint.c
+++ b/src/nm-checkpoint.c
@@ -171,7 +171,7 @@ find_settings_connection (NMCheckpoint *self,
*need_update = FALSE;
uuid = nm_connection_get_uuid (dev_checkpoint->settings_connection);
- sett_conn = nm_settings_get_connection_by_uuid (nm_settings_get (), uuid);
+ sett_conn = nm_settings_get_connection_by_uuid (NM_SETTINGS_GET, uuid);
if (!sett_conn)
return NULL;
@@ -239,7 +239,7 @@ restore_and_activate_connection (NMCheckpoint *self,
_LOGD ("rollback: adding connection %s again",
nm_connection_get_uuid (dev_checkpoint->settings_connection));
- connection = nm_settings_add_connection (nm_settings_get (),
+ connection = nm_settings_add_connection (NM_SETTINGS_GET,
dev_checkpoint->settings_connection,
TRUE,
&local_error);
@@ -419,7 +419,7 @@ next_dev:
gs_free NMSettingsConnection **list = NULL;
g_return_val_if_fail (priv->connection_uuids, NULL);
- list = nm_settings_get_connections_clone (nm_settings_get (), NULL,
+ list = nm_settings_get_connections_clone (NM_SETTINGS_GET, NULL,
NULL, NULL,
nm_settings_connection_cmp_autoconnect_priority_p_with_data, NULL);
@@ -687,7 +687,7 @@ nm_checkpoint_new (NMManager *manager, GPtrArray *devices, guint32 rollback_time
if (NM_FLAGS_HAS (flags, NM_CHECKPOINT_CREATE_FLAG_DELETE_NEW_CONNECTIONS)) {
priv->connection_uuids = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, NULL);
- for (con = nm_settings_get_connections (nm_settings_get (), NULL); *con; con++) {
+ for (con = nm_settings_get_connections (NM_SETTINGS_GET, NULL); *con; con++) {
g_hash_table_add (priv->connection_uuids,
g_strdup (nm_settings_connection_get_uuid (*con)));
}
diff --git a/src/nm-logging.c b/src/nm-logging.c
index 48e51421b9..79e3658ab4 100644
--- a/src/nm-logging.c
+++ b/src/nm-logging.c
@@ -68,6 +68,15 @@
/*****************************************************************************/
+G_STATIC_ASSERT (LOG_EMERG == 0);
+G_STATIC_ASSERT (LOG_ALERT == 1);
+G_STATIC_ASSERT (LOG_CRIT == 2);
+G_STATIC_ASSERT (LOG_ERR == 3);
+G_STATIC_ASSERT (LOG_WARNING == 4);
+G_STATIC_ASSERT (LOG_NOTICE == 5);
+G_STATIC_ASSERT (LOG_INFO == 6);
+G_STATIC_ASSERT (LOG_DEBUG == 7);
+
/* We have more then 32 logging domains. Assert that it compiles to a 64 bit sized enum */
G_STATIC_ASSERT (sizeof (NMLogDomain) >= sizeof (guint64));
diff --git a/src/nm-manager.c b/src/nm-manager.c
index c0cd15c0cd..3622a0a5ad 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -7313,7 +7313,7 @@ periodic_update_active_connection_timestamps (gpointer user_data)
c_list_for_each_entry (ac, &priv->active_connections_lst_head, active_connections_lst) {
if (nm_active_connection_get_state (ac) == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) {
nm_settings_connection_update_timestamp (nm_active_connection_get_settings_connection (ac),
- (guint64) time (NULL), FALSE);
+ (guint64) time (NULL));
}
}
return G_SOURCE_CONTINUE;
diff --git a/src/settings/nm-settings-connection.c b/src/settings/nm-settings-connection.c
index 3fdaa59814..3bb30cbe57 100644
--- a/src/settings/nm-settings-connection.c
+++ b/src/settings/nm-settings-connection.c
@@ -25,6 +25,7 @@
#include "c-list/src/c-list.h"
+#include "nm-glib-aux/nm-keyfile-aux.h"
#include "nm-libnm-core-intern/nm-common-macros.h"
#include "nm-config.h"
#include "nm-config-data.h"
@@ -38,9 +39,6 @@
#include "nm-core-internal.h"
#include "nm-audit-manager.h"
-#define SETTINGS_TIMESTAMPS_FILE NMSTATEDIR "/timestamps"
-#define SETTINGS_SEEN_BSSIDS_FILE NMSTATEDIR "/seen-bssids"
-
#define AUTOCONNECT_RETRIES_UNSET -2
#define AUTOCONNECT_RETRIES_FOREVER -1
#define AUTOCONNECT_RESET_RETRIES_TIMER 300
@@ -86,6 +84,9 @@ static guint signals[LAST_SIGNAL] = { 0 };
typedef struct _NMSettingsConnectionPrivate {
+ NMKeyFileDB *kf_db_timestamps;
+ NMKeyFileDB *kf_db_seen_bssids;
+
NMAgentManager *agent_mgr;
NMSessionMonitor *session_monitor;
gulong session_changed_id;
@@ -658,42 +659,6 @@ out:
return TRUE;
}
-static void
-remove_entry_from_db (NMSettingsConnection *self, const char* db_name)
-{
- GKeyFile *key_file;
- const char *db_file;
-
- if (strcmp (db_name, "timestamps") == 0)
- db_file = SETTINGS_TIMESTAMPS_FILE;
- else if (strcmp (db_name, "seen-bssids") == 0)
- db_file = SETTINGS_SEEN_BSSIDS_FILE;
- else
- return;
-
- key_file = g_key_file_new ();
- if (g_key_file_load_from_file (key_file, db_file, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
- const char *connection_uuid;
- char *data;
- gsize len;
- GError *error = NULL;
-
- connection_uuid = nm_settings_connection_get_uuid (self);
-
- g_key_file_remove_key (key_file, db_name, connection_uuid, NULL);
- data = g_key_file_to_data (key_file, &len, &error);
- if (data) {
- g_file_set_contents (db_file, data, len, &error);
- g_free (data);
- }
- if (error) {
- _LOGW ("error writing %s file '%s': %s", db_name, db_file, error->message);
- g_error_free (error);
- }
- }
- g_key_file_free (key_file);
-}
-
gboolean
nm_settings_connection_delete (NMSettingsConnection *self,
GError **error)
@@ -701,6 +666,7 @@ nm_settings_connection_delete (NMSettingsConnection *self,
gs_unref_object NMSettingsConnection *self_keep_alive = NULL;
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
NMConnection *for_agents;
+ const char *connection_uuid;
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE);
@@ -719,11 +685,13 @@ nm_settings_connection_delete (NMSettingsConnection *self,
for_agents);
g_object_unref (for_agents);
- /* Remove timestamp from timestamps database file */
- remove_entry_from_db (self, "timestamps");
+ connection_uuid = nm_settings_connection_get_uuid (self);
+
+ if (priv->kf_db_timestamps)
+ nm_key_file_db_remove_key (priv->kf_db_timestamps, connection_uuid);
- /* Remove connection from seen-bssids database file */
- remove_entry_from_db (self, "seen-bssids");
+ if (priv->kf_db_seen_bssids)
+ nm_key_file_db_remove_key (priv->kf_db_seen_bssids, connection_uuid);
nm_settings_connection_signal_remove (self);
return TRUE;
@@ -2338,11 +2306,13 @@ gboolean
nm_settings_connection_get_timestamp (NMSettingsConnection *self,
guint64 *out_timestamp)
{
+ NMSettingsConnectionPrivate *priv;
+
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (self), FALSE);
- if (out_timestamp)
- *out_timestamp = NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp;
- return NM_SETTINGS_CONNECTION_GET_PRIVATE (self)->timestamp_set;
+ priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
+ NM_SET_OUT (out_timestamp, priv->timestamp);
+ return priv->timestamp_set;
}
/**
@@ -2350,56 +2320,31 @@ nm_settings_connection_get_timestamp (NMSettingsConnection *self,
* @self: the #NMSettingsConnection
* @timestamp: timestamp to set into the connection and to store into
* the timestamps database
- * @flush_to_disk: if %TRUE, commit timestamp update to persistent storage
*
* Updates the connection and timestamps database with the provided timestamp.
**/
void
nm_settings_connection_update_timestamp (NMSettingsConnection *self,
- guint64 timestamp,
- gboolean flush_to_disk)
+ guint64 timestamp)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
const char *connection_uuid;
- GKeyFile *timestamps_file;
- char *data, *tmp;
- gsize len;
- GError *error = NULL;
+ char sbuf[60];
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self));
- /* Update timestamp in private storage */
priv->timestamp = timestamp;
priv->timestamp_set = TRUE;
- if (flush_to_disk == FALSE)
- return;
- if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD)
+ if (!priv->kf_db_timestamps)
return;
- /* Save timestamp to timestamps database file */
- timestamps_file = g_key_file_new ();
- if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
- _LOGW ("error parsing timestamps file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message);
- g_clear_error (&error);
- }
-
connection_uuid = nm_settings_connection_get_uuid (self);
- tmp = g_strdup_printf ("%" G_GUINT64_FORMAT, timestamp);
- g_key_file_set_value (timestamps_file, "timestamps", connection_uuid, tmp);
- g_free (tmp);
-
- data = g_key_file_to_data (timestamps_file, &len, &error);
- if (data) {
- g_file_set_contents (SETTINGS_TIMESTAMPS_FILE, data, len, &error);
- g_free (data);
+ if (connection_uuid) {
+ nm_key_file_db_set_value (priv->kf_db_timestamps,
+ connection_uuid,
+ nm_sprintf_buf (sbuf, "%" G_GUINT64_FORMAT, timestamp));
}
- if (error) {
- _LOGW ("error saving timestamp to file '%s': %s", SETTINGS_TIMESTAMPS_FILE, error->message);
- g_error_free (error);
- }
- g_key_file_free (timestamps_file);
}
/**
@@ -2410,38 +2355,79 @@ nm_settings_connection_update_timestamp (NMSettingsConnection *self,
* stores it into the connection private data.
**/
void
-nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self)
+nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
+ NMKeyFileDB *kf_db_timestamps,
+ NMKeyFileDB *kf_db_seen_bssids)
{
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- gs_unref_keyfile GKeyFile *timestamps_file = NULL;
- gs_free_error GError *error = NULL;
- gs_free char *tmp_str = NULL;
+ NMSettingsConnectionPrivate *priv;
const char *connection_uuid;
- gint64 timestamp;
g_return_if_fail (NM_IS_SETTINGS_CONNECTION (self));
+ g_return_if_fail (kf_db_timestamps);
+ g_return_if_fail (kf_db_seen_bssids);
- timestamps_file = g_key_file_new ();
- if (!g_key_file_load_from_file (timestamps_file, SETTINGS_TIMESTAMPS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- _LOGD ("failed to read connection timestamp: %s", error->message);
- return;
- }
+ priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
connection_uuid = nm_settings_connection_get_uuid (self);
- tmp_str = g_key_file_get_value (timestamps_file, "timestamps", connection_uuid, &error);
- if (!tmp_str) {
- _LOGD ("failed to read connection timestamp: %s", error->message);
- return;
- }
- timestamp = _nm_utils_ascii_str_to_int64 (tmp_str, 10, 0, G_MAXINT64, -1);
- if (timestamp < 0) {
- _LOGD ("failed to read connection timestamp: %s", "invalid number");
- return;
+ if (priv->kf_db_timestamps != kf_db_timestamps) {
+ gs_free char *tmp_str = NULL;
+ guint64 timestamp;
+
+ nm_key_file_db_unref (priv->kf_db_timestamps);
+ priv->kf_db_timestamps = nm_key_file_db_ref (kf_db_timestamps);
+
+ tmp_str = nm_key_file_db_get_value (priv->kf_db_timestamps, connection_uuid);
+
+ timestamp = _nm_utils_ascii_str_to_uint64 (tmp_str, 10, 0, G_MAXUINT64, G_MAXUINT64);
+ if (timestamp != G_MAXUINT64) {
+ priv->timestamp = timestamp;
+ priv->timestamp_set = TRUE;
+ _LOGT ("read timestamp %"G_GUINT64_FORMAT" from keyfile database \"%s\"",
+ timestamp, nm_key_file_db_get_filename (priv->kf_db_timestamps));
+ } else
+ _LOGT ("no timestamp from keyfile database \"%s\"",
+ nm_key_file_db_get_filename (priv->kf_db_timestamps));
}
- priv->timestamp = timestamp;
- priv->timestamp_set = TRUE;
+ if (priv->kf_db_seen_bssids != kf_db_seen_bssids) {
+ gs_strfreev char **tmp_strv = NULL;
+ gsize i, len;
+
+ nm_key_file_db_unref (priv->kf_db_seen_bssids);
+ priv->kf_db_seen_bssids = nm_key_file_db_ref (kf_db_seen_bssids);
+
+ tmp_strv = nm_key_file_db_get_string_list (priv->kf_db_seen_bssids, connection_uuid, &len);
+
+ if (tmp_strv) {
+ _LOGT ("read %zu seen-bssids from keyfile database \"%s\"",
+ NM_PTRARRAY_LEN (tmp_strv),
+ nm_key_file_db_get_filename (priv->kf_db_seen_bssids));
+ g_hash_table_remove_all (priv->seen_bssids);
+ for (i = len; i > 0; )
+ g_hash_table_add (priv->seen_bssids, g_steal_pointer (&tmp_strv[--i]));
+ } else {
+ NMSettingWireless *s_wifi;
+
+ _LOGT ("no seen-bssids from keyfile database \"%s\"",
+ nm_key_file_db_get_filename (priv->kf_db_seen_bssids));
+
+ /* If this connection didn't have an entry in the seen-bssids database,
+ * maybe this is the first time we've read it in, so populate the
+ * seen-bssids list from the deprecated seen-bssids property of the
+ * wifi setting.
+ */
+ s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (self));
+ if (s_wifi) {
+ len = nm_setting_wireless_get_num_seen_bssids (s_wifi);
+ for (i = 0; i < len; i++) {
+ const char *bssid = nm_setting_wireless_get_seen_bssid (s_wifi, i);
+
+ g_hash_table_add (priv->seen_bssids, g_strdup (bssid));
+ }
+ }
+ }
+ }
}
/**
@@ -2504,108 +2490,26 @@ nm_settings_connection_add_seen_bssid (NMSettingsConnection *self,
const char *seen_bssid)
{
NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
+ gs_free const char **strv = NULL;
const char *connection_uuid;
- GKeyFile *seen_bssids_file;
- char *data, *bssid_str;
- const char **list;
- gsize len;
- GError *error = NULL;
- GHashTableIter iter;
- guint n;
g_return_if_fail (seen_bssid != NULL);
- if (g_hash_table_lookup (priv->seen_bssids, seen_bssid))
- return; /* Already in the list */
-
- /* Add the new BSSID; let the hash take ownership of the allocated BSSID string */
- bssid_str = g_strdup (seen_bssid);
- g_hash_table_insert (priv->seen_bssids, bssid_str, bssid_str);
+ g_hash_table_add (priv->seen_bssids, g_strdup (seen_bssid));
- /* Build up a list of all the BSSIDs in string form */
- n = 0;
- list = g_malloc0 (g_hash_table_size (priv->seen_bssids) * sizeof (char *));
- g_hash_table_iter_init (&iter, priv->seen_bssids);
- while (g_hash_table_iter_next (&iter, NULL, (gpointer) &bssid_str))
- list[n++] = bssid_str;
-
- /* Save BSSID to seen-bssids file */
- seen_bssids_file = g_key_file_new ();
- g_key_file_set_list_separator (seen_bssids_file, ',');
- if (!g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, &error)) {
- if (!g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
- _LOGW ("error parsing seen-bssids file '%s': %s",
- SETTINGS_SEEN_BSSIDS_FILE, error->message);
- }
- g_clear_error (&error);
- }
+ if (!priv->kf_db_seen_bssids)
+ return;
connection_uuid = nm_settings_connection_get_uuid (self);
- g_key_file_set_string_list (seen_bssids_file, "seen-bssids", connection_uuid, list, n);
- g_free (list);
+ if (!connection_uuid)
+ return;
- data = g_key_file_to_data (seen_bssids_file, &len, &error);
- if (data) {
- g_file_set_contents (SETTINGS_SEEN_BSSIDS_FILE, data, len, &error);
- g_free (data);
- }
- g_key_file_free (seen_bssids_file);
+ strv = nm_utils_strdict_get_keys (priv->seen_bssids, TRUE, NULL);
- if (error) {
- _LOGW ("error saving seen-bssids to file '%s': %s",
- SETTINGS_SEEN_BSSIDS_FILE, error->message);
- g_error_free (error);
- }
-}
-
-/**
- * nm_settings_connection_read_and_fill_seen_bssids:
- * @self: the #NMSettingsConnection
- *
- * Retrieves seen BSSIDs of the connection from database file and stores then into the
- * connection private data.
- **/
-void
-nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self)
-{
- NMSettingsConnectionPrivate *priv = NM_SETTINGS_CONNECTION_GET_PRIVATE (self);
- const char *connection_uuid;
- GKeyFile *seen_bssids_file;
- char **tmp_strv = NULL;
- gsize i, len = 0;
- NMSettingWireless *s_wifi;
-
- /* Get seen BSSIDs from database file */
- seen_bssids_file = g_key_file_new ();
- g_key_file_set_list_separator (seen_bssids_file, ',');
- if (g_key_file_load_from_file (seen_bssids_file, SETTINGS_SEEN_BSSIDS_FILE, G_KEY_FILE_KEEP_COMMENTS, NULL)) {
- connection_uuid = nm_settings_connection_get_uuid (self);
- tmp_strv = g_key_file_get_string_list (seen_bssids_file, "seen-bssids", connection_uuid, &len, NULL);
- }
- g_key_file_free (seen_bssids_file);
-
- /* Update connection's seen-bssids */
- if (tmp_strv) {
- g_hash_table_remove_all (priv->seen_bssids);
- for (i = 0; i < len; i++)
- g_hash_table_insert (priv->seen_bssids, tmp_strv[i], tmp_strv[i]);
- g_free (tmp_strv);
- } else {
- /* If this connection didn't have an entry in the seen-bssids database,
- * maybe this is the first time we've read it in, so populate the
- * seen-bssids list from the deprecated seen-bssids property of the
- * wifi setting.
- */
- s_wifi = nm_connection_get_setting_wireless (nm_settings_connection_get_connection (self));
- if (s_wifi) {
- len = nm_setting_wireless_get_num_seen_bssids (s_wifi);
- for (i = 0; i < len; i++) {
- char *bssid_dup = g_strdup (nm_setting_wireless_get_seen_bssid (s_wifi, i));
-
- g_hash_table_insert (priv->seen_bssids, bssid_dup, bssid_dup);
- }
- }
- }
+ nm_key_file_db_set_string_list (priv->kf_db_seen_bssids,
+ connection_uuid,
+ strv ?: NM_PTRARRAY_EMPTY (const char *),
+ -1);
}
/*****************************************************************************/
@@ -2932,6 +2836,9 @@ dispose (GObject *object)
g_clear_pointer (&priv->filename, g_free);
+ g_clear_pointer (&priv->kf_db_timestamps, nm_key_file_db_unref);
+ g_clear_pointer (&priv->kf_db_seen_bssids, nm_key_file_db_unref);
+
G_OBJECT_CLASS (nm_settings_connection_parent_class)->dispose (object);
}
diff --git a/src/settings/nm-settings-connection.h b/src/settings/nm-settings-connection.h
index e796b71645..c23f68fcdc 100644
--- a/src/settings/nm-settings-connection.h
+++ b/src/settings/nm-settings-connection.h
@@ -220,14 +220,17 @@ int nm_settings_connection_cmp_timestamp_p_with_data (gconstpointer pa, gconstpo
int nm_settings_connection_cmp_autoconnect_priority (NMSettingsConnection *a, NMSettingsConnection *b);
int nm_settings_connection_cmp_autoconnect_priority_p_with_data (gconstpointer pa, gconstpointer pb, gpointer user_data);
+struct _NMKeyFileDB;
+
+void nm_settings_connection_register_kf_dbs (NMSettingsConnection *self,
+ struct _NMKeyFileDB *kf_db_timestamps,
+ struct _NMKeyFileDB *kf_db_seen_bssids);
+
gboolean nm_settings_connection_get_timestamp (NMSettingsConnection *self,
guint64 *out_timestamp);
void nm_settings_connection_update_timestamp (NMSettingsConnection *self,
- guint64 timestamp,
- gboolean flush_to_disk);
-
-void nm_settings_connection_read_and_fill_timestamp (NMSettingsConnection *self);
+ guint64 timestamp);
char **nm_settings_connection_get_seen_bssids (NMSettingsConnection *self);
@@ -237,8 +240,6 @@ gboolean nm_settings_connection_has_seen_bssid (NMSettingsConnection *self,
void nm_settings_connection_add_seen_bssid (NMSettingsConnection *self,
const char *seen_bssid);
-void nm_settings_connection_read_and_fill_seen_bssids (NMSettingsConnection *self);
-
int nm_settings_connection_autoconnect_retries_get (NMSettingsConnection *self);
void nm_settings_connection_autoconnect_retries_set (NMSettingsConnection *self,
int retries);
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index e594860bcb..9bc3bce95f 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -37,6 +37,7 @@
#endif
#include "nm-libnm-core-intern/nm-common-macros.h"
+#include "nm-glib-aux/nm-keyfile-aux.h"
#include "nm-dbus-interface.h"
#include "nm-connection.h"
#include "nm-setting-8021x.h"
@@ -119,6 +120,9 @@ typedef struct {
GSList *plugins;
+ NMKeyFileDB *kf_db_timestamps;
+ NMKeyFileDB *kf_db_seen_bssids;
+
CList connections_lst_head;
NMSettingsConnection **connections_cached_list;
@@ -131,6 +135,9 @@ typedef struct {
guint connections_len;
+ guint kf_db_flush_idle_id_timestamps;
+ guint kf_db_flush_idle_id_seen_bssids;
+
bool started:1;
bool startup_complete:1;
bool connections_loaded:1;
@@ -935,11 +942,9 @@ claim_connection (NMSettings *self, NMSettingsConnection *sett_conn)
return;
}
- /* Read timestamp from look-aside file and put it into the connection's data */
- nm_settings_connection_read_and_fill_timestamp (sett_conn);
-
- /* Read seen-bssids from look-aside file and put it into the connection's data */
- nm_settings_connection_read_and_fill_seen_bssids (sett_conn);
+ nm_settings_connection_register_kf_dbs (sett_conn,
+ priv->kf_db_timestamps,
+ priv->kf_db_seen_bssids);
/* Ensure its initial visibility is up-to-date */
nm_settings_connection_recheck_visibility (sett_conn);
@@ -1764,6 +1769,128 @@ nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean quittin
/*****************************************************************************/
+G_GNUC_PRINTF (4, 5)
+static void
+_kf_db_log_fcn (NMKeyFileDB *kf_db,
+ int syslog_level,
+ gpointer user_data,
+ const char *fmt,
+ ...)
+{
+ NMSettings *self = user_data;
+ NMLogLevel level = nm_log_level_from_syslog (syslog_level);
+
+ if (_NMLOG_ENABLED (level)) {
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ gs_free char *msg = NULL;
+ va_list ap;
+ const char *prefix;
+
+ va_start (ap, fmt);
+ msg = g_strdup_vprintf (fmt, ap);
+ va_end (ap);
+
+ if (priv->kf_db_timestamps == kf_db)
+ prefix = "timestamps";
+ else if (priv->kf_db_seen_bssids == kf_db)
+ prefix = "seen-bssids";
+ else {
+ nm_assert_not_reached ();
+ prefix = "???";
+ }
+
+ _NMLOG (level, "[%s-keyfile]: %s", prefix, msg);
+ }
+}
+
+static gboolean
+_kf_db_got_dirty_flush (NMSettings *self,
+ gboolean is_timestamps)
+{
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ const char *prefix;
+ NMKeyFileDB *kf_db;
+
+ if (is_timestamps) {
+ prefix = "timestamps";
+ kf_db = priv->kf_db_timestamps;
+ priv->kf_db_flush_idle_id_timestamps = 0;
+ } else {
+ prefix = "seen-bssids";
+ kf_db = priv->kf_db_seen_bssids;
+ priv->kf_db_flush_idle_id_seen_bssids = 0;
+ }
+
+ if (nm_key_file_db_is_dirty (kf_db))
+ nm_key_file_db_to_file (kf_db, FALSE);
+ else {
+ _LOGT ("[%s-keyfile]: skip saving changes to \"%s\"",
+ prefix,
+ nm_key_file_db_get_filename (kf_db));
+ }
+
+ return G_SOURCE_REMOVE;
+}
+
+static gboolean
+_kf_db_got_dirty_flush_timestamps_cb (gpointer user_data)
+{
+ return _kf_db_got_dirty_flush (user_data,
+ TRUE);
+}
+
+static gboolean
+_kf_db_got_dirty_flush_seen_bssids_cb (gpointer user_data)
+{
+ return _kf_db_got_dirty_flush (user_data,
+ FALSE);
+}
+
+static void
+_kf_db_got_dirty_fcn (NMKeyFileDB *kf_db,
+ gpointer user_data)
+{
+ NMSettings *self = user_data;
+ NMSettingsPrivate *priv = NM_SETTINGS_GET_PRIVATE (self);
+ GSourceFunc idle_func;
+ guint *p_id;
+ const char *prefix;
+
+ if (priv->kf_db_timestamps == kf_db) {
+ prefix = "timestamps";
+ p_id = &priv->kf_db_flush_idle_id_timestamps;
+ idle_func = _kf_db_got_dirty_flush_timestamps_cb;
+ } else if (priv->kf_db_seen_bssids == kf_db) {
+ prefix = "seen-bssids";
+ p_id = &priv->kf_db_flush_idle_id_seen_bssids;
+ idle_func = _kf_db_got_dirty_flush_seen_bssids_cb;
+ } else {
+ nm_assert_not_reached ();
+ return;
+ }
+
+ if (*p_id != 0)
+ return;
+ _LOGT ("[%s-keyfile]: schedule flushing changes to disk", prefix);
+ *p_id = g_idle_add_full (G_PRIORITY_LOW, idle_func, self, NULL);
+}
+
+void
+nm_settings_kf_db_write (NMSettings *self)
+{
+ NMSettingsPrivate *priv;
+
+ g_return_if_fail (NM_IS_SETTINGS (self));
+
+ priv = NM_SETTINGS_GET_PRIVATE (self);
+ if (priv->kf_db_timestamps)
+ nm_key_file_db_to_file (priv->kf_db_timestamps, TRUE);
+ if (priv->kf_db_seen_bssids)
+ nm_key_file_db_to_file (priv->kf_db_seen_bssids, TRUE);
+}
+
+/*****************************************************************************/
+
const char *
nm_settings_get_startup_complete_blocked_reason (NMSettings *self)
{
@@ -1797,6 +1924,19 @@ nm_settings_start (NMSettings *self, GError **error)
priv = NM_SETTINGS_GET_PRIVATE (self);
+ priv->kf_db_timestamps = nm_key_file_db_new (NMSTATEDIR "/timestamps",
+ "timestamps",
+ _kf_db_log_fcn,
+ _kf_db_got_dirty_fcn,
+ self);
+ priv->kf_db_seen_bssids = nm_key_file_db_new (NMSTATEDIR "/seen-bssids",
+ "seen-bssids",
+ _kf_db_log_fcn,
+ _kf_db_got_dirty_fcn,
+ self);
+ nm_key_file_db_start (priv->kf_db_timestamps);
+ nm_key_file_db_start (priv->kf_db_seen_bssids);
+
/* Load the plugins; fail if a plugin is not found. */
plugins = nm_config_data_get_plugins (nm_config_get_data_orig (priv->config), TRUE);
@@ -1933,6 +2073,13 @@ finalize (GObject *object)
g_clear_object (&priv->config);
+ nm_clear_g_source (&priv->kf_db_flush_idle_id_timestamps);
+ nm_clear_g_source (&priv->kf_db_flush_idle_id_seen_bssids);
+ nm_key_file_db_to_file (priv->kf_db_timestamps, FALSE);
+ nm_key_file_db_to_file (priv->kf_db_seen_bssids, FALSE);
+ nm_key_file_db_destroy (priv->kf_db_timestamps);
+ nm_key_file_db_destroy (priv->kf_db_seen_bssids);
+
G_OBJECT_CLASS (nm_settings_parent_class)->finalize (object);
}
diff --git a/src/settings/nm-settings.h b/src/settings/nm-settings.h
index eb74c09c4a..a3bd26a938 100644
--- a/src/settings/nm-settings.h
+++ b/src/settings/nm-settings.h
@@ -114,4 +114,6 @@ void nm_settings_device_removed (NMSettings *self, NMDevice *device, gboolean qu
const char *nm_settings_get_startup_complete_blocked_reason (NMSettings *self);
+void nm_settings_kf_db_write (NMSettings *settings);
+
#endif /* __NM_SETTINGS_H__ */