summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-07-24 16:26:16 +0200
committerThomas Haller <thaller@redhat.com>2019-07-25 23:27:48 +0200
commit064544cc07878caa248c3557c47f91736e5d2af1 (patch)
tree4c7662af4c48b3f083a4342db0ac5f8f343b1125
parente3b5b1e64b9afe56ba5cd452775ba02a9d92dd2f (diff)
downloadNetworkManager-064544cc07878caa248c3557c47f91736e5d2af1.tar.gz
settings: support storing "shadowed-storage" to .nmmeta files
Before, the .nmmeta file could only contain one piece of information: the loaded-path. This was persisted to disk by writing a "$UUID.nmmeta" symlink that links to the loaded-path. Also, in practice this is used for tombstones, so the only valid loaded-path is "/dev/null" (all other paths are ignored). Extend the .nmmeta file format to also be able to store additional data: the shadowed-storage path. We will need that later but the idea is that if we have a tombstone on disk, then this tombstone might explicitly shadow another file. The use is when re-adding a profile with the same UUID, then the existing storage is used (instead of creating a new file). This will be necessary with Update2(NM_SETTINGS_UPDATE2_FLAG_IN_MEMORY_DETACHED) flag. This flag first allows to clone a profile from persistent storage to a profile in /run. Later, when this profile gets deleted, the original profile will be left on disk. If the same profile then gets re-created with AddConnection(), then the original filename must be taken over again. This is to avoid duplication of profiles on disk. Note that this piece of information is relevent per-UUID, and as such it's correct to store it in the .nmmeta file. That is related to the "shadowed-storage" information that we store in the [.nmmeta] section of keyfiles.
-rw-r--r--src/settings/nm-settings.c3
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.c22
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-plugin.h1
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.c17
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-storage.h7
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-utils.c111
-rw-r--r--src/settings/plugins/keyfile/nms-keyfile-utils.h7
-rw-r--r--src/settings/plugins/keyfile/tests/test-keyfile-settings.c6
8 files changed, 137 insertions, 37 deletions
diff --git a/src/settings/nm-settings.c b/src/settings/nm-settings.c
index 8679128a23..7dadd4e3e3 100644
--- a/src/settings/nm-settings.c
+++ b/src/settings/nm-settings.c
@@ -1914,6 +1914,7 @@ nm_settings_delete_connection (NMSettings *self,
uuid,
FALSE,
TRUE,
+ NULL,
&tombstone_1_storage,
NULL))
tombstone_in_memory = TRUE;
@@ -1927,6 +1928,7 @@ nm_settings_delete_connection (NMSettings *self,
uuid,
TRUE,
TRUE,
+ NULL,
&tombstone_2_storage,
NULL)) {
nms_keyfile_plugin_set_nmmeta_tombstone (priv->keyfile_plugin,
@@ -1934,6 +1936,7 @@ nm_settings_delete_connection (NMSettings *self,
uuid,
TRUE,
TRUE,
+ NULL,
&tombstone_2_storage,
NULL);
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.c b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
index eb3ae5f100..fbe70ef4d2 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.c
@@ -309,6 +309,7 @@ _load_file (NMSKeyfilePlugin *self,
if (_ignore_filename (storage_type, filename)) {
gs_free char *nmmeta = NULL;
gs_free char *loaded_path = NULL;
+ gs_free char *shadowed_storage_filename = NULL;
if (!nms_keyfile_nmmeta_check_filename (filename, NULL)) {
if (error)
@@ -322,6 +323,7 @@ _load_file (NMSKeyfilePlugin *self,
&full_filename,
&nmmeta,
&loaded_path,
+ &shadowed_storage_filename,
NULL)) {
if (error)
nm_utils_error_set (error, NM_UTILS_ERROR_UNKNOWN, "skip unreadable nmmeta file");
@@ -349,7 +351,8 @@ _load_file (NMSKeyfilePlugin *self,
return nms_keyfile_storage_new_tombstone (self,
nmmeta,
full_filename,
- storage_type);
+ storage_type,
+ shadowed_storage_filename);
}
full_filename = g_build_filename (dirname, filename, NULL);
@@ -1052,6 +1055,9 @@ delete_connection (NMSettingsPlugin *plugin,
* has no /etc directory configured, this results in a hard failure.
* @set: if %TRUE, write the symlink to point to /dev/null. If %FALSE,
* delete the nmmeta file (if it exists).
+ * @shadowed_storage: a tombstone can also shadow an existing storage.
+ * In combination with @set and @in_memory, this is allowed to store
+ * the shadowed storage filename.
* @out_storage: (transfer full) (allow-none): the storage element that changes, or
* NULL if nothing changed. Note that the file on disk is already as
* we want to write it, then this still counts as a change. No change only
@@ -1076,6 +1082,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
const char *uuid,
gboolean in_memory,
gboolean set,
+ const char *shadowed_storage,
NMSettingsStorage **out_storage,
gboolean *out_hard_failure)
{
@@ -1092,6 +1099,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
nm_assert (NMS_IS_KEYFILE_PLUGIN (self));
nm_assert (nm_utils_is_uuid (uuid));
nm_assert (!out_storage || !*out_storage);
+ nm_assert (!shadowed_storage || (set && in_memory));
priv = NMS_KEYFILE_PLUGIN_GET_PRIVATE (self);
@@ -1104,7 +1112,7 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
dirname = priv->dirname_run;
} else {
if (!priv->dirname_etc) {
- _LOGT ("commit: cannot %s%s nmmeta symlink for %s as there is no /etc directory",
+ _LOGT ("commit: cannot %s%s nmmeta file for %s as there is no /etc directory",
simulate ? "simulate " : "",
loaded_path ? "write" : "delete",
uuid);
@@ -1123,13 +1131,15 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
uuid,
loaded_path,
FALSE,
+ shadowed_storage,
&nmmeta_filename);
}
- _LOGT ("commit: %s nmmeta symlink \"%s\"%s%s%s %s",
+ _LOGT ("commit: %s nmmeta file \"%s\"%s%s%s%s%s%s %s",
loaded_path ? "writing" : "deleting",
nmmeta_filename,
NM_PRINT_FMT_QUOTED (loaded_path, " (pointing to \"", loaded_path, "\")", ""),
+ NM_PRINT_FMT_QUOTED (shadowed_storage, " (shadows \"", shadowed_storage, "\")", ""),
simulate
? "simulated"
: ( nmmeta_success
@@ -1152,8 +1162,12 @@ nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
storage = nms_keyfile_storage_new_tombstone (self,
uuid,
nmmeta_filename,
- storage_type);
+ storage_type,
+ shadowed_storage);
nm_sett_util_storages_add_take (&priv->storages, storage);
+ } else {
+ g_free (storage->u.meta_data.shadowed_storage);
+ storage->u.meta_data.shadowed_storage = g_strdup (shadowed_storage);
}
storage_result = g_object_ref (storage);
diff --git a/src/settings/plugins/keyfile/nms-keyfile-plugin.h b/src/settings/plugins/keyfile/nms-keyfile-plugin.h
index b2a4a23864..4844096456 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-plugin.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-plugin.h
@@ -68,6 +68,7 @@ gboolean nms_keyfile_plugin_set_nmmeta_tombstone (NMSKeyfilePlugin *self,
const char *uuid,
gboolean in_memory,
gboolean set,
+ const char *shadowed_storage,
NMSettingsStorage **out_storage,
gboolean *out_hard_failure);
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.c b/src/settings/plugins/keyfile/nms-keyfile-storage.c
index b8bf3e6380..d68d60c8ec 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.c
@@ -46,9 +46,13 @@ nms_keyfile_storage_copy_content (NMSKeyfileStorage *dst,
nm_assert (dst->storage_type == src->storage_type);
nm_assert (dst->is_meta_data == src->is_meta_data);
- if (dst->is_meta_data)
+ if (dst->is_meta_data) {
+ gs_free char *shadowed_storage_to_free = NULL;
+
+ shadowed_storage_to_free = g_steal_pointer (&dst->u.meta_data.shadowed_storage);
dst->u.meta_data = src->u.meta_data;
- else {
+ dst->u.meta_data.shadowed_storage = g_strdup (dst->u.meta_data.shadowed_storage);
+ } else {
gs_unref_object NMConnection *connection_to_free = NULL;
gs_free char *shadowed_storage_to_free = NULL;
@@ -140,7 +144,8 @@ NMSKeyfileStorage *
nms_keyfile_storage_new_tombstone (NMSKeyfilePlugin *plugin,
const char *uuid,
const char *filename,
- NMSKeyfileStorageType storage_type)
+ NMSKeyfileStorageType storage_type,
+ const char *shadowed_storage)
{
NMSKeyfileStorage *self;
@@ -152,6 +157,8 @@ nms_keyfile_storage_new_tombstone (NMSKeyfilePlugin *plugin,
self = _storage_new (plugin, uuid, filename, TRUE, storage_type);
self->u.meta_data.is_tombstone = TRUE;
+ if (storage_type == NMS_KEYFILE_STORAGE_TYPE_RUN)
+ self->u.meta_data.shadowed_storage = g_strdup (shadowed_storage);
return self;
}
@@ -200,7 +207,9 @@ _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)
+ nm_clear_g_free (&self->u.meta_data.shadowed_storage);
+ else {
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;
diff --git a/src/settings/plugins/keyfile/nms-keyfile-storage.h b/src/settings/plugins/keyfile/nms-keyfile-storage.h
index 5c43e79759..2252b47b7e 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-storage.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-storage.h
@@ -35,6 +35,7 @@
typedef struct {
/* whether this is a tombstone to hide a UUID (via symlink to /dev/null). */
+ char *shadowed_storage;
bool is_tombstone:1;
} NMSettingsMetaData;
@@ -116,7 +117,8 @@ struct _NMSKeyfilePlugin;
NMSKeyfileStorage *nms_keyfile_storage_new_tombstone (struct _NMSKeyfilePlugin *self,
const char *uuid,
const char *filename,
- NMSKeyfileStorageType storage_type);
+ NMSKeyfileStorageType storage_type,
+ const char *shadowed_storage);
NMSKeyfileStorage *nms_keyfile_storage_new_connection (struct _NMSKeyfilePlugin *self,
NMConnection *connection_take /* pass reference */,
@@ -221,6 +223,9 @@ nm_settings_storage_get_shadowed_storage (const NMSettingsStorage *storage,
NM_SET_OUT (out_shadowed_owned, self->u.conn_data.shadowed_owned);
return self->u.conn_data.shadowed_storage;
}
+ } else {
+ NM_SET_OUT (out_shadowed_owned, FALSE);
+ return self->u.meta_data.shadowed_storage;
}
}
}
diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.c b/src/settings/plugins/keyfile/nms-keyfile-utils.c
index e9d5351573..ea03e1b611 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-utils.c
+++ b/src/settings/plugins/keyfile/nms-keyfile-utils.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <sys/stat.h>
+#include "nm-glib-aux/nm-io-utils.h"
#include "nm-keyfile-internal.h"
#include "nm-utils.h"
#include "nm-setting-wired.h"
@@ -33,6 +34,13 @@
/*****************************************************************************/
+#define NMMETA_KF_GROUP_NAME_NMMETA "nmmeta"
+#define NMMETA_KF_KEY_NAME_NMMETA_UUID "uuid"
+#define NMMETA_KF_KEY_NAME_NMMETA_LOADED_PATH "loaded-path"
+#define NMMETA_KF_KEY_NAME_NMMETA_SHADOWED_STORAGE "shadowed-storage"
+
+/*****************************************************************************/
+
const char *
nms_keyfile_nmmeta_check_filename (const char *filename,
guint *out_uuid_len)
@@ -106,12 +114,16 @@ nms_keyfile_nmmeta_read (const char *dirname,
char **out_full_filename,
char **out_uuid,
char **out_loaded_path,
+ char **out_shadowed_storage,
struct stat *out_st)
{
const char *uuid;
guint uuid_len;
gs_free char *full_filename = NULL;
- gs_free char *ln = NULL;
+ gs_free char *loaded_path = NULL;
+ gs_free char *shadowed_storage = NULL;
+ struct stat st_stack;
+ struct stat *st = out_st ?: &st_stack;
nm_assert (dirname && dirname[0] == '/');
nm_assert (filename && filename[0] && !strchr (filename, '/'));
@@ -124,17 +136,43 @@ nms_keyfile_nmmeta_read (const char *dirname,
if (!nms_keyfile_utils_check_file_permissions (NMS_KEYFILE_FILETYPE_NMMETA,
full_filename,
- out_st,
+ st,
NULL))
return FALSE;
- ln = nm_utils_read_link_absolute (full_filename, NULL);
- if (!ln)
- return FALSE;
+ if (S_ISREG (st->st_mode)) {
+ gs_unref_keyfile GKeyFile *kf = NULL;
+ gs_free char *v_uuid = NULL;
+
+ kf = g_key_file_new ();
+
+ if (!g_key_file_load_from_file (kf, full_filename, G_KEY_FILE_NONE, NULL))
+ return FALSE;
+
+ v_uuid = g_key_file_get_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_UUID, NULL);
+ if (!nm_streq0 (v_uuid, uuid))
+ return FALSE;
+
+ loaded_path = g_key_file_get_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_LOADED_PATH, NULL);
+ shadowed_storage = g_key_file_get_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_SHADOWED_STORAGE, NULL);
+
+ if ( !loaded_path
+ && !shadowed_storage) {
+ /* if there is no useful information in the file, it is the same as if
+ * the file is not present. Signal failure. */
+ return FALSE;
+ }
+
+ } else {
+ loaded_path = nm_utils_read_link_absolute (full_filename, NULL);
+ if (!loaded_path)
+ return FALSE;
+ }
NM_SET_OUT (out_uuid, g_strndup (uuid, uuid_len));
NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename));
- NM_SET_OUT (out_loaded_path, g_steal_pointer (&ln));
+ NM_SET_OUT (out_loaded_path, g_steal_pointer (&loaded_path));
+ NM_SET_OUT (out_shadowed_storage, g_steal_pointer (&shadowed_storage));
return TRUE;
}
@@ -143,7 +181,8 @@ nms_keyfile_nmmeta_read_from_file (const char *full_filename,
char **out_dirname,
char **out_filename,
char **out_uuid,
- char **out_loaded_path)
+ char **out_loaded_path,
+ char **out_shadowed_storage)
{
gs_free char *dirname = NULL;
gs_free char *filename = NULL;
@@ -158,6 +197,7 @@ nms_keyfile_nmmeta_read_from_file (const char *full_filename,
NULL,
out_uuid,
out_loaded_path,
+ out_shadowed_storage,
NULL))
return FALSE;
@@ -170,7 +210,8 @@ gboolean
nms_keyfile_nmmeta_write (const char *dirname,
const char *uuid,
const char *loaded_path,
- gboolean allow_relative,
+ gboolean loaded_path_allow_relative,
+ const char *shadowed_storage,
char **out_full_filename)
{
gs_free char *full_filename_tmp = NULL;
@@ -180,6 +221,7 @@ nms_keyfile_nmmeta_write (const char *dirname,
nm_assert ( nm_utils_is_uuid (uuid)
&& !strchr (uuid, '/'));
nm_assert (!loaded_path || loaded_path[0] == '/');
+ nm_assert (!shadowed_storage || loaded_path);
full_filename_tmp = nms_keyfile_nmmeta_filename (dirname, uuid, TRUE);
@@ -198,7 +240,7 @@ nms_keyfile_nmmeta_write (const char *dirname,
return success;
}
- if (allow_relative) {
+ if (loaded_path_allow_relative) {
const char *f;
f = nm_utils_file_is_in_path (loaded_path, dirname);
@@ -209,18 +251,40 @@ nms_keyfile_nmmeta_write (const char *dirname,
}
}
- if (symlink (loaded_path, full_filename_tmp) != 0) {
- full_filename_tmp[strlen (full_filename_tmp) - 1] = '\0';
- NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp));
- return FALSE;
- }
+ full_filename = g_strndup (full_filename_tmp, strlen (full_filename_tmp) - 1);
- full_filename = g_strdup (full_filename_tmp);
- full_filename[strlen (full_filename) - 1] = '\0';
- if (rename (full_filename_tmp, full_filename) != 0) {
- (void) unlink (full_filename_tmp);
- NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename));
- return FALSE;
+ if (shadowed_storage) {
+ gs_unref_keyfile GKeyFile *kf = NULL;
+ gs_free char *contents = NULL;
+ gsize length;
+
+ kf = g_key_file_new ();
+
+ g_key_file_set_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_UUID, uuid);
+ g_key_file_set_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_LOADED_PATH, loaded_path);
+ g_key_file_set_string (kf, NMMETA_KF_GROUP_NAME_NMMETA, NMMETA_KF_KEY_NAME_NMMETA_SHADOWED_STORAGE, shadowed_storage);
+
+ contents = g_key_file_to_data (kf, &length, NULL);
+
+ if (!nm_utils_file_set_contents (full_filename, contents, length, 0600, NULL)) {
+ NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp));
+ return FALSE;
+ }
+ } else {
+ /* we only have the "loaded_path" to store. That is commonly used for the tombstones to
+ * link to /dev/null. A symlink is sufficient to store that ammount of information.
+ * No need to bother with a keyfile. */
+ if (symlink (loaded_path, full_filename_tmp) != 0) {
+ full_filename_tmp[strlen (full_filename_tmp) - 1] = '\0';
+ NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename_tmp));
+ return FALSE;
+ }
+
+ if (rename (full_filename_tmp, full_filename) != 0) {
+ (void) unlink (full_filename_tmp);
+ NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename));
+ return FALSE;
+ }
}
NM_SET_OUT (out_full_filename, g_steal_pointer (&full_filename));
@@ -243,9 +307,10 @@ nms_keyfile_utils_check_file_permissions_stat (NMSKeyfileFiletype filetype,
return FALSE;
}
} else if (filetype == NMS_KEYFILE_FILETYPE_NMMETA) {
- if (!S_ISLNK (st->st_mode)) {
+ if ( !S_ISLNK (st->st_mode)
+ && !S_ISREG (st->st_mode)) {
g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
- "file is not a slink");
+ "file is neither a symlink nor a regular file");
return FALSE;
}
} else
@@ -259,7 +324,7 @@ nms_keyfile_utils_check_file_permissions_stat (NMSKeyfileFiletype filetype,
return FALSE;
}
- if ( filetype == NMS_KEYFILE_FILETYPE_KEYFILE
+ if ( S_ISREG (st->st_mode)
&& (st->st_mode & 0077)) {
g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_INVALID_CONNECTION,
"File permissions (%03o) are insecure",
diff --git a/src/settings/plugins/keyfile/nms-keyfile-utils.h b/src/settings/plugins/keyfile/nms-keyfile-utils.h
index 4f4ad54091..723c443625 100644
--- a/src/settings/plugins/keyfile/nms-keyfile-utils.h
+++ b/src/settings/plugins/keyfile/nms-keyfile-utils.h
@@ -56,18 +56,21 @@ gboolean nms_keyfile_nmmeta_read (const char *dirname,
char **out_full_filename,
char **out_uuid,
char **out_loaded_path,
+ char **out_shadowed_storage,
struct stat *out_st);
gboolean nms_keyfile_nmmeta_read_from_file (const char *full_filename,
char **out_dirname,
char **out_filename,
char **out_uuid,
- char **out_loaded_path);
+ char **out_loaded_path,
+ char **out_shadowed_storage);
gboolean nms_keyfile_nmmeta_write (const char *dirname,
const char *uuid,
const char *loaded_path,
- gboolean allow_relative,
+ gboolean loaded_path_allow_relative,
+ const char *shadowed_storage,
char **out_full_filename);
/*****************************************************************************/
diff --git a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
index ce7540ebda..f96111a2e4 100644
--- a/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
+++ b/src/settings/plugins/keyfile/tests/test-keyfile-settings.c
@@ -2543,7 +2543,7 @@ _assert_keyfile_nmmeta (const char *dirname,
nm_clear_g_free (&full_filename);
- g_assert (nms_keyfile_nmmeta_write (dirname, uuid, loaded_path, allow_relative, &full_filename));
+ g_assert (nms_keyfile_nmmeta_write (dirname, uuid, loaded_path, allow_relative, NULL, &full_filename));
g_assert_cmpstr (full_filename, ==, exp_full_filename);
nm_clear_g_free (&full_filename);
@@ -2555,7 +2555,7 @@ _assert_keyfile_nmmeta (const char *dirname,
g_assert_cmpstr (symlink_target, ==, exp_symlink_target);
- success = nms_keyfile_nmmeta_read (dirname, filename, &full_filename, &uuid2, &loaded_path2, NULL);
+ success = nms_keyfile_nmmeta_read (dirname, filename, &full_filename, &uuid2, &loaded_path2, NULL, NULL);
g_assert_cmpint (!!exp_uuid, ==, success);
if (success)
g_assert_cmpstr (full_filename, ==, exp_full_filename);
@@ -2566,7 +2566,7 @@ _assert_keyfile_nmmeta (const char *dirname,
g_assert_cmpstr (loaded_path2, ==, exp_loaded_path);
- success = nms_keyfile_nmmeta_read_from_file (exp_full_filename, &dirname3, &filename3, &uuid3, &loaded_path3);
+ success = nms_keyfile_nmmeta_read_from_file (exp_full_filename, &dirname3, &filename3, &uuid3, &loaded_path3, NULL);
g_assert_cmpint (!!exp_uuid, ==, success);
if (success) {
g_assert_cmpstr (dirname3, ==, dirname);