[SCM] Samba Shared Repository - branch master updated

Martin Schwenke martins at samba.org
Tue May 30 06:06:02 UTC 2017


The branch, master has been updated
       via  8d818e1 ctdb-tools: Always exit with positive return value
       via  a64a83f ctdb-eventd: Avoid passing NULL pointer to printf( %s )
       via  b0293ce ctdb-eventd: Use run_event abstraction
       via  98ee7e7 ctdb-common: Add run_event abstraction
       via  16c188c ctdb-common: Update run_proc api to re-assign stdin
      from  15367ce s4/torture: add a leases test with stat open

https://git.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 8d818e18c2ba0385b96e0fd9385dc77b23cf43b1
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Tue Mar 7 16:44:08 2017 +1100

    ctdb-tools: Always exit with positive return value
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>
    
    Autobuild-User(master): Martin Schwenke <martins at samba.org>
    Autobuild-Date(master): Tue May 30 08:05:56 CEST 2017 on sn-devel-144

commit a64a83f08a09fbafa0c86171a0f639cc7d4c03f5
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Mon May 29 12:36:11 2017 +1000

    ctdb-eventd: Avoid passing NULL pointer to printf( %s )
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit b0293ce826e307e3af9750f174355c08815edf6e
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Mon Feb 27 15:00:42 2017 +1100

    ctdb-eventd: Use run_event abstraction
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 98ee7e799171c270460d966a4d4700072eb41ed0
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Thu Feb 23 18:40:48 2017 +1100

    ctdb-common: Add run_event abstraction
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

commit 16c188c7f8e335e5c8c191148be2f8347020178a
Author: Amitay Isaacs <amitay at gmail.com>
Date:   Sat May 6 02:47:00 2017 +1000

    ctdb-common: Update run_proc api to re-assign stdin
    
    This allows to pass data to a child process via stdin.
    
    Signed-off-by: Amitay Isaacs <amitay at gmail.com>
    Reviewed-by: Martin Schwenke <martin at meltin.net>

-----------------------------------------------------------------------

Summary of changes:
 ctdb/common/run_event.c           | 796 ++++++++++++++++++++++++++++++++++++
 ctdb/common/run_event.h           | 148 +++++++
 ctdb/common/run_proc.c            |  13 +-
 ctdb/common/run_proc.h            |   3 +-
 ctdb/server/ctdb_eventd.c         | 835 ++++++--------------------------------
 ctdb/tests/cunit/run_event_001.sh | 134 ++++++
 ctdb/tests/cunit/run_proc_001.sh  |  38 +-
 ctdb/tests/src/run_event_test.c   | 205 ++++++++++
 ctdb/tests/src/run_proc_test.c    |  14 +-
 ctdb/tools/ctdb_event.c           |   3 +-
 ctdb/wscript                      |   5 +-
 11 files changed, 1468 insertions(+), 726 deletions(-)
 create mode 100644 ctdb/common/run_event.c
 create mode 100644 ctdb/common/run_event.h
 create mode 100755 ctdb/tests/cunit/run_event_001.sh
 create mode 100644 ctdb/tests/src/run_event_test.c


Changeset truncated at 500 lines:

diff --git a/ctdb/common/run_event.c b/ctdb/common/run_event.c
new file mode 100644
index 0000000..e5d562c
--- /dev/null
+++ b/ctdb/common/run_event.c
@@ -0,0 +1,796 @@
+/*
+   Run scripts in a directory with specific event arguments
+
+   Copyright (C) Amitay Isaacs  2017
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program; if not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "replace.h"
+#include "system/filesys.h"
+#include "system/dir.h"
+#include "system/locale.h"
+#include "system/wait.h"
+
+#include <talloc.h>
+#include <tevent.h>
+
+#include "lib/util/tevent_unix.h"
+#include "lib/util/debug.h"
+
+#include "common/logging.h"
+#include "common/run_proc.h"
+#include "common/run_event.h"
+
+/*
+ * Utility functions
+ */
+
+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;
+	}
+
+	return 1;
+}
+
+static int get_script_list(TALLOC_CTX *mem_ctx,
+			   const char *script_dir,
+			   struct run_event_script_list **out)
+{
+	struct dirent **namelist = NULL;
+	struct run_event_script_list *script_list;
+	int count, ret;
+	int i;
+
+	count = scandir(script_dir, &namelist, script_filter, alphasort);
+	if (count == -1) {
+		ret = errno;
+		if (ret == ENOENT) {
+			D_WARNING("event script dir %s removed\n", script_dir);
+		} else {
+			D_WARNING("scandir() failed on %s, ret=%d\n",
+				  script_dir, ret);
+		}
+		*out = NULL;
+		ret = 0;
+		goto done;
+	}
+
+	if (count == 0) {
+		*out = NULL;
+		ret = 0;
+		goto done;
+	}
+
+	script_list = talloc_zero(mem_ctx, struct run_event_script_list);
+	if (script_list == NULL) {
+		return ENOMEM;
+	}
+
+	script_list->num_scripts = count;
+	script_list->script = talloc_zero_array(script_list,
+						struct run_event_script,
+						count);
+	if (script_list->script == NULL) {
+		ret = ENOMEM;
+		talloc_free(script_list);
+		goto done;
+	}
+
+	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);
+		if (s->name == NULL) {
+			ret = ENOMEM;
+			talloc_free(script_list);
+			goto done;
+		}
+	}
+
+	*out = script_list;
+	ret = 0;
+
+done:
+	if (namelist != NULL && count != -1) {
+		for (i=0; i<count; i++) {
+			free(namelist[i]);
+		}
+		free(namelist);
+	}
+	return ret;
+}
+
+static int script_chmod(TALLOC_CTX *mem_ctx, const char *script_dir,
+			const char *script_name, bool enable)
+{
+	DIR *dirp;
+	struct dirent *de;
+	int ret, new_mode;
+	char *filename;
+	struct stat st;
+	bool found;
+	int fd = -1;
+
+	dirp = opendir(script_dir);
+	if (dirp == NULL) {
+		return errno;
+	}
+
+	found = false;
+	while ((de = readdir(dirp)) != NULL) {
+		if (strcmp(de->d_name, script_name) == 0) {
+
+			/* check for valid script names */
+			ret = script_filter(de);
+			if (ret == 0) {
+				closedir(dirp);
+				return EINVAL;
+			}
+
+			found = true;
+			break;
+		}
+	}
+	closedir(dirp);
+
+	if (! found) {
+		return ENOENT;
+	}
+
+	filename = talloc_asprintf(mem_ctx, "%s/%s", script_dir, script_name);
+	if (filename == NULL) {
+		return ENOMEM;
+	}
+
+	fd = open(filename, O_RDWR);
+	if (fd == -1) {
+		ret = errno;
+		goto done;
+	}
+
+	ret = fstat(fd, &st);
+	if (ret != 0) {
+		ret = errno;
+		goto done;
+	}
+
+	if (enable) {
+		new_mode = st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH);
+	} else {
+		new_mode = st.st_mode & ~(S_IXUSR | S_IXGRP | S_IXOTH);
+	}
+
+	ret = fchmod(fd, new_mode);
+	if (ret != 0) {
+		ret = errno;
+		goto done;
+	}
+
+done:
+	if (fd != -1) {
+		close(fd);
+	}
+	talloc_free(filename);
+	return ret;
+}
+
+static int script_args(TALLOC_CTX *mem_ctx, const char *event_str,
+		       const char *arg_str, const char ***out)
+{
+	const char **argv;
+	int argc;
+	size_t len;
+
+	/* Preallocate argv array to avoid reallocation. */
+	len = 8;
+	argv = talloc_array(mem_ctx, const char *, len);
+	if (argv == NULL) {
+		return ENOMEM;
+	}
+
+	argv[0] = NULL; /* script name */
+	argv[1] = event_str;
+	argc = 2;
+
+	if (arg_str != NULL) {
+		char *str, *t, *tok;
+
+		str = talloc_strdup(argv, arg_str);
+		if (str == NULL) {
+			return ENOMEM;
+		}
+
+		t = str;
+		while ((tok = strtok(t, " ")) != NULL) {
+			argv[argc] = talloc_strdup(argv, tok);
+			if (argv[argc] == NULL) {
+				talloc_free(argv);
+				return ENOMEM;
+			}
+			argc += 1;
+			if (argc >= len) {
+				argv = talloc_realloc(mem_ctx, argv,
+						      const char *, len + 8);
+				if (argv == NULL) {
+					return ENOMEM;
+				}
+				len += 8;
+			}
+			t = NULL;
+		}
+
+		talloc_free(str);
+	}
+
+	argv[argc] = NULL;
+	argc += 1;
+
+	*out = argv;
+	return 0;
+}
+
+struct run_event_context {
+	struct run_proc_context *run_proc_ctx;
+	const char *script_dir;
+	const char *debug_prog;
+	bool debug_running;
+};
+
+
+int run_event_init(TALLOC_CTX *mem_ctx, struct tevent_context *ev,
+		   const char *script_dir, const char *debug_prog,
+		   struct run_event_context **out)
+{
+	struct run_event_context *run_ctx;
+	struct stat st;
+	int ret;
+
+	run_ctx = talloc_zero(mem_ctx, struct run_event_context);
+	if (run_ctx == NULL) {
+		return ENOMEM;
+	}
+
+	ret = run_proc_init(run_ctx, ev, &run_ctx->run_proc_ctx);
+	if (ret != 0) {
+		talloc_free(run_ctx);
+		return ret;
+	}
+
+	ret = stat(script_dir, &st);
+	if (ret != 0) {
+		ret = errno;
+		talloc_free(run_ctx);
+		return ret;
+	}
+
+	if (! S_ISDIR(st.st_mode)) {
+		talloc_free(run_ctx);
+		return EINVAL;
+	}
+
+	run_ctx->script_dir = talloc_strdup(run_ctx, script_dir);
+	if (run_ctx->script_dir == NULL) {
+		talloc_free(run_ctx);
+		return ENOMEM;
+	}
+
+	if (debug_prog != NULL) {
+		run_ctx->debug_prog = talloc_strdup(run_ctx, debug_prog);
+		if (run_ctx->debug_prog == NULL) {
+			talloc_free(run_ctx);
+			return ENOMEM;
+		}
+	}
+
+	run_ctx->debug_running = false;
+
+	*out = run_ctx;
+	return 0;
+}
+
+static struct run_proc_context *
+run_event_run_proc_context(struct run_event_context *run_ctx)
+{
+	return run_ctx->run_proc_ctx;
+}
+
+static const char *run_event_script_dir(struct run_event_context *run_ctx)
+{
+	return run_ctx->script_dir;
+}
+
+static const char *run_event_debug_prog(struct run_event_context *run_ctx)
+{
+	return run_ctx->debug_prog;
+}
+
+static int run_event_script_status(struct run_event_script *script)
+{
+	int ret;
+
+	if (script->result.sig > 0) {
+		ret = -EINTR;
+	} else if (script->result.err > 0) {
+		if (script->result.err == EACCES) {
+			/* Map EACCESS to ENOEXEC */
+			ret = -ENOEXEC;
+		} else {
+			ret = -script->result.err;
+		}
+	} else {
+		ret = script->result.status;
+	}
+
+	return ret;
+}
+
+int run_event_script_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;
+
+	ret = get_script_list(mem_ctx, run_event_script_dir(run_ctx),
+			      &script_list);
+	if (ret != 0) {
+		return ret;
+	}
+
+	if (script_list == NULL) {
+		*output = NULL;
+		return 0;
+	}
+
+	for (i=0; i<script_list->num_scripts; i++) {
+		struct run_event_script *script = &script_list->script[i];
+		struct stat st;
+		char *path = NULL;
+
+		path = talloc_asprintf(mem_ctx, "%s/%s",
+				       run_event_script_dir(run_ctx),
+				       script->name);
+		if (path == NULL) {
+			continue;
+		}
+
+		ret = stat(path, &st);
+		if (ret != 0) {
+			TALLOC_FREE(path);
+			continue;
+		}
+
+		if (! (st.st_mode & S_IXUSR)) {
+			script->summary = -ENOEXEC;
+		}
+
+		TALLOC_FREE(path);
+	}
+
+	*output = script_list;
+	return 0;
+}
+
+int run_event_script_enable(struct run_event_context *run_ctx,
+			    const char *script_name)
+{
+	return script_chmod(run_ctx, run_event_script_dir(run_ctx),
+			    script_name, true);
+}
+
+int run_event_script_disable(struct run_event_context *run_ctx,
+			     const char *script_name)
+{
+	return script_chmod(run_ctx, run_event_script_dir(run_ctx),
+			    script_name, false);
+}
+
+/*
+ * Run debug program to diagnose hung scripts
+ */
+
+static int debug_args(TALLOC_CTX *mem_ctx, const char *path,
+		      const char *event_str, pid_t pid, const char ***out)
+{
+	const char **argv;
+
+	argv = talloc_array(mem_ctx, const char *, 4);
+	if (argv == NULL) {
+		return ENOMEM;
+	}
+
+	argv[0] = path;
+	argv[1] = talloc_asprintf(argv, "%d", pid);
+	argv[2] = event_str;
+	if (argv[1] == NULL) {
+		talloc_free(argv);
+		return ENOMEM;
+	}
+	argv[3] = NULL;
+
+	*out = argv;
+	return 0;
+}
+
+static void debug_log(int loglevel, const char *output, const char *log_prefix)
+{
+	char *line, *s;
+
+	s = strdup(output);
+	if (s == NULL) {
+		DEBUG(loglevel, ("%s: %s\n", log_prefix, output));
+		return;
+	}
+
+	line = strtok(s, "\n");
+	while (line != NULL) {
+		DEBUG(loglevel, ("%s: %s\n", log_prefix, line));
+		line = strtok(NULL, "\n");
+	}
+	free(s);
+}
+
+struct run_debug_state {
+	struct run_event_context *run_ctx;
+	pid_t pid;
+};
+
+static void run_debug_done(struct tevent_req *subreq);
+
+static struct tevent_req *run_debug_send(TALLOC_CTX *mem_ctx,
+					 struct tevent_context *ev,
+					 struct run_event_context *run_ctx,
+					 const char *event_str, pid_t pid)
+{
+	struct tevent_req *req, *subreq;
+	struct run_debug_state *state;
+	const char **argv;
+	const char *debug_prog;
+	int ret;
+
+	req = tevent_req_create(mem_ctx, &state, struct run_debug_state);
+	if (req == NULL) {
+		return NULL;
+	}
+
+	state->run_ctx = run_ctx;
+	state->pid = pid;
+
+	debug_prog = run_event_debug_prog(run_ctx);
+	if (debug_prog == NULL) {
+		tevent_req_done(req);
+		return tevent_req_post(req, ev);
+	}


-- 
Samba Shared Repository



More information about the samba-cvs mailing list