summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLubomir Rintel <lkundrak@v3.sk>2018-11-20 16:51:46 +0100
committerLubomir Rintel <lkundrak@v3.sk>2019-04-29 16:57:07 +0200
commit35a428f16897e277db81293ae79e9b5ed061c044 (patch)
treed76ebd8b4f57f6542141793b09e3ae52383653ec
parent3fc41cd6d5f68a6caa01ed8037d992ed289e5bec (diff)
downloadNetworkManager-35a428f16897e277db81293ae79e9b5ed061c044.tar.gz
dispatcher: look for the scripts in /usr/lib as well
This makes it possible for packages that ship dispatcher scripts to use the correct location.
-rw-r--r--dispatcher/nm-dispatcher.c103
-rw-r--r--shared/nm-libnm-core-aux/nm-dispatcher-api.h5
2 files changed, 71 insertions, 37 deletions
diff --git a/dispatcher/nm-dispatcher.c b/dispatcher/nm-dispatcher.c
index fe6eaa17ad..231a3f9a83 100644
--- a/dispatcher/nm-dispatcher.c
+++ b/dispatcher/nm-dispatcher.c
@@ -466,12 +466,6 @@ check_permissions (struct stat *s, const char **out_error_msg)
g_return_val_if_fail (out_error_msg != NULL, FALSE);
g_return_val_if_fail (*out_error_msg == NULL, FALSE);
- /* Only accept regular files */
- if (!S_ISREG (s->st_mode)) {
- *out_error_msg = "not a regular file.";
- return FALSE;
- }
-
/* Only accept files owned by root */
if (s->st_uid != 0) {
*out_error_msg = "not owned by root.";
@@ -573,59 +567,104 @@ dispatch_one_script (Request *request)
return FALSE;
}
-static GSList *
-find_scripts (const char *str_action)
+static int
+_compare_basenames (gconstpointer a, gconstpointer b)
+{
+ const char *basename_a = strrchr (a, '/');
+ const char *basename_b = strrchr (b, '/');
+ int ret;
+
+ nm_assert (basename_a);
+ nm_assert (basename_b);
+
+ ret = strcmp (++basename_a, ++basename_b);
+ if (ret)
+ return ret;
+
+ nm_assert_not_reached ();
+ return 0;
+}
+
+static void
+_find_scripts (GHashTable *scripts, const char *base, const char *subdir)
{
- GDir *dir;
const char *filename;
- GSList *sorted = NULL;
+ gs_free char *dirname = NULL;
GError *error = NULL;
- const char *dirname;
+ GDir *dir;
- if ( strcmp (str_action, NMD_ACTION_PRE_UP) == 0
- || strcmp (str_action, NMD_ACTION_VPN_PRE_UP) == 0)
- dirname = NMD_SCRIPT_DIR_PRE_UP;
- else if ( strcmp (str_action, NMD_ACTION_PRE_DOWN) == 0
- || strcmp (str_action, NMD_ACTION_VPN_PRE_DOWN) == 0)
- dirname = NMD_SCRIPT_DIR_PRE_DOWN;
- else
- dirname = NMD_SCRIPT_DIR_DEFAULT;
+ dirname = g_build_filename (base, "dispatcher.d", subdir, NULL);
if (!(dir = g_dir_open (dirname, 0, &error))) {
g_message ("find-scripts: Failed to open dispatcher directory '%s': %s",
dirname, error->message);
g_error_free (error);
- return NULL;
+ return;
}
while ((filename = g_dir_read_name (dir))) {
- char *path;
+ if (!check_filename (filename))
+ continue;
+
+ g_hash_table_insert (scripts,
+ g_strdup (filename),
+ g_build_filename (dirname, filename, NULL));
+ }
+
+ g_dir_close (dir);
+}
+
+static GSList *
+find_scripts (const char *str_action)
+{
+ gs_unref_hashtable GHashTable *scripts = NULL;
+ GSList *script_list = NULL;
+ GHashTableIter iter;
+ const char *subdir = NULL;
+ char *path;
+ char *filename;
+
+ if ( strcmp (str_action, NMD_ACTION_PRE_UP) == 0
+ || strcmp (str_action, NMD_ACTION_VPN_PRE_UP) == 0)
+ subdir = "pre-up.d";
+ else if ( strcmp (str_action, NMD_ACTION_PRE_DOWN) == 0
+ || strcmp (str_action, NMD_ACTION_VPN_PRE_DOWN) == 0)
+ subdir = "pre-down.d";
+
+ scripts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+
+ _find_scripts (scripts, NMLIBDIR, subdir);
+ _find_scripts (scripts, NMCONFDIR, subdir);
+
+ g_hash_table_iter_init (&iter, scripts);
+ while (g_hash_table_iter_next (&iter, (gpointer *) &filename, (gpointer *) &path)) {
struct stat st;
+ char *link_target;
int err;
const char *err_msg = NULL;
- if (!check_filename (filename))
+ link_target = g_file_read_link (path, NULL);
+ if (g_strcmp0 (link_target, "/dev/null") == 0) {
+ g_free (link_target);
continue;
-
- path = g_build_filename (dirname, filename, NULL);
+ }
+ g_free (link_target);
err = stat (path, &st);
if (err)
g_warning ("find-scripts: Failed to stat '%s': %d", path, err);
- else if (S_ISDIR (st.st_mode))
+ else if (!S_ISREG (st.st_mode))
; /* silently skip. */
else if (!check_permissions (&st, &err_msg))
g_warning ("find-scripts: Cannot execute '%s': %s", path, err_msg);
else {
/* success */
- sorted = g_slist_insert_sorted (sorted, path, (GCompareFunc) g_strcmp0);
- path = NULL;
+ script_list = g_slist_prepend (script_list, g_strdup (path));
+ continue;
}
- g_free (path);
}
- g_dir_close (dir);
- return sorted;
+ return g_slist_sort (script_list, _compare_basenames);
}
static gboolean
@@ -636,6 +675,7 @@ script_must_wait (const char *path)
gs_free char *real = NULL;
char *tmp;
+
link = g_file_read_link (path, NULL);
if (link) {
if (!g_path_is_absolute (link)) {
@@ -648,8 +688,7 @@ script_must_wait (const char *path)
dir = g_path_get_dirname (link);
real = realpath (dir, NULL);
-
- if (real && !strcmp (real, NMD_SCRIPT_DIR_NO_WAIT))
+ if (real && !g_str_has_suffix (real, "/no-wait.d"))
return FALSE;
}
diff --git a/shared/nm-libnm-core-aux/nm-dispatcher-api.h b/shared/nm-libnm-core-aux/nm-dispatcher-api.h
index e6d0d92f85..2da5bd88f1 100644
--- a/shared/nm-libnm-core-aux/nm-dispatcher-api.h
+++ b/shared/nm-libnm-core-aux/nm-dispatcher-api.h
@@ -21,11 +21,6 @@
#ifndef __NM_DISPACHER_API_H__
#define __NM_DISPACHER_API_H__
-#define NMD_SCRIPT_DIR_DEFAULT NMCONFDIR "/dispatcher.d"
-#define NMD_SCRIPT_DIR_PRE_UP NMD_SCRIPT_DIR_DEFAULT "/pre-up.d"
-#define NMD_SCRIPT_DIR_PRE_DOWN NMD_SCRIPT_DIR_DEFAULT "/pre-down.d"
-#define NMD_SCRIPT_DIR_NO_WAIT NMD_SCRIPT_DIR_DEFAULT "/no-wait.d"
-
#define NM_DISPATCHER_DBUS_SERVICE "org.freedesktop.nm_dispatcher"
#define NM_DISPATCHER_DBUS_INTERFACE "org.freedesktop.nm_dispatcher"
#define NM_DISPATCHER_DBUS_PATH "/org/freedesktop/nm_dispatcher"