summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-07-19 16:55:47 +0200
committerThomas Haller <thaller@redhat.com>2019-07-25 22:02:00 +0200
commite3b5b1e64b9afe56ba5cd452775ba02a9d92dd2f (patch)
tree9c0c5d985f1cf80f70c188742e729e6eade8c7c2
parentaade7e5317253be58c4a5091bbb978e2a9adc0cd (diff)
downloadNetworkManager-e3b5b1e64b9afe56ba5cd452775ba02a9d92dd2f.tar.gz
settings: support storing "shadowed-storage" to [.nmmeta] section for keyfiles in /run
When we make runtime only changes, we may leave the profile in persistent storage and store a overlay profile in /run. However, in various cases we need to remember the original path. Add code to store and retrieve that path from the keyfile. Note that this data is written inside the keyfile in /run. That is because this piece of information really depends on that particular keyfile, and not on the profile/UUID. That is why we write it to the [.nmmeta] section of the keyfile and not to the .nmmeta file (which is per-UUID). This patch only adds the backend to write and load the setting from disk. It's not yet used.
-rw-r--r--libnm-core/nm-keyfile-internal.h2
-rw-r--r--src/settings/nm-settings.c17
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.c64
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.h6
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.c12
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-reader.h2
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.c14
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.h60
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.c24
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-writer.h2
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile-settings.c2
11 files changed, 193 insertions, 12 deletions
diff --git a/libnm-core/nm-keyfile-internal.h b/libnm-core/nm-keyfile-internal.h
index e1fb10c2b4..ced4ed975f 100644
--- a/libnm-core/nm-keyfile-internal.h
+++ b/libnm-core/nm-keyfile-internal.h
@@ -174,6 +174,8 @@ gboolean _nm_keyfile_has_values (GKeyFile *keyfile);
#define NM_KEYFILE_GROUP_NMMETA ".nmmeta"
#define NM_KEYFILE_KEY_NMMETA_NM_GENERATED "nm-generated"
#define NM_KEYFILE_KEY_NMMETA_VOLATILE "volatile"
+#define NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE "shadowed-storage"
+#define NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED "shadowed-owned"
#define NM_KEYFILE_PATH_NAME_LIB NMLIBDIR "/system-connections"
#define NM_KEYFILE_PATH_NAME_ETC_DEFAULT NMCONFDIR "/system-connections"
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 3e7d847b58..8679128a23 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -1284,6 +1284,8 @@ _add_connection_to_first_plugin (NMSettings *self,
gboolean in_memory,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
NMSettingsStorage **out_new_storage,
NMConnection **out_new_connection,
GError **error)
@@ -1311,9 +1313,11 @@ _add_connection_to_first_plugin (NMSettings *self,
if (plugin == (NMSettingsPlugin *) priv->keyfile_plugin) {
success = nms_keyfile_plugin_add_connection (priv->keyfile_plugin,
new_connection,
+ in_memory,
is_nm_generated,
is_volatile,
- in_memory,
+ shadowed_storage,
+ shadowed_owned,
&storage,
&connection_to_add,
&add_error);
@@ -1457,6 +1461,8 @@ nm_settings_add_connection (NMSettings *self,
| NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED)),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
+ NULL,
+ FALSE,
&new_storage,
&new_connection,
&local)) {
@@ -1538,6 +1544,8 @@ nm_settings_update_connection (NMSettings *self,
gboolean cur_in_memory;
gboolean new_in_memory;
const char *uuid;
+ const char *shadowed_storage;
+ gboolean shadowed_owned;
g_return_val_if_fail (NM_IS_SETTINGS (self), FALSE);
g_return_val_if_fail (NM_IS_SETTINGS_CONNECTION (sett_conn), FALSE);
@@ -1659,6 +1667,9 @@ nm_settings_update_connection (NMSettings *self,
| NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE);
}
+ /* TODO: set and handle shadowed-storages. */
+ shadowed_storage = NULL;
+ shadowed_owned = FALSE;
if (persist_mode == NM_SETTINGS_CONNECTION_PERSIST_MODE_NO_PERSIST) {
new_storage = g_object_ref (cur_storage);
@@ -1688,6 +1699,8 @@ nm_settings_update_connection (NMSettings *self,
new_in_memory,
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
+ shadowed_storage,
+ shadowed_owned,
&new_storage,
&new_connection,
&local);
@@ -1701,6 +1714,8 @@ nm_settings_update_connection (NMSettings *self,
connection,
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_NM_GENERATED),
NM_FLAGS_HAS (sett_flags, NM_SETTINGS_CONNECTION_INT_FLAGS_VOLATILE),
+ shadowed_storage,
+ shadowed_owned,
NM_FLAGS_HAS (update_reason, NM_SETTINGS_CONNECTION_UPDATE_REASON_FORCE_RENAME),
&new_storage,
&new_connection,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index a7048a8dd1..eb3ae5f100 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -216,13 +216,22 @@ _read_from_file (const char *full_filename,
struct stat *out_stat,
NMTernary *out_is_nm_generated,
NMTernary *out_is_volatile,
+ char **out_shadowed_storage,
+ NMTernary *out_shadowed_owned,
GError **error)
{
NMConnection *connection;
nm_assert (full_filename && full_filename[0] == '/');
- connection = nms_keyfile_reader_from_file (full_filename, plugin_dir, out_stat, out_is_nm_generated, out_is_volatile, error);
+ connection = nms_keyfile_reader_from_file (full_filename,
+ plugin_dir,
+ out_stat,
+ out_is_nm_generated,
+ out_is_volatile,
+ out_shadowed_storage,
+ out_shadowed_owned,
+ error);
nm_assert (!connection || (_nm_connection_verify (connection, NULL) == NM_SETTING_VERIFY_SUCCESS));
nm_assert (!connection || nm_utils_is_uuid (nm_connection_get_uuid (connection)));
@@ -291,6 +300,8 @@ _load_file (NMSKeyfilePlugin *self,
gs_unref_object NMConnection *connection = NULL;
NMTernary is_volatile_opt;
NMTernary is_nm_generated_opt;
+ NMTernary shadowed_owned_opt;
+ gs_free char *shadowed_storage = NULL;
gs_free_error GError *local = NULL;
gs_free char *full_filename = NULL;
struct stat st;
@@ -350,6 +361,8 @@ _load_file (NMSKeyfilePlugin *self,
&st,
&is_nm_generated_opt,
&is_volatile_opt,
+ &shadowed_storage,
+ &shadowed_owned_opt,
&local);
if (!connection) {
if (error)
@@ -365,6 +378,8 @@ _load_file (NMSKeyfilePlugin *self,
storage_type,
is_nm_generated_opt,
is_volatile_opt,
+ shadowed_storage,
+ shadowed_owned_opt,
&st.st_mtim);
}
@@ -725,9 +740,11 @@ load_connections (NMSettingsPlugin *plugin,
gboolean
nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
NMConnection *connection,
+ gboolean in_memory,
gboolean is_nm_generated,
gboolean is_volatile,
- gboolean in_memory,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error)
@@ -747,8 +764,16 @@ nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
nm_assert (out_storage && !*out_storage);
nm_assert (out_connection && !*out_connection);
+ nm_assert ( in_memory
+ || ( !is_nm_generated
+ && !is_volatile
+ && !shadowed_storage
+ && !shadowed_owned));
+
uuid = nm_connection_get_uuid (connection);
+ /* Note that even if the caller requests persistent storage, we may switch to in-memory, if
+ * no /etc directory is configured. */
storage_type = !in_memory && priv->dirname_etc
? NMS_KEYFILE_STORAGE_TYPE_ETC
: NMS_KEYFILE_STORAGE_TYPE_RUN;
@@ -756,6 +781,8 @@ nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
if (!nms_keyfile_writer_connection (connection,
is_nm_generated,
is_volatile,
+ shadowed_storage,
+ shadowed_owned,
storage_type == NMS_KEYFILE_STORAGE_TYPE_ETC
? priv->dirname_etc
: priv->dirname_run,
@@ -787,11 +814,12 @@ nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
nm_assert (full_filename && full_filename[0] == '/');
nm_assert (!nm_sett_util_storages_lookup_by_filename (&priv->storages, full_filename));
- _LOGT ("commit: %s (%s) added as \"%s\"%s",
+ _LOGT ("commit: %s (%s) added as \"%s\"%s%s%s%s",
uuid,
nm_connection_get_id (connection),
full_filename,
- _extra_flags_to_string (strbuf, sizeof (strbuf), is_nm_generated, is_volatile));
+ _extra_flags_to_string (strbuf, sizeof (strbuf), is_nm_generated, is_volatile),
+ NM_PRINT_FMT_QUOTED (shadowed_storage, " (shadows \"", shadowed_storage, shadowed_owned ? "\", owned)" : "\")", ""));
storage = nms_keyfile_storage_new_connection (self,
g_steal_pointer (&reread),
@@ -799,6 +827,8 @@ nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
storage_type,
is_nm_generated ? NM_TERNARY_TRUE : NM_TERNARY_FALSE,
is_volatile ? NM_TERNARY_TRUE : NM_TERNARY_FALSE,
+ shadowed_storage,
+ shadowed_owned ? NM_TERNARY_TRUE : NM_TERNARY_FALSE,
nm_sett_util_stat_mtime (full_filename, FALSE, &mtime));
nm_sett_util_storages_add_take (&priv->storages, g_object_ref (storage));
@@ -821,6 +851,8 @@ add_connection (NMSettingsPlugin *plugin,
FALSE,
FALSE,
FALSE,
+ NULL,
+ FALSE,
out_storage,
out_connection,
error);
@@ -832,6 +864,8 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
gboolean force_rename,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
@@ -847,6 +881,7 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
const char *previous_filename;
gboolean reread_same;
const char *uuid;
+ char strbuf[100];
_nm_assert_storage (self, storage, TRUE);
nm_assert (NM_IS_CONNECTION (connection));
@@ -855,11 +890,15 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
nm_assert (!error || !*error);
nm_assert (NM_IN_SET (storage->storage_type, NMS_KEYFILE_STORAGE_TYPE_ETC,
NMS_KEYFILE_STORAGE_TYPE_RUN));
- nm_assert ( (!is_nm_generated && !is_volatile)
- || storage->storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN);
+ nm_assert (!storage->is_meta_data);
+ nm_assert ( storage->storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN
+ || ( !is_nm_generated
+ && !is_volatile
+ && !shadowed_storage
+ && !shadowed_owned));
+ nm_assert (!shadowed_owned || shadowed_storage);
nm_assert ( priv->dirname_etc
|| storage->storage_type != NMS_KEYFILE_STORAGE_TYPE_ETC);
- nm_assert (!storage->is_meta_data);
previous_filename = nms_keyfile_storage_get_filename (storage);
uuid = nms_keyfile_storage_get_uuid (storage);
@@ -867,6 +906,8 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
if (!nms_keyfile_writer_connection (connection,
is_nm_generated,
is_volatile,
+ shadowed_storage,
+ shadowed_owned,
storage->storage_type == NMS_KEYFILE_STORAGE_TYPE_ETC
? priv->dirname_etc
: priv->dirname_run,
@@ -899,14 +940,17 @@ nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
nm_assert (_nm_connection_verify (reread, NULL) == NM_SETTING_VERIFY_SUCCESS);
nm_assert (nm_streq (nm_connection_get_uuid (reread), uuid));
- _LOGT ("commit: \"%s\": profile %s (%s) written",
+ _LOGT ("commit: \"%s\": profile %s (%s) written%s%s%s%s",
full_filename,
uuid,
- nm_connection_get_id (connection));
+ nm_connection_get_id (connection),
+ _extra_flags_to_string (strbuf, sizeof (strbuf), is_nm_generated, is_volatile),
+ NM_PRINT_FMT_QUOTED (shadowed_storage, shadowed_owned ? " (owns \"" : " (shadows \"", shadowed_storage, "\")", ""));
storage->u.conn_data.is_nm_generated = is_nm_generated;
storage->u.conn_data.is_volatile = is_volatile;
storage->u.conn_data.stat_mtime = *nm_sett_util_stat_mtime (full_filename, FALSE, &mtime);
+ storage->u.conn_data.shadowed_owned = shadowed_owned;
*out_storage = g_object_ref (NM_SETTINGS_STORAGE (storage));
*out_connection = g_steal_pointer (&reread);
@@ -926,6 +970,8 @@ update_connection (NMSettingsPlugin *plugin,
connection,
FALSE,
FALSE,
+ NULL,
+ FALSE,
FALSE,
out_storage,
out_connection,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.h b/src/settings/plugins/keyfile/nms-keyfile-plugin.h
index f3e6870861..b2a4a23864 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.h
@@ -42,9 +42,11 @@ NMSKeyfilePlugin *nms_keyfile_plugin_new (void);
gboolean nms_keyfile_plugin_add_connection (NMSKeyfilePlugin *self,
NMConnection *connection,
+ gboolean in_memory,
gboolean is_nm_generated,
gboolean is_volatile,
- gboolean in_memory,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
GError **error);
@@ -54,6 +56,8 @@ gboolean nms_keyfile_plugin_update_connection (NMSKeyfilePlugin *self,
NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
gboolean force_rename,
NMSettingsStorage **out_storage,
NMConnection **out_connection,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.c b/src/settings/plugins/keyfile/nms-keyfile-reader.c
index a6562a04dc..8d1f5599fe 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.c
@@ -164,6 +164,8 @@ nms_keyfile_reader_from_file (const char *full_filename,
struct stat *out_stat,
NMTernary *out_is_nm_generated,
NMTernary *out_is_volatile,
+ char **out_shadowed_storage,
+ NMTernary *out_shadowed_owned,
GError **error)
{
gs_unref_keyfile GKeyFile *key_file = NULL;
@@ -210,6 +212,16 @@ nms_keyfile_reader_from_file (const char *full_filename,
NM_KEYFILE_KEY_NMMETA_VOLATILE,
NM_TERNARY_DEFAULT));
+ NM_SET_OUT (out_shadowed_storage, g_key_file_get_string (key_file,
+ NM_KEYFILE_GROUP_NMMETA,
+ NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE,
+ NULL));
+
+ NM_SET_OUT (out_shadowed_owned, nm_key_file_get_boolean (key_file,
+ NM_KEYFILE_GROUP_NMMETA,
+ NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED,
+ NM_TERNARY_DEFAULT));
+
return connection;
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-reader.h b/src/settings/plugins/keyfile/nms-keyfile-reader.h
index b17b6dd77b..f20e6d93ee 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-reader.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-reader.h
@@ -37,6 +37,8 @@ NMConnection *nms_keyfile_reader_from_file (const char *full_filename,
struct stat *out_stat,
NMTernary *out_is_nm_generated,
NMTernary *out_is_volatile,
+ char **out_shadowed_storage,
+ NMTernary *out_shadowed_owned,
GError **error);
#endif /* __NMS_KEYFILE_READER_H__ */
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.c b/src/settings/plugins/keyfile/nms-keyfile-storage.c
index 33ebb8f941..b8bf3e6380 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.c
@@ -50,10 +50,13 @@ nms_keyfile_storage_copy_content (NMSKeyfileStorage *dst,
dst->u.meta_data = src->u.meta_data;
else {
gs_unref_object NMConnection *connection_to_free = NULL;
+ gs_free char *shadowed_storage_to_free = NULL;
connection_to_free = g_steal_pointer (&dst->u.conn_data.connection);
+ shadowed_storage_to_free = g_steal_pointer (&dst->u.conn_data.shadowed_storage);
dst->u.conn_data = src->u.conn_data;
nm_g_object_ref (dst->u.conn_data.connection);
+ dst->u.conn_data.shadowed_storage = g_strdup (dst->u.conn_data.shadowed_storage);
}
}
@@ -159,6 +162,8 @@ nms_keyfile_storage_new_connection (NMSKeyfilePlugin *plugin,
NMSKeyfileStorageType storage_type,
NMTernary is_nm_generated_opt,
NMTernary is_volatile_opt,
+ const char *shadowed_storage,
+ NMTernary shadowed_owned_opt,
const struct timespec *stat_mtime)
{
NMSKeyfileStorage *self;
@@ -175,12 +180,16 @@ nms_keyfile_storage_new_connection (NMSKeyfilePlugin *plugin,
self->u.conn_data.connection = connection_take; /* take reference. */
+ self->u.conn_data.shadowed_storage = g_strdup (shadowed_storage);
+
if (stat_mtime)
self->u.conn_data.stat_mtime = *stat_mtime;
if (storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN) {
self->u.conn_data.is_nm_generated = (is_nm_generated_opt == NM_TERNARY_TRUE);
self->u.conn_data.is_volatile = (is_volatile_opt == NM_TERNARY_TRUE);
+ self->u.conn_data.shadowed_owned = shadowed_storage
+ && (shadowed_owned_opt == NM_TERNARY_TRUE);
}
return self;
@@ -191,8 +200,11 @@ _storage_clear (NMSKeyfileStorage *self)
{
c_list_unlink (&self->parent._storage_lst);
c_list_unlink (&self->parent._storage_by_uuid_lst);
- if (!self->is_meta_data)
+ if (!self->is_meta_data) {
g_clear_object (&self->u.conn_data.connection);
+ nm_clear_g_free (&self->u.conn_data.shadowed_storage);
+ self->u.conn_data.shadowed_owned = FALSE;
+ }
}
static void
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.h b/src/settings/plugins/keyfile/nms-keyfile-storage.h
index 7968da09ac..5c43e79759 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.h
@@ -51,6 +51,19 @@ typedef struct {
struct {
NMConnection *connection;
+ /* when we move a profile from permanent storage to unsaved (/run), then
+ * we may leave the profile on disk (depending on options for Update2()).
+ *
+ * Later, when we save the profile again to disk, we want to re-use that filename.
+ * Likewise, we delete the (now in-memory) profile, we may want to also delete
+ * the original filename.
+ *
+ * This is the original filename, and we store it inside [.nmmeta] in the
+ * keyfile in /run. Note that we don't store this in the .nmmeta file, because
+ * the information is tied to the particular keyfile in /run, not to all UUIDs
+ * in general. */
+ char *shadowed_storage;
+
/* the timestamp (stat's mtime) of the keyfile. For meta-data this
* is irrelevant. The purpose is that if the same storage type (directory) has
* multiple files with the same UUID, then the newer file gets preferred. */
@@ -66,6 +79,11 @@ typedef struct {
bool is_nm_generated:1;
bool is_volatile:1;
+ /* if shadowed_storage is set, then this flag indicates whether the file
+ * is owned. The difference comes into play when deleting the in-memory,
+ * shadowing profile: a owned profile will also be deleted. */
+ bool shadowed_owned:1;
+
} conn_data;
/* the content from the .nmmeta file. Note that the nmmeta file has the UUID
@@ -106,6 +124,8 @@ NMSKeyfileStorage *nms_keyfile_storage_new_connection (struct _NMSKeyfilePlugin
NMSKeyfileStorageType storage_type,
NMTernary is_nm_generated_opt,
NMTernary is_volatile_opt,
+ const char *shadowed_storage,
+ NMTernary shadowed_owned_opt,
const struct timespec *stat_mtime);
void nms_keyfile_storage_destroy (NMSKeyfileStorage *storage);
@@ -188,6 +208,46 @@ nm_settings_storage_is_meta_data_alive (const NMSettingsStorage *storage)
return meta_data;
}
+static inline const char *
+nm_settings_storage_get_shadowed_storage (const NMSettingsStorage *storage,
+ gboolean *out_shadowed_owned)
+{
+ if (NMS_IS_KEYFILE_STORAGE (storage)) {
+ const NMSKeyfileStorage *self = (const NMSKeyfileStorage *) storage;
+
+ if (self->storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN) {
+ if (!self->is_meta_data) {
+ if (self->u.conn_data.shadowed_storage) {
+ NM_SET_OUT (out_shadowed_owned, self->u.conn_data.shadowed_owned);
+ return self->u.conn_data.shadowed_storage;
+ }
+ }
+ }
+ }
+
+ NM_SET_OUT (out_shadowed_owned, FALSE);
+ return NULL;
+}
+
+static inline const char *
+nm_settings_storage_get_filename_for_shadowed_storage (const NMSettingsStorage *storage)
+{
+ g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), NULL);
+
+ if (!storage->_filename)
+ return NULL;
+
+ if (NMS_IS_KEYFILE_STORAGE (storage)) {
+ const NMSKeyfileStorage *self = (const NMSKeyfileStorage *) storage;
+
+ if ( self->is_meta_data
+ || self->storage_type != NMS_KEYFILE_STORAGE_TYPE_ETC)
+ return NULL;
+ }
+
+ return storage->_filename;
+}
+
/*****************************************************************************/
enum _NMSettingsConnectionIntFlags;
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c
index 54e62b7373..5fbbb7a1c8 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c
@@ -170,6 +170,8 @@ static gboolean
_internal_write_connection (NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
const char *keyfile_dir,
const char *profile_dir,
gboolean with_extension,
@@ -201,6 +203,8 @@ _internal_write_connection (NMConnection *connection,
nm_assert (_nm_connection_verify (connection, NULL) == NM_SETTING_VERIFY_SUCCESS);
+ nm_assert (!shadowed_owned || shadowed_storage);
+
rename = force_rename
|| existing_path_read_only
|| ( existing_path
@@ -229,6 +233,20 @@ _internal_write_connection (NMConnection *connection,
TRUE);
}
+ if (shadowed_storage) {
+ g_key_file_set_string (kf_file,
+ NM_KEYFILE_GROUP_NMMETA,
+ NM_KEYFILE_KEY_NMMETA_SHADOWED_STORAGE,
+ shadowed_storage);
+ }
+
+ if (shadowed_owned) {
+ g_key_file_set_boolean (kf_file,
+ NM_KEYFILE_GROUP_NMMETA,
+ NM_KEYFILE_KEY_NMMETA_SHADOWED_OWNED,
+ TRUE);
+ }
+
kf_content_buf = g_key_file_to_data (kf_file, &kf_content_len, error);
if (!kf_content_buf)
return FALSE;
@@ -356,6 +374,8 @@ gboolean
nms_keyfile_writer_connection (NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
const char *keyfile_dir,
const char *profile_dir,
const char *existing_path,
@@ -371,6 +391,8 @@ nms_keyfile_writer_connection (NMConnection *connection,
return _internal_write_connection (connection,
is_nm_generated,
is_volatile,
+ shadowed_storage,
+ shadowed_owned,
keyfile_dir,
profile_dir,
TRUE,
@@ -400,6 +422,8 @@ nms_keyfile_writer_test_connection (NMConnection *connection,
return _internal_write_connection (connection,
FALSE,
FALSE,
+ NULL,
+ FALSE,
keyfile_dir,
keyfile_dir,
FALSE,
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.h b/src/settings/plugins/keyfile/nms-keyfile-writer.h
index 4fb9a20638..99e86025ae 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-writer.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-writer.h
@@ -29,6 +29,8 @@ typedef gboolean (*NMSKeyfileWriterAllowFilenameCb) (const char *check_filename,
gboolean nms_keyfile_writer_connection (NMConnection *connection,
gboolean is_nm_generated,
gboolean is_volatile,
+ const char *shadowed_storage,
+ gboolean shadowed_owned,
const char *keyfile_dir,
const char *profile_dir,
const char *existing_path,
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
index 5942f04bb1..ce7540ebda 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
@@ -75,6 +75,8 @@ check_ip_route (NMSettingIPConfig *config, int idx, const char *destination, int
NULL, \
NULL, \
NULL, \
+ NULL, \
+ NULL, \
(nmtst_get_rand_uint32 () % 2) ? &_error : NULL); \
nmtst_assert_success (_connection, _error); \
nmtst_assert_connection_verifies_without_normalization (_connection); \