mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-26 05:20:08 +01:00
core: merge branch 'th/cache-state-keyfiles'
https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/134
This commit is contained in:
commit
7a5bf59e5f
18 changed files with 794 additions and 231 deletions
|
|
@ -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 \
|
||||
|
|
|
|||
|
|
@ -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 ' '
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
413
shared/nm-glib-aux/nm-keyfile-aux.c
Normal file
413
shared/nm-glib-aux/nm-keyfile-aux.c
Normal file
|
|
@ -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);
|
||||
}
|
||||
78
shared/nm-glib-aux/nm-keyfile-aux.h
Normal file
78
shared/nm-glib-aux/nm-keyfile-aux.h
Normal file
|
|
@ -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__ */
|
||||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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), '/'); \
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
/* Remove connection from seen-bssids database file */
|
||||
remove_entry_from_db (self, "seen-bssids");
|
||||
if (priv->kf_db_timestamps)
|
||||
nm_key_file_db_remove_key (priv->kf_db_timestamps, connection_uuid);
|
||||
|
||||
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)
|
||||
if (!priv->kf_db_timestamps)
|
||||
return;
|
||||
if (nm_config_get_configure_and_quit (nm_config_get ()) == NM_CONFIG_CONFIGURE_AND_QUIT_INITRD)
|
||||
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;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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_seen_bssids != kf_db_seen_bssids) {
|
||||
gs_strfreev char **tmp_strv = NULL;
|
||||
gsize i, len;
|
||||
|
||||
priv->timestamp = timestamp;
|
||||
priv->timestamp_set = TRUE;
|
||||
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 */
|
||||
g_hash_table_add (priv->seen_bssids, g_strdup (seen_bssid));
|
||||
|
||||
/* 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);
|
||||
|
||||
/* 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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue