From 35a428f16897e277db81293ae79e9b5ed061c044 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Tue, 20 Nov 2018 16:51:46 +0100 Subject: 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. --- dispatcher/nm-dispatcher.c | 103 ++++++++++++++++++--------- shared/nm-libnm-core-aux/nm-dispatcher-api.h | 5 -- 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" -- cgit v1.2.1