about summary refs log tree commit diff
path: root/src/NetworkManagerUtils.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/NetworkManagerUtils.c')
-rw-r--r--src/NetworkManagerUtils.c185
1 files changed, 106 insertions, 79 deletions
diff --git a/src/NetworkManagerUtils.c b/src/NetworkManagerUtils.c
index b208ffc6..89bd357f 100644
--- a/src/NetworkManagerUtils.c
+++ b/src/NetworkManagerUtils.c
@@ -31,6 +31,7 @@
 #include "nm-core-internal.h"
 
 #include "platform/nm-platform.h"
+#include "nm-exported-object.h"
 #include "nm-auth-utils.h"
 
 /*****************************************************************************/
@@ -67,93 +68,98 @@ nm_utils_get_shared_wifi_permission (NMConnection *connection)
 /*****************************************************************************/
 
 static char *
-get_new_connection_name (NMConnection *const*existing_connections,
+get_new_connection_name (const GSList *existing,
                          const char *preferred,
                          const char *fallback_prefix)
 {
-	gs_free const char **existing_names = NULL;
-	guint i, existing_len = 0;
+	GSList *names = NULL;
+	const GSList *iter;
+	char *cname = NULL;
+	int i = 0;
+	gboolean preferred_found = FALSE;
 
 	g_assert (fallback_prefix);
 
-	if (existing_connections) {
-		existing_len = NM_PTRARRAY_LEN (existing_connections);
-		existing_names = g_new (const char *, existing_len);
-		for (i = 0; i < existing_len; i++) {
-			NMConnection *candidate;
-			const char *id;
+	for (iter = existing; iter; iter = g_slist_next (iter)) {
+		NMConnection *candidate = NM_CONNECTION (iter->data);
+		const char *id;
 
-			candidate = existing_connections[i];
-			nm_assert (NM_IS_CONNECTION (candidate));
+		id = nm_connection_get_id (candidate);
+		g_assert (id);
+		names = g_slist_append (names, (gpointer) id);
 
-			id = nm_connection_get_id (candidate);
-			nm_assert (id);
-
-			existing_names[i] = id;
-
-			if (   preferred
-				&& nm_streq (preferred, id)) {
-				/* the preferred name is already taken. Forget about it. */
-				preferred = NULL;
-			}
-		}
-		nm_assert (!existing_connections[i]);
+		if (preferred && !preferred_found && (strcmp (preferred, id) == 0))
+			preferred_found = TRUE;
 	}
 
 	/* Return the preferred name if it was unique */
-	if (preferred)
+	if (preferred && !preferred_found) {
+		g_slist_free (names);
 		return g_strdup (preferred);
+	}
 
 	/* Otherwise find the next available unique connection name using the given
 	 * connection name template.
 	 */
-	for (i = 1; TRUE; i++) {
+	while (!cname && (i++ < 10000)) {
 		char *temp;
+		gboolean found = FALSE;
 
-		/* TRANSLATORS: the first %s is a prefix for the connection id, such
+		/* Translators: the first %s is a prefix for the connection id, such
 		 * as "Wired Connection" or "VPN Connection". The %d is a number
 		 * that is combined with the first argument to create a unique
 		 * connection id. */
-		temp = g_strdup_printf (C_("connection id fallback", "%s %u"),
+		temp = g_strdup_printf (C_("connection id fallback", "%s %d"),
 		                        fallback_prefix, i);
-
-		if (nm_utils_strv_find_first ((char **) existing_names,
-		                              existing_len,
-		                              temp) < 0)
-			return temp;
-
-		g_free (temp);
+		for (iter = names; iter; iter = g_slist_next (iter)) {
+			if (!strcmp (iter->data, temp)) {
+				found = TRUE;
+				break;
+			}
+		}
+		if (!found)
+			cname = temp;
+		else
+			g_free (temp);
 	}
+
+	g_slist_free (names);
+	return cname;
 }
 
 static char *
 get_new_connection_ifname (NMPlatform *platform,
-                           NMConnection *const*existing_connections,
+                           const GSList *existing,
                            const char *prefix)
 {
-	guint i, j;
-
-	for (i = 0; TRUE; i++) {
-		char *name;
+	int i;
+	char *name;
+	const GSList *iter;
+	gboolean found;
 
+	for (i = 0; i < 500; i++) {
 		name = g_strdup_printf ("%s%d", prefix, i);
 
 		if (nm_platform_link_get_by_ifname (platform, name))
 			goto next;
 
-		if (existing_connections) {
-			for (j = 0; existing_connections[j]; j++) {
-				if (nm_streq0 (nm_connection_get_interface_name (existing_connections[j]),
-				               name))
-					goto next;
+		for (iter = existing, found = FALSE; iter; iter = g_slist_next (iter)) {
+			NMConnection *candidate = iter->data;
+
+			if (g_strcmp0 (nm_connection_get_interface_name (candidate), name) == 0) {
+				found = TRUE;
+				break;
 			}
 		}
 
-		return name;
+		if (!found)
+			return name;
 
-next:
+	next:
 		g_free (name);
 	}
+
+	return NULL;
 }
 
 const char *
@@ -245,7 +251,7 @@ void
 nm_utils_complete_generic (NMPlatform *platform,
                            NMConnection *connection,
                            const char *ctype,
-                           NMConnection *const*existing_connections,
+                           const GSList *existing,
                            const char *preferred_id,
                            const char *fallback_id_prefix,
                            const char *ifname_prefix,
@@ -272,14 +278,14 @@ nm_utils_complete_generic (NMPlatform *platform,
 
 	/* Add a connection ID if absent */
 	if (!nm_setting_connection_get_id (s_con)) {
-		id = get_new_connection_name (existing_connections, preferred_id, fallback_id_prefix);
+		id = get_new_connection_name (existing, preferred_id, fallback_id_prefix);
 		g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_ID, id, NULL);
 		g_free (id);
 	}
 
 	/* Add an interface name, if requested */
 	if (ifname_prefix && !nm_setting_connection_get_interface_name (s_con)) {
-		ifname = get_new_connection_ifname (platform, existing_connections, ifname_prefix);
+		ifname = get_new_connection_ifname (platform, existing, ifname_prefix);
 		g_object_set (G_OBJECT (s_con), NM_SETTING_CONNECTION_INTERFACE_NAME, ifname, NULL);
 		g_free (ifname);
 	}
@@ -874,37 +880,58 @@ nm_utils_match_connection (NMConnection *const*connections,
 
 /*****************************************************************************/
 
-int
-nm_match_spec_device_by_pllink (const NMPlatformLink *pllink,
-                                const char *match_device_type,
-                                const GSList *specs,
-                                int no_match_value)
+/**
+ * nm_utils_g_value_set_object_path:
+ * @value: a #GValue, initialized to store an object path
+ * @object: (allow-none): an #NMExportedObject
+ *
+ * Sets @value to @object's object path. If @object is %NULL, or not
+ * exported, @value is set to "/".
+ */
+void
+nm_utils_g_value_set_object_path (GValue *value, gpointer object)
+{
+	g_return_if_fail (!object || NM_IS_EXPORTED_OBJECT (object));
+
+	if (object && nm_exported_object_is_exported (object))
+		g_value_set_string (value, nm_exported_object_get_path (object));
+	else
+		g_value_set_string (value, "/");
+}
+
+/**
+ * nm_utils_g_value_set_object_path_array:
+ * @value: a #GValue, initialized to store an object path
+ * @objects: a #GSList of #NMExportedObjects
+ * @filter_func: (allow-none): function to call on each object in @objects
+ * @user_data: data to pass to @filter_func
+ *
+ * Sets @value to an array of object paths of the objects in @objects.
+ */
+void
+nm_utils_g_value_set_object_path_array (GValue *value,
+                                        GSList *objects,
+                                        NMUtilsObjectFunc filter_func,
+                                        gpointer user_data)
 {
-	NMMatchSpecMatchType m;
-
-	/* we can only match by certain properties that are available on the
-	 * platform link (and even @pllink might be missing.
-	 *
-	 * It's still useful because of specs like "*" and "except:interface-name:eth0",
-	 * which match even in that case. */
-	m = nm_match_spec_device (specs,
-	                          pllink ? pllink->name : NULL,
-	                          match_device_type,
-	                          pllink ? pllink->driver : NULL,
-	                          NULL,
-	                          NULL,
-	                          NULL);
-
-	switch (m) {
-	case NM_MATCH_SPEC_MATCH:
-		return TRUE;
-	case NM_MATCH_SPEC_NEG_MATCH:
-		return FALSE;
-	case NM_MATCH_SPEC_NO_MATCH:
-		return no_match_value;
+	char **paths;
+	guint i;
+	GSList *iter;
+
+	paths = g_new (char *, g_slist_length (objects) + 1);
+	for (i = 0, iter = objects; iter; iter = iter->next) {
+		NMExportedObject *object = iter->data;
+		const char *path;
+
+		path = nm_exported_object_get_path (object);
+		if (!path)
+			continue;
+		if (filter_func && !filter_func ((GObject *) object, user_data))
+			continue;
+		paths[i++] = g_strdup (path);
 	}
-	nm_assert_not_reached ();
-	return no_match_value;
+	paths[i] = NULL;
+	g_value_take_boxed (value, paths);
 }
 
-
+/*****************************************************************************/