Note that we allow both a tagged version or a git build that has sufficient patches for the features we require.
v2: close criu's stderr too Signed-off-by: Tycho Andersen <tycho.ander...@canonical.com> Acked-by: Serge E. Hallyn <serge.hal...@ubuntu.com> --- src/lxc/criu.c | 90 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/src/lxc/criu.c b/src/lxc/criu.c index 043db36..ca8344f 100644 --- a/src/lxc/criu.c +++ b/src/lxc/criu.c @@ -193,6 +193,93 @@ err: free(argv); } +/* + * Check to see if the criu version is recent enough for all the features we + * use. This version allows either CRIU_VERSION or (CRIU_GITID_VERSION and + * CRIU_GITID_PATCHLEVEL) to work, enabling users building from git to c/r + * things potentially before a version is released with a particular feature. + * + * The intent is that when criu development slows down, we can drop this, but + * for now we shouldn't attempt to c/r with versions that we know won't work. + */ +static bool criu_version_ok() +{ + int pipes[2]; + pid_t pid; + + if (pipe(pipes) < 0) { + SYSERROR("pipe() failed"); + return false; + } + + pid = fork(); + if (pid < 0) { + SYSERROR("fork() failed"); + return false; + } + + if (pid == 0) { + char *args[] = { "criu", "--version", NULL }; + close(pipes[0]); + + close(STDERR_FILENO); + if (dup2(pipes[1], STDOUT_FILENO) < 0) + exit(1); + + execv("/usr/local/sbin/criu", args); + exit(1); + } else { + FILE *f; + char version[1024]; + int patch; + + close(pipes[1]); + if (wait_for_pid(pid) < 0) { + close(pipes[0]); + return false; + } + + f = fdopen(pipes[0], "r"); + if (!f) { + close(pipes[0]); + return false; + } + + if (fscanf(f, "Version: %1024[^\n]s", version) != 1) + goto version_error; + + if (fgetc(f) != '\n') + goto version_error; + + if (strcmp(version, CRIU_VERSION) >= 0) + goto version_match; + + if (fscanf(f, "GitID: v%1024[^-]s", version) != 1) + goto version_error; + + if (fgetc(f) != '-') + goto version_error; + + if (fscanf(f, "%d", &patch) != 1) + goto version_error; + + if (strcmp(version, CRIU_GITID_VERSION) < 0) + goto version_error; + + if (patch < CRIU_GITID_PATCHLEVEL) + goto version_error; + +version_match: + close(pipes[0]); + return true; + +version_error: + close(pipes[0]); + ERROR("must have criu " CRIU_VERSION " or greater to checkpoint/restore\n"); + return false; + } +} + /* Check and make sure the container has a configuration that we know CRIU can * dump. */ bool criu_ok(struct lxc_container *c) @@ -200,6 +287,9 @@ bool criu_ok(struct lxc_container *c) struct lxc_list *it; bool found_deny_rule = false; + if (!criu_version_ok()) + return false; + if (geteuid()) { ERROR("Must be root to checkpoint\n"); return false; -- 2.1.4 _______________________________________________ lxc-devel mailing list lxc-devel@lists.linuxcontainers.org http://lists.linuxcontainers.org/listinfo/lxc-devel