ctdb-common: Improve error handling in run_event
[kai/samba-autobuild/.git] / ctdb / common / run_event.c
index e230b12f151ab0b16a3b0792d9ffa1aab23e4b6a..9ff18707715199ae28f143e4f21e2029fde546fd 100644 (file)
@@ -20,7 +20,7 @@
 #include "replace.h"
 #include "system/filesys.h"
 #include "system/dir.h"
-#include "system/locale.h"
+#include "system/glob.h"
 #include "system/wait.h"
 
 #include <talloc.h>
 
 static int script_filter(const struct dirent *de)
 {
-       size_t namelen = strlen(de->d_name);
-       char *ptr;
-
-       /* Ignore . and .. */
-       if (namelen < 3) {
-               return 0;
-       }
-
-       /* Skip filenames with ~ */
-       ptr = strchr(de->d_name, '~');
-       if (ptr != NULL) {
-               return 0;
-       }
-
-       /* Filename should start with [0-9][0-9]. */
-       if ((! isdigit(de->d_name[0])) ||
-           (! isdigit(de->d_name[1])) ||
-           (de->d_name[2] != '.')) {
-               return 0;
-       }
+       int ret;
 
-       /* Ignore filenames with multiple '.'s */
-       ptr = index(&de->d_name[3], '.');
-       if (ptr != NULL) {
-               return 0;
+       /* Match a script pattern */
+       ret = fnmatch("[0-9][0-9].*.script", de->d_name, 0);
+       if (ret == 0) {
+               return 1;
        }
 
-       return 1;
+       return 0;
 }
 
 static int get_script_list(TALLOC_CTX *mem_ctx,
@@ -75,6 +56,7 @@ static int get_script_list(TALLOC_CTX *mem_ctx,
 {
        struct dirent **namelist = NULL;
        struct run_event_script_list *script_list;
+       size_t ls;
        int count, ret;
        int i;
 
@@ -88,7 +70,6 @@ static int get_script_list(TALLOC_CTX *mem_ctx,
                                  script_dir, ret);
                }
                *out = NULL;
-               ret = 0;
                goto done;
        }
 
@@ -113,10 +94,13 @@ static int get_script_list(TALLOC_CTX *mem_ctx,
                goto done;
        }
 
+       ls = strlen(".script");
        for (i=0; i<count; i++) {
                struct run_event_script *s = &script_list->script[i];
 
-               s->name = talloc_strdup(script_list, namelist[i]->d_name);
+               s->name = talloc_strndup(script_list,
+                                        namelist[i]->d_name,
+                                        strlen(namelist[i]->d_name) - ls);
                if (s->name == NULL) {
                        ret = ENOMEM;
                        talloc_free(script_list);
@@ -142,12 +126,21 @@ static int script_chmod(TALLOC_CTX *mem_ctx, const char *script_dir,
 {
        DIR *dirp;
        struct dirent *de;
+       char script_file[PATH_MAX];
        int ret, new_mode;
        char *filename;
        struct stat st;
        bool found;
        int fd = -1;
 
+       ret = snprintf(script_file,
+                      sizeof(script_file),
+                      "%s.script",
+                      script_name);
+       if (ret >= sizeof(script_file)) {
+               return ENAMETOOLONG;
+       }
+
        dirp = opendir(script_dir);
        if (dirp == NULL) {
                return errno;
@@ -155,7 +148,7 @@ static int script_chmod(TALLOC_CTX *mem_ctx, const char *script_dir,
 
        found = false;
        while ((de = readdir(dirp)) != NULL) {
-               if (strcmp(de->d_name, script_name) == 0) {
+               if (strcmp(de->d_name, script_file) == 0) {
 
                        /* check for valid script names */
                        ret = script_filter(de);
@@ -174,7 +167,7 @@ static int script_chmod(TALLOC_CTX *mem_ctx, const char *script_dir,
                return ENOENT;
        }
 
-       filename = talloc_asprintf(mem_ctx, "%s/%s", script_dir, script_name);
+       filename = talloc_asprintf(mem_ctx, "%s/%s", script_dir, script_file);
        if (filename == NULL) {
                return ENOMEM;
        }
@@ -278,7 +271,7 @@ struct run_event_context {
 };
 
 
-int run_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+int run_event_init(TALLOC_CTX *mem_ctx, struct run_proc_context *run_proc_ctx,
                   const char *script_dir, const char *debug_prog,
                   struct run_event_context **out)
 {
@@ -291,11 +284,7 @@ int run_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
                return ENOMEM;
        }
 
-       ret = run_proc_init(run_ctx, ev, &run_ctx->run_proc_ctx);
-       if (ret != 0) {
-               talloc_free(run_ctx);
-               return ret;
-       }
+       run_ctx->run_proc_ctx = run_proc_ctx;
 
        ret = stat(script_dir, &st);
        if (ret != 0) {
@@ -306,7 +295,7 @@ int run_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
 
        if (! S_ISDIR(st.st_mode)) {
                talloc_free(run_ctx);
-               return EINVAL;
+               return ENOTDIR;
        }
 
        run_ctx->script_dir = talloc_strdup(run_ctx, script_dir);
@@ -399,9 +388,9 @@ static int run_event_script_status(struct run_event_script *script)
        return ret;
 }
 
-int run_event_script_list(struct run_event_context *run_ctx,
-                         TALLOC_CTX *mem_ctx,
-                         struct run_event_script_list **output)
+int run_event_list(struct run_event_context *run_ctx,
+                  TALLOC_CTX *mem_ctx,
+                  struct run_event_script_list **output)
 {
        struct run_event_script_list *script_list;
        int ret, i;
@@ -422,7 +411,7 @@ int run_event_script_list(struct run_event_context *run_ctx,
                struct stat st;
                char *path = NULL;
 
-               path = talloc_asprintf(mem_ctx, "%s/%s",
+               path = talloc_asprintf(mem_ctx, "%s/%s.script",
                                       run_event_script_dir(run_ctx),
                                       script->name);
                if (path == NULL) {
@@ -669,6 +658,11 @@ struct tevent_req *run_event_send(TALLOC_CTX *mem_ctx,
        state->timeout = timeout;
        state->cancelled = false;
 
+       state->script_list = talloc_zero(state, struct run_event_script_list);
+       if (tevent_req_nomem(state->script_list, req)) {
+               return tevent_req_post(req, ev);
+       }
+
        /*
         * If monitor event is running,
         *   cancel the running monitor event and run new event
@@ -683,11 +677,6 @@ struct tevent_req *run_event_send(TALLOC_CTX *mem_ctx,
                if (monitor_running) {
                        run_event_cancel(current_req);
                } else if (strcmp(event_str, "monitor") == 0) {
-                       state->script_list = talloc_zero(
-                               state, struct run_event_script_list);
-                       if (tevent_req_nomem(state->script_list, req)) {
-                               return tevent_req_post(req, ev);
-                       }
                        state->script_list->summary = -ECANCELED;
                        tevent_req_done(req);
                        return tevent_req_post(req, ev);
@@ -724,14 +713,16 @@ static void run_event_trigger(struct tevent_req *req, void *private_data)
        struct tevent_req *subreq;
        struct run_event_state *state = tevent_req_data(
                req, struct run_event_state);
+       struct run_event_script_list *script_list;
        int ret;
        bool is_monitor = false;
 
        D_DEBUG("Running event %s with args \"%s\"\n", state->event_str,
                state->arg_str == NULL ? "(null)" : state->arg_str);
 
-       ret = get_script_list(state, run_event_script_dir(state->run_ctx),
-                             &state->script_list);
+       ret = get_script_list(state,
+                             run_event_script_dir(state->run_ctx),
+                             &script_list);
        if (ret != 0) {
                D_ERR("get_script_list() failed, ret=%d\n", ret);
                tevent_req_error(req, ret);
@@ -739,12 +730,14 @@ static void run_event_trigger(struct tevent_req *req, void *private_data)
        }
 
        /* No scripts */
-       if (state->script_list == NULL ||
-           state->script_list->num_scripts == 0) {
+       if (script_list == NULL || script_list->num_scripts == 0) {
                tevent_req_done(req);
                return;
        }
 
+       talloc_free(state->script_list);
+       state->script_list = script_list;
+
        ret = script_args(state, state->event_str, state->arg_str,
                          &state->argv);
        if (ret != 0) {
@@ -779,7 +772,7 @@ static struct tevent_req *run_event_run_script(struct tevent_req *req)
 
        script = &state->script_list->script[state->index];
 
-       path = talloc_asprintf(state, "%s/%s",
+       path = talloc_asprintf(state, "%s/%s.script",
                               run_event_script_dir(state->run_ctx),
                               script->name);
        if (path == NULL) {