libnm: let nm_vpn_plugin_info_new_search_file() call full list-load

list-load does some special handling, for example, it will avoid adding
duplicates. As such, two plugin infos cannot have the same name or
same service type.

nm_vpn_plugin_info_new_search_file() did not implement this, it merely
loaded each directory after the other, sort the plugin infos, and
returned the first match.

That might mean, with unusual (duplicate) name files,
nm_vpn_plugin_info_new_search_file() might return a value
that would not otherwise be returned by
nm_vpn_plugin_info_list_load().

Let nm_vpn_plugin_info_new_search_file() call list-load, so that
the search result is always consistent.

The downside of this is that previously, if the searched plugin was
already found in /usr/lib, we would skip loading /etc. But
that is a minor optimization, in any case nm_vpn_plugin_info_new_search_file()
scales with the number of .name files on disk, which is expected to be small.
This commit is contained in:
Thomas Haller 2020-03-14 17:16:19 +01:00
parent 1a76141e66
commit 2b814f4e87

View file

@ -172,23 +172,6 @@ _sort_files (LoadDirInfo *a, LoadDirInfo *b)
nm_vpn_plugin_info_get_filename (b->plugin_info));
}
#define DEFINE_DEFAULT_DIR_LIST(dir) \
const char *dir[] = { \
/* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with
* preference to the former.
*
* load user directory with highest priority. */ \
_nm_vpn_plugin_info_get_default_dir_user (), \
\
/* lib directory has higher priority then etc. The reason is that
* etc is deprecated and used by old plugins. We expect newer plugins
* to install their file in lib, where they have higher priority.
*
* Optimally, there are no duplicates anyway, so it doesn't really matter. */ \
_nm_vpn_plugin_info_get_default_dir_lib (), \
_nm_vpn_plugin_info_get_default_dir_etc (), \
}
/**
* _nm_vpn_plugin_info_get_default_dir_etc:
*
@ -223,7 +206,7 @@ _nm_vpn_plugin_info_get_default_dir_lib ()
const char *
_nm_vpn_plugin_info_get_default_dir_user ()
{
return g_getenv ("NM_VPN_PLUGIN_DIR");
return nm_str_not_empty (g_getenv ("NM_VPN_PLUGIN_DIR"));
}
/**
@ -316,7 +299,21 @@ nm_vpn_plugin_info_list_load ()
gint64 uid;
GSList *list = NULL;
GSList *infos, *info;
DEFINE_DEFAULT_DIR_LIST (dir);
const char *const dir[] = {
/* We load plugins from NM_VPN_PLUGIN_DIR *and* DEFAULT_DIR*, with
* preference to the former.
*
* load user directory with highest priority. */
_nm_vpn_plugin_info_get_default_dir_user (),
/* lib directory has higher priority then etc. The reason is that
* etc is deprecated and used by old plugins. We expect newer plugins
* to install their file in lib, where they have higher priority.
*
* Optimally, there are no duplicates anyway, so it doesn't really matter. */
_nm_vpn_plugin_info_get_default_dir_lib (),
_nm_vpn_plugin_info_get_default_dir_etc (),
};
uid = getuid ();
@ -354,44 +351,32 @@ nm_vpn_plugin_info_list_load ()
NMVpnPluginInfo *
nm_vpn_plugin_info_new_search_file (const char *name, const char *service)
{
int i;
gint64 uid;
NMVpnPluginInfo *plugin_info = NULL;
GSList *infos, *info;
DEFINE_DEFAULT_DIR_LIST (dir);
GSList *infos;
GSList *info;
if (!name && !service)
g_return_val_if_reached (NULL);
uid = getuid ();
infos = nm_vpn_plugin_info_list_load ();
for (i = 0; !plugin_info && i < G_N_ELEMENTS (dir); i++) {
if ( !dir[i]
|| nm_utils_strv_find_first ((char **) dir, i, dir[i]) >= 0)
for (info = infos; info; info = info->next) {
NMVpnPluginInfo *p = info->data;
if ( name
&& !nm_streq (nm_vpn_plugin_info_get_name (p), name))
continue;
/* We still must load the entire directory while searching for the matching
* plugin-info. The reason is that reading the directory has no stable
* order and we can only sort them after reading the entire directory --
* which _nm_vpn_plugin_info_list_load_dir() does. */
infos = _nm_vpn_plugin_info_list_load_dir (dir[i], TRUE, uid, NULL, NULL);
for (info = infos; info; info = info->next) {
NMVpnPluginInfo *p = info->data;
if (name && !nm_streq (nm_vpn_plugin_info_get_name (p), name))
continue;
if ( service
&& !nm_streq (nm_vpn_plugin_info_get_service (p), service)
&& (nm_utils_strv_find_first (NM_VPN_PLUGIN_INFO_GET_PRIVATE (p)->aliases,
-1, service) < 0))
continue;
plugin_info = g_object_ref (p);
break;
}
g_slist_free_full (infos, g_object_unref);
if ( service
&& !nm_streq (nm_vpn_plugin_info_get_service (p), service)
&& (nm_utils_strv_find_first (NM_VPN_PLUGIN_INFO_GET_PRIVATE (p)->aliases,
-1, service) < 0))
continue;
plugin_info = g_object_ref (p);
break;
}
g_slist_free_full (infos, g_object_unref);
return plugin_info;
}