diff options
Diffstat (limited to 'src/settings/plugins/keyfile/nms-keyfile-writer.c')
| -rw-r--r-- | src/settings/plugins/keyfile/nms-keyfile-writer.c | 173 |
1 files changed, 105 insertions, 68 deletions
diff --git a/src/settings/plugins/keyfile/nms-keyfile-writer.c b/src/settings/plugins/keyfile/nms-keyfile-writer.c index 2e06aeb9..5fbbb7a1 100644 --- a/src/settings/plugins/keyfile/nms-keyfile-writer.c +++ b/src/settings/plugins/keyfile/nms-keyfile-writer.c @@ -1,4 +1,3 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ /* NetworkManager system settings service - keyfile plugin * * This program is free software; you can redistribute it and/or modify @@ -169,6 +168,10 @@ _handler_write (NMConnection *connection, 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, @@ -177,6 +180,8 @@ _internal_write_connection (NMConnection *connection, const char *existing_path, gboolean existing_path_read_only, gboolean force_rename, + NMSKeyfileWriterAllowFilenameCb allow_filename_cb, + gpointer allow_filename_user_data, char **out_path, NMConnection **out_reread, gboolean *out_reread_same, @@ -191,33 +196,57 @@ _internal_write_connection (NMConnection *connection, GError *local_err = NULL; int errsv; gboolean rename; + int i_path; g_return_val_if_fail (!out_path || !*out_path, FALSE); g_return_val_if_fail (keyfile_dir && keyfile_dir[0] == '/', FALSE); + 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 && !nm_utils_file_is_in_path (existing_path, keyfile_dir)); - switch (_nm_connection_verify (connection, error)) { - case NM_SETTING_VERIFY_NORMALIZABLE: - nm_assert_not_reached (); - /* fall-through */ - case NM_SETTING_VERIFY_SUCCESS: - break; - default: - g_return_val_if_reached (FALSE); - } - id = nm_connection_get_id (connection); - g_assert (id && *id); + nm_assert (id && *id); info.keyfile_dir = keyfile_dir; kf_file = nm_keyfile_write (connection, _handler_write, &info, error); if (!kf_file) return FALSE; + + if (is_nm_generated) { + g_key_file_set_boolean (kf_file, + NM_KEYFILE_GROUP_NMMETA, + NM_KEYFILE_KEY_NMMETA_NM_GENERATED, + TRUE); + } + + if (is_volatile) { + g_key_file_set_boolean (kf_file, + NM_KEYFILE_GROUP_NMMETA, + NM_KEYFILE_KEY_NMMETA_VOLATILE, + 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; @@ -225,64 +254,59 @@ _internal_write_connection (NMConnection *connection, if (!g_file_test (keyfile_dir, G_FILE_TEST_IS_DIR)) (void) g_mkdir_with_parents (keyfile_dir, 0755); - /* If we have existing file path, use it. Else generate one from - * connection's ID. - */ - if ( existing_path - && !rename) - path = g_strdup (existing_path); - else { - gs_free char *filename_escaped = NULL; + for (i_path = -2; i_path < 10000; i_path++) { + gs_free char *path_candidate = NULL; + gboolean is_existing_path; - filename_escaped = nm_keyfile_utils_create_filename (id, with_extension); - path = g_build_filename (keyfile_dir, filename_escaped, NULL); - } - - /* If a file with this path already exists (but isn't the existing path - * of the connection) then we need another name. Multiple connections - * can have the same ID (ie if two connections with the same ID are visible - * to different users) but of course can't have the same path. Yeah, - * there's a race here, but there's not a lot we can do about it, and - * we shouldn't get more than one connection with the same UUID either. - */ - if ( !nm_streq0 (path, existing_path) - && g_file_test (path, G_FILE_TEST_EXISTS)) { - guint i; - gboolean name_found = FALSE; + if (i_path == -2) { + if ( !existing_path + || rename) + continue; + path_candidate = g_strdup (existing_path); + } else if (i_path == -1) { + gs_free char *filename_escaped = NULL; - /* A keyfile with this connection's ID already exists. Pick another name. */ - for (i = 0; i < 100; i++) { + filename_escaped = nm_keyfile_utils_create_filename (id, with_extension); + path_candidate = g_build_filename (keyfile_dir, filename_escaped, NULL); + } else { gs_free char *filename_escaped = NULL; gs_free char *filename = NULL; - if (i == 0) + if (i_path == 0) filename = g_strdup_printf ("%s-%s", id, nm_connection_get_uuid (connection)); else - filename = g_strdup_printf ("%s-%s-%u", id, nm_connection_get_uuid (connection), i); + filename = g_strdup_printf ("%s-%s-%d", id, nm_connection_get_uuid (connection), i_path); filename_escaped = nm_keyfile_utils_create_filename (filename, with_extension); - g_free (path); - path = g_strdup_printf ("%s/%s", keyfile_dir, filename_escaped); - - if ( nm_streq0 (path, existing_path) - || !g_file_test (path, G_FILE_TEST_EXISTS)) { - name_found = TRUE; - break; - } + path_candidate = g_strdup_printf ("%s/%s", keyfile_dir, filename_escaped); } - if (!name_found) { - if (existing_path_read_only || !existing_path) { - /* this really should not happen, we tried hard to find an unused name... bail out. */ - g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, - "could not find suitable keyfile file name (%s already used)", path); - return FALSE; - } - /* Both our preferred path based on connection id and id-uuid are taken. - * Fallback to @existing_path */ - g_free (path); - path = g_strdup (existing_path); + + is_existing_path = existing_path + && nm_streq (existing_path, path_candidate); + + if ( is_existing_path + && rename) + continue; + + if ( allow_filename_cb + && !allow_filename_cb (path_candidate, allow_filename_user_data)) + continue; + + if (!is_existing_path) { + if (g_file_test (path_candidate, G_FILE_TEST_EXISTS)) + continue; } + + path = g_steal_pointer (&path_candidate); + break; + } + + if (!path) { + /* this really should not happen, we tried hard to find an unused name... bail out. */ + g_set_error (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_FAILED, + "could not find suitable keyfile file name (%s already used)", path); + return FALSE; } nm_utils_file_set_contents (path, kf_content_buf, kf_content_len, 0600, &local_err); @@ -348,30 +372,37 @@ _internal_write_connection (NMConnection *connection, gboolean nms_keyfile_writer_connection (NMConnection *connection, - gboolean save_to_disk, + 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, + gboolean existing_path_read_only, gboolean force_rename, + NMSKeyfileWriterAllowFilenameCb allow_filename_cb, + gpointer allow_filename_user_data, char **out_path, NMConnection **out_reread, gboolean *out_reread_same, GError **error) { - const char *keyfile_dir; - - if (save_to_disk) - keyfile_dir = nms_keyfile_utils_get_path (); - else - keyfile_dir = NM_KEYFILE_PATH_NAME_RUN; - return _internal_write_connection (connection, + is_nm_generated, + is_volatile, + shadowed_storage, + shadowed_owned, keyfile_dir, - nms_keyfile_utils_get_path (), + profile_dir, TRUE, 0, 0, existing_path, - FALSE, + existing_path_read_only, force_rename, + allow_filename_cb, + allow_filename_user_data, out_path, out_reread, out_reread_same, @@ -389,6 +420,10 @@ nms_keyfile_writer_test_connection (NMConnection *connection, GError **error) { return _internal_write_connection (connection, + FALSE, + FALSE, + NULL, + FALSE, keyfile_dir, keyfile_dir, FALSE, @@ -397,6 +432,8 @@ nms_keyfile_writer_test_connection (NMConnection *connection, NULL, FALSE, FALSE, + NULL, + NULL, out_path, out_reread, out_reread_same, |