]> git.ipfire.org Git - thirdparty/lxc.git/commitdiff
conf: execute hooks based on lxc.hooks.version
authorChristian Brauner <christian.brauner@ubuntu.com>
Sun, 10 Dec 2017 11:54:00 +0000 (12:54 +0100)
committerChristian Brauner <christian.brauner@ubuntu.com>
Thu, 14 Dec 2017 10:52:07 +0000 (11:52 +0100)
Unblocks #2013.
Unblocks #2015.
Closes #1766.

Signed-off-by: Christian Brauner <christian.brauner@ubuntu.com>
src/lxc/conf.c

index 0da760933e9aa908c15cfc2e654d3a193c3169e7..8e31275f6219fc53884f641765f788f34a986552 100644 (file)
@@ -308,84 +308,114 @@ static int run_buffer(char *buffer)
 
        f = lxc_popen(buffer);
        if (!f) {
-               SYSERROR("Failed to popen() %s.", buffer);
+               SYSERROR("Failed to popen() %s", buffer);
                return -1;
        }
 
        output = malloc(LXC_LOG_BUFFER_SIZE);
        if (!output) {
-               ERROR("Failed to allocate memory for %s.", buffer);
+               ERROR("Failed to allocate memory for %s", buffer);
                lxc_pclose(f);
                return -1;
        }
 
        while (fgets(output, LXC_LOG_BUFFER_SIZE, f->f))
-               DEBUG("Script %s with output: %s.", buffer, output);
+               DEBUG("Script %s with output: %s", buffer, output);
 
        free(output);
 
        ret = lxc_pclose(f);
        if (ret == -1) {
-               SYSERROR("Script exited with error.");
+               SYSERROR("Script exited with error");
                return -1;
        } else if (WIFEXITED(ret) && WEXITSTATUS(ret) != 0) {
-               ERROR("Script exited with status %d.", WEXITSTATUS(ret));
+               ERROR("Script exited with status %d", WEXITSTATUS(ret));
                return -1;
        } else if (WIFSIGNALED(ret)) {
-               ERROR("Script terminated by signal %d.", WTERMSIG(ret));
+               ERROR("Script terminated by signal %d", WTERMSIG(ret));
                return -1;
        }
 
        return 0;
 }
 
-static int run_script_argv(const char *name, const char *section,
-                          const char *script, const char *hook,
-                          const char *lxcpath, char **argsin)
+static int run_script_argv(const char *name, unsigned int hook_version,
+                          const char *section, const char *script,
+                          const char *hookname, const char *lxcpath,
+                          char **argsin)
 {
-       int ret, i;
+       int buf_pos, i, ret;
        char *buffer;
-       size_t size = 0;
+       size_t size = 0, size_legacy_args = 0;
 
-       INFO("Executing script \"%s\" for container \"%s\", config section \"%s\".",
-            script, name, section);
+       if (hook_version == 0)
+               INFO("Executing script \"%s\" for container \"%s\", config "
+                    "section \"%s\"", script, name, section);
+       else
+               INFO("Executing script \"%s\" for container \"%s\"", script, name);
 
        for (i = 0; argsin && argsin[i]; i++)
                size += strlen(argsin[i]) + 1;
 
-       size += strlen(hook) + 1;
-
-       size += strlen("exec");
+       size += sizeof("exec");
        size += strlen(script);
-       size += strlen(name);
-       size += strlen(section);
-       size += 4;
+       size++;
+
+       size_legacy_args += strlen(section);
+       size_legacy_args++;
+
+       size_legacy_args += strlen(name);
+       size_legacy_args++;
+
+       size_legacy_args += strlen(hookname);
+       size_legacy_args++;
 
        if (size > INT_MAX)
-               return -1;
+               return -EFBIG;
 
        buffer = alloca(size);
-       if (!buffer) {
-               ERROR("Failed to allocate memory.");
-               return -1;
-       }
 
-       ret =
-           snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hook);
-       if (ret < 0 || (size_t)ret >= size) {
-               ERROR("Script name too long.");
-               return -1;
+       if (hook_version == 0) {
+               size += size_legacy_args;
+
+               buf_pos = snprintf(buffer, size, "exec %s %s %s %s", script, name, section, hookname);
+               if (buf_pos < 0 || (size_t)buf_pos >= size) {
+                       ERROR("Failed to create command line for script \"%s\"", script);
+                       return -1;
+               }
+       } else {
+               buf_pos = snprintf(buffer, size, "exec %s", script);
+               if (buf_pos < 0 || (size_t)buf_pos >= size) {
+                       ERROR("Failed to create command line for script \"%s\"", script);
+                       return -1;
+               }
+
+               ret = setenv("LXC_HOOK_TYPE", hookname, 1);
+               if (ret < 0) {
+                       SYSERROR("Failed to set environment variable: "
+                                "LXC_HOOK_TYPE=%s", hookname);
+                       return -1;
+               }
+               TRACE("Set environment variable: LXC_HOOK_TYPE=%s", section);
+
+               ret = setenv("LXC_HOOK_SECTION", section, 1);
+               if (ret < 0) {
+                       SYSERROR("Failed to set environment variable: "
+                                "LXC_HOOK_SECTION=%s", section);
+                       return -1;
+               }
+               TRACE("Set environment variable: LXC_HOOK_SECTION=%s", section);
        }
 
        for (i = 0; argsin && argsin[i]; i++) {
-               int len = size - ret;
-               int rc;
-               rc = snprintf(buffer + ret, len, " %s", argsin[i]);
-               if (rc < 0 || rc >= len) {
-                       ERROR("Script args too long.");
+               size_t len = size - buf_pos;
+
+               ret = snprintf(buffer + buf_pos, len, " %s", argsin[i]);
+               if (ret < 0 || (size_t)ret >= len) {
+                       ERROR("Failed to create command line for script \"%s\"", script);
                        return -1;
                }
-               ret += rc;
+               buf_pos += ret;
        }
 
        return run_buffer(buffer);
@@ -3261,41 +3291,45 @@ int lxc_setup(struct lxc_handler *handler)
        return 0;
 }
 
-int run_lxc_hooks(const char *name, char *hook, struct lxc_conf *conf,
+int run_lxc_hooks(const char *name, char *hookname, struct lxc_conf *conf,
                  const char *lxcpath, char *argv[])
 {
-       int which = -1;
        struct lxc_list *it;
+       int which = -1;
 
-       if (strcmp(hook, "pre-start") == 0)
+       if (strcmp(hookname, "pre-start") == 0)
                which = LXCHOOK_PRESTART;
-       else if (strcmp(hook, "start-host") == 0)
+       else if (strcmp(hookname, "start-host") == 0)
                which = LXCHOOK_START_HOST;
-       else if (strcmp(hook, "pre-mount") == 0)
+       else if (strcmp(hookname, "pre-mount") == 0)
                which = LXCHOOK_PREMOUNT;
-       else if (strcmp(hook, "mount") == 0)
+       else if (strcmp(hookname, "mount") == 0)
                which = LXCHOOK_MOUNT;
-       else if (strcmp(hook, "autodev") == 0)
+       else if (strcmp(hookname, "autodev") == 0)
                which = LXCHOOK_AUTODEV;
-       else if (strcmp(hook, "start") == 0)
+       else if (strcmp(hookname, "start") == 0)
                which = LXCHOOK_START;
-       else if (strcmp(hook, "stop") == 0)
+       else if (strcmp(hookname, "stop") == 0)
                which = LXCHOOK_STOP;
-       else if (strcmp(hook, "post-stop") == 0)
+       else if (strcmp(hookname, "post-stop") == 0)
                which = LXCHOOK_POSTSTOP;
-       else if (strcmp(hook, "clone") == 0)
+       else if (strcmp(hookname, "clone") == 0)
                which = LXCHOOK_CLONE;
-       else if (strcmp(hook, "destroy") == 0)
+       else if (strcmp(hookname, "destroy") == 0)
                which = LXCHOOK_DESTROY;
        else
                return -1;
+
        lxc_list_for_each(it, &conf->hooks[which]) {
                int ret;
-               char *hookname = it->elem;
-               ret = run_script_argv(name, "lxc", hookname, hook, lxcpath, argv);
-               if (ret)
-                       return ret;
+               char *hook = it->elem;
+
+               ret = run_script_argv(name, conf->hooks_version, "lxc", hook,
+                                     hookname, lxcpath, argv);
+               if (ret < 0)
+                       return -1;
        }
+
        return 0;
 }