diff options
| author | Jeremy Kerr <jk@ozlabs.org> | 2018-08-13 11:48:23 +0800 |
|---|---|---|
| committer | Jeremy Kerr <jk@ozlabs.org> | 2018-08-13 11:48:23 +0800 |
| commit | a87af8462346f7db6cac87ba13bac5a4b20132c3 (patch) | |
| tree | 6b68b1ab78278e6dbeec2365e1bfb3f2b9b1587b | |
| parent | 4ac9246f8391ac5af736046fa6001632f91c1173 (diff) | |
| download | jsnbd-a87af8462346f7db6cac87ba13bac5a4b20132c3.tar.gz jsnbd-a87af8462346f7db6cac87ba13bac5a4b20132c3.zip | |
nbd-proxy: replace hook dir with a single executable
A future change will run the executable asynchronously. With a directory
of hooks, this gets overly complicated.
Replace the directory-of-hooks concept with a single hook. The hook
itself can then spawn multiple hooks if required (eg, with run-parts).
Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
| -rw-r--r-- | README | 12 | ||||
| -rw-r--r-- | nbd-proxy.c | 96 |
2 files changed, 24 insertions, 84 deletions
@@ -54,12 +54,12 @@ There is no authentication or authorisation implemented in the nbd proxy. Your websocket proxy should implement proper authentication before nbd-proxy is connected to the websocket endpoint. -State hooks ------------ +State hook +---------- -The nbd-proxy has a facility to run hooks on state change. When a -nbd session is established or shut down, the proxy will run any executables -found under the hook path (by default, /etc/nbd-proxy/state.d/). +The nbd-proxy has a facility to run an program on state change. When a nbd +session is established or shut down, the proxy will run the executable at +/etc/nbd-proxy/state. -These hooks are called with two arguments: the action ("start" or "stop"), +This executable is called with two arguments: the action ("start" or "stop"), and the name of the configuration (as specified in the config.json file). diff --git a/nbd-proxy.c b/nbd-proxy.c index 6e932ad..2db70df 100644 --- a/nbd-proxy.c +++ b/nbd-proxy.c @@ -69,14 +69,12 @@ struct ctx { }; static const char *conf_path = SYSCONFDIR "/nbd-proxy/config.json"; -static const char *state_hook_path = SYSCONFDIR "/nbd-proxy/state.d"; +static const char *state_hook_path = SYSCONFDIR "/nbd-proxy/state"; static const char *sockpath_tmpl = RUNSTATEDIR "/nbd.%d.sock"; static const size_t bufsize = 0x20000; static const int nbd_timeout_default = 30; -#define BUILD_ASSERT_OR_ZERO(c) (sizeof(struct {int:-!(c);})) - static int open_nbd_socket(struct ctx *ctx) { struct sockaddr_un addr; @@ -352,40 +350,29 @@ static int wait_for_nbd_client(struct ctx *ctx) return 0; } -#define join_paths(p1, p2, r) \ - (BUILD_ASSERT_OR_ZERO(sizeof(r) > PATH_MAX) + __join_paths(p1, p2, r)) -static int __join_paths(const char *p1, const char *p2, char res[]) -{ - size_t len; - char *pos; - - len = strlen(p1) + 1 + strlen(p2); - if (len > PATH_MAX) - return -1; - - pos = res; - strcpy(pos, p1); - pos += strlen(p1); - *pos = '/'; - pos++; - strcpy(pos, p2); - - return 0; -} - -static int run_state_hook(struct ctx *ctx, - const char *path, const char *name, const char *action) +static int run_state_hook(struct ctx *ctx, const char *action) { int status, rc, fd; pid_t pid; + /* if the hook isn't present or executable, that's not necessarily + * an error condition */ + if (!access(state_hook_path, X_OK)) + return 0; + pid = fork(); if (pid < 0) { - warn("can't fork to execute hook %s", name); + warn("can't fork to execute hook %s", state_hook_path); return -1; } if (!pid) { + const char *argv0; + + argv0 = strchr(state_hook_path, '/'); + if (!argv0) + argv0 = state_hook_path; + fd = open("/dev/null", O_RDWR | O_CLOEXEC); if (fd < 0) exit(EXIT_FAILURE); @@ -393,7 +380,7 @@ static int run_state_hook(struct ctx *ctx, dup2(fd, STDIN_FILENO); dup2(fd, STDOUT_FILENO); dup2(fd, STDERR_FILENO); - execl(path, name, action, ctx->config->name, NULL); + execl(state_hook_path, argv0, action, ctx->config->name, NULL); exit(EXIT_FAILURE); } @@ -404,60 +391,13 @@ static int run_state_hook(struct ctx *ctx, } if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { - warnx("hook %s failed", name); + warnx("hook %s failed", state_hook_path); return -1; } return 0; } -static int run_state_hooks(struct ctx *ctx, const char *action) -{ - struct dirent *dirent; - DIR *dir; - int rc; - - dir = opendir(state_hook_path); - if (!dir) - return 0; - - rc = 0; - - for (dirent = readdir(dir); dirent; dirent = readdir(dir)) { - char full_path[PATH_MAX+1]; - struct stat statbuf; - - if (dirent->d_name[0] == '.') - continue; - - rc = fstatat(dirfd(dir), dirent->d_name, &statbuf, 0); - if (rc) { - rc = 0; - continue; - } - - if (!(S_ISREG(statbuf.st_mode) || S_ISLNK(statbuf.st_mode))) - continue; - - if (faccessat(dirfd(dir), dirent->d_name, X_OK, 0)) - continue; - - rc = join_paths(state_hook_path, dirent->d_name, full_path); - if (rc) { - rc = 0; - continue; - } - - rc = run_state_hook(ctx, full_path, dirent->d_name, action); - if (rc) - break; - } - - closedir(dir); - - return rc; -} - static int udev_init(struct ctx *ctx) { int rc; @@ -536,7 +476,7 @@ static int udev_process(struct ctx *ctx) ctx->monitor = NULL; ctx->udev = NULL; - rc = run_state_hooks(ctx, "start"); + rc = run_state_hook(ctx, "start"); return rc; } @@ -886,7 +826,7 @@ int main(int argc, char **argv) if (ctx->udev) udev_free(ctx); - run_state_hooks(ctx, "stop"); + run_state_hook(ctx, "stop"); out_stop_client: /* we cleanup signals before stopping the client, because we |

