summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2016-04-04 19:31:53 +0200
committerThomas Haller <thaller@redhat.com>2016-08-21 12:56:31 +0200
commit5e0df650e8d12111dacde0c3c56b6bfe1f24bcb3 (patch)
tree065814f6beb73e5e1c0507274bad8b5cd0f8a67f
parent8dcfda6dcdf6a7498a386a952da8b78071ccf71c (diff)
downloadNetworkManager-th/device-run-state.tar.gz
-rw-r--r--src/devices/nm-device.c119
-rw-r--r--src/devices/nm-device.h12
-rw-r--r--src/nm-manager.c21
3 files changed, 148 insertions, 4 deletions
diff --git a/src/devices/nm-device.c b/src/devices/nm-device.c
index 44e22ff9c0..c9745dad7c 100644
--- a/src/devices/nm-device.c
+++ b/src/devices/nm-device.c
@@ -663,6 +663,125 @@ _get_stable_id (NMConnection *connection, NMUtilsStableType *out_stable_type)
return stable_id;
}
+/*****************************************************************************/
+
+#define NM_DEV_RUN_STATE_KEYFILE_GROUP_DEV "dev"
+#define NM_DEV_RUN_STATE_KEYFILE_KEY_DEV_MANAGED "managed"
+#define NM_DEV_RUN_STATE_KEYFILE_KEY_DEV_UUID "uuid"
+
+static NMDevRunState *
+_dev_run_state_new (GKeyFile *kf)
+{
+ NMDevRunState *run_state;
+ gboolean managed = TRUE;
+ gs_free char *uuid = NULL;
+ gsize uuid_len_plus_1;
+ char *run_state_data;
+
+ run_state = g_slice_new (NMDevRunState);
+
+ if (kf) {
+ managed = nm_config_keyfile_get_boolean (kf,
+ NM_DEV_RUN_STATE_KEYFILE_GROUP_DEV,
+ NM_DEV_RUN_STATE_KEYFILE_KEY_DEV_MANAGED,
+ FALSE);
+ }
+ if (kf && managed) {
+ uuid = nm_config_keyfile_get_value (kf,
+ NM_DEV_RUN_STATE_KEYFILE_GROUP_DEV,
+ NM_DEV_RUN_STATE_KEYFILE_KEY_DEV_UUID,
+ NM_CONFIG_GET_VALUE_STRIP | NM_CONFIG_GET_VALUE_NO_EMPTY);
+ }
+
+ uuid_len_plus_1 = uuid ? strlen (uuid) + 1 : 0;
+
+ run_state = g_malloc (sizeof (NMDevRunState) + uuid_len_plus_1);
+
+ run_state->managed = managed;
+ if (uuid) {
+ run_state_data = (((char *) run_state) + sizeof (NMDevRunState));
+ memcpy (run_state_data, uuid, uuid_len_plus_1);
+ run_state->uuid = run_state_data;
+ } else
+ run_state->uuid = NULL;
+
+ return run_state;
+}
+
+/**
+ * nm_dev_run_state_load:
+ * @ifindex: the ifindex for which the state is to load
+ * @unlink_file: if TRUE, the state file will be deleted
+ * after reading.
+ *
+ * Returns: (transfer full): a run state object.
+ * Must be freed with g_free().
+ */
+NMDevRunState *
+nm_dev_run_state_load (int ifindex, gboolean unlink_file)
+{
+ char path[NM_STRLEN (NM_DEVICE_STATE_DIR) + 60];
+ gs_unref_keyfile GKeyFile *kf = NULL;
+ gs_free_error GError *error = NULL;
+
+ g_return_val_if_fail (ifindex > 0, NULL);
+
+ nm_sprintf_buf (path, "%s/%d", NM_DEVICE_STATE_DIR, ifindex);
+
+ kf = nm_config_create_keyfile ();
+ if (!g_key_file_load_from_file (kf, path, G_KEY_FILE_NONE, &error)) {
+ if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ unlink_file = FALSE;
+ g_clear_pointer (&kf, g_key_file_unref);
+ }
+
+ if (unlink_file)
+ (void) unlink (path);
+
+ return _dev_run_state_new (kf);
+}
+
+void
+nm_dev_run_state_purge_stale_files (GHashTable *seen_ifindexes)
+{
+ GDir *dir;
+ const char *fn;
+ int ifindex;
+ gsize fn_len;
+ char buf[NM_STRLEN (NM_DEVICE_STATE_DIR"/") + 30 + 3] = NM_DEVICE_STATE_DIR"/";
+ char *buf_p = &buf[NM_STRLEN (NM_DEVICE_STATE_DIR"/")];
+
+ g_return_if_fail (seen_ifindexes);
+
+ dir = g_dir_open (NM_DEVICE_STATE_DIR, 0, NULL);
+ if (!dir)
+ return;
+
+ while ((fn = g_dir_read_name (dir))) {
+
+ if ( !fn[0]
+ || g_ascii_isspace (fn[0]))
+ continue;
+
+ fn_len = strlen (fn);
+ if ( fn_len >= 30
+ || g_ascii_isspace (fn[fn_len - 1]))
+ continue;
+
+ ifindex = _nm_utils_ascii_str_to_int64 (fn, 10, 1, G_MAXINT, 0);
+ if (!ifindex)
+ continue;
+
+ if (g_hash_table_contains (seen_ifindexes, GINT_TO_POINTER (ifindex)))
+ continue;
+
+ memcpy (buf_p, fn, fn_len + 1);
+ (void) unlink (buf_p);
+ }
+
+ g_dir_close (dir);
+}
+
/***********************************************************/
const char *
diff --git a/src/devices/nm-device.h b/src/devices/nm-device.h
index e33a312605..3514b2c2ed 100644
--- a/src/devices/nm-device.h
+++ b/src/devices/nm-device.h
@@ -101,8 +101,20 @@
typedef enum NMActStageReturn NMActStageReturn;
+/*****************************************************************************/
+
#define NM_DEVICE_STATE_DIR ""NMRUNDIR"/devices"
+typedef struct {
+ bool managed:1;
+ const char *uuid;
+} NMDevRunState;
+
+NMDevRunState *nm_dev_run_state_load (int ifindex, gboolean unlink_file);
+void nm_dev_run_state_purge_stale_files (GHashTable *seen_ifindexes);
+
+/*****************************************************************************/
+
/* These flags affect whether a connection is considered available on a device
* (check_connection_available()). The flags should have the meaning of relaxing
* a condition, so that adding a flag might make a connection available that would
diff --git a/src/nm-manager.c b/src/nm-manager.c
index 237a45537d..06dbc86d7c 100644
--- a/src/nm-manager.c
+++ b/src/nm-manager.c
@@ -2089,7 +2089,8 @@ _register_device_factory (NMDeviceFactory *factory, gpointer user_data)
static void
platform_link_added (NMManager *self,
int ifindex,
- const NMPlatformLink *plink)
+ const NMPlatformLink *plink,
+ NMDevRunState *run_state)
{
NMDeviceFactory *factory;
NMDevice *device = NULL;
@@ -2200,7 +2201,7 @@ _platform_link_cb_idle (PlatformLinkCbData *data)
NMPlatformLink pllink;
pllink = *l; /* make a copy of the link instance */
- platform_link_added (self, data->ifindex, &pllink);
+ platform_link_added (self, data->ifindex, &pllink, NULL);
} else {
NMDevice *device;
GError *error = NULL;
@@ -2258,11 +2259,23 @@ platform_query_devices (NMManager *self)
GArray *links_array;
NMPlatformLink *links;
int i;
+ gs_unref_hashtable GHashTable *seen_ifindexes = NULL;
+
+ seen_ifindexes = g_hash_table_new (NULL, NULL);
links_array = nm_platform_link_get_all (NM_PLATFORM_GET);
links = (NMPlatformLink *) links_array->data;
- for (i = 0; i < links_array->len; i++)
- platform_link_added (self, links[i].ifindex, &links[i]);
+ for (i = 0; i < links_array->len; i++) {
+ gs_free NMDevRunState *run_state = NULL;
+
+ g_hash_table_add (seen_ifindexes, GINT_TO_POINTER (links[i].ifindex));
+
+ run_state = nm_dev_run_state_load (links[i].ifindex, FALSE);
+
+ platform_link_added (self, links[i].ifindex, &links[i], run_state);
+ }
+
+ nm_dev_run_state_purge_stale_files (seen_ifindexes);
g_array_unref (links_array);
}