diff options
-rw-r--r-- | include/docker.h | 22 | ||||
-rw-r--r-- | src/docker.c | 139 |
2 files changed, 161 insertions, 0 deletions
diff --git a/include/docker.h b/include/docker.h new file mode 100644 index 0000000..03f5d0d --- /dev/null +++ b/include/docker.h @@ -0,0 +1,22 @@ +#ifndef OMC_DOCKER_H +#define OMC_DOCKER_H + +#define OMC_DOCKER_QUIET 1 << 1 + +#define OMC_DOCKER_BUILD 1 << 1 +#define OMC_DOCKER_BUILD_X 1 << 2 + +struct DockerCapabilities { + int podman; + int build; + int available; + int usable; +}; + +int docker_capable(struct DockerCapabilities *result); +int docker_exec(const char *args, unsigned flags); +int docker_build(const char *dirpath, const char *args, int engine); +int docker_script(const char *image, char *data, unsigned flags); +int docker_save(const char *image, const char *destdir); + +#endif //OMC_DOCKER_H diff --git a/src/docker.c b/src/docker.c new file mode 100644 index 0000000..49d8b08 --- /dev/null +++ b/src/docker.c @@ -0,0 +1,139 @@ +#include "omc.h" +#include "docker.h" + + +int docker_exec(const char *args, unsigned flags) { + struct Process proc; + char cmd[PATH_MAX]; + + memset(&proc, 0, sizeof(proc)); + memset(cmd, 0, sizeof(cmd)); + snprintf(cmd, sizeof(cmd) - 1, "docker %s", args); + if (flags & OMC_DOCKER_QUIET) { + strcpy(proc.f_stdout, "/dev/null"); + strcpy(proc.f_stderr, "/dev/null"); + } + fprintf(stderr, "%s\n", cmd); + shell(&proc, cmd); + return proc.returncode; +} + +int docker_script(const char *image, char *data, unsigned flags) { + FILE *infile; + FILE *outfile; + char cmd[PATH_MAX]; + + memset(cmd, 0, sizeof(cmd)); + snprintf(cmd, sizeof(cmd) - 1, "docker run --rm -i %s /bin/bash -", image); + if (flags & OMC_DOCKER_QUIET) { + } + fprintf(stderr, "%s\n", cmd); + outfile = popen(cmd, "w"); + + infile = fmemopen(data, strlen(data), "r"); + char buffer[OMC_BUFSIZ]; + do { + fgets(buffer, sizeof(buffer) - 1, infile); + fputs(buffer, outfile); + } while (!feof(infile)); + fclose(infile); + pclose(outfile); + + return 0; +} + +int docker_build(const char *dirpath, const char *args, int engine) { + char cmd[PATH_MAX]; + char build[15]; + + memset(build, 0, sizeof(build)); + memset(cmd, 0, sizeof(cmd)); + + if (engine & OMC_DOCKER_BUILD) { + strcpy(build, "build"); + } + if (engine & OMC_DOCKER_BUILD_X) { + strcpy(build, "buildx build"); + } + snprintf(cmd, sizeof(cmd) - 1, "%s %s %s", build, args, dirpath); + return docker_exec(cmd, 0); +} + +int docker_save(const char *image, const char *destdir) { + char cmd[PATH_MAX]; + memset(cmd, 0, sizeof(cmd)); + sprintf(cmd, "save %s -o \"%s/%s.tar\"", image, destdir, image); + return docker_exec(cmd, 0); +} + +static int docker_exists() { + if (find_program("docker")) { + return true; + } + return false; +} + +char *docker_ident() { + FILE *fp = NULL; + char *tempfile = NULL; + char line[PATH_MAX]; + struct Process proc; + + tempfile = xmkstemp(&fp); + if (!fp || !tempfile) { + return NULL; + } + + memset(&proc, 0, sizeof(proc)); + strcpy(proc.f_stdout, tempfile); + strcpy(proc.f_stderr, "/dev/null"); + shell(&proc, "docker -v"); + + if (!freopen(tempfile, "r", fp)) { + return NULL; + } + + if (!fgets(line, sizeof(line) - 1, fp)) { + free(tempfile); + return NULL; + } + fclose(fp); + remove(tempfile); + + return strdup(line); +} + +int docker_capable(struct DockerCapabilities *result) { + char *version = NULL; + memset(result, 0, sizeof(*result)); + + if (!docker_exists()) { + // docker isn't available + return false; + } + result->available = true; + + if (docker_exec("ps", OMC_DOCKER_QUIET)) { + // user cannot connect to the socket + return false; + } + + version = docker_ident(); + if (version && startswith(version, "podman")) { + result->podman = true; + } + guard_free(version) + + if (!docker_exec("buildx build --help", OMC_DOCKER_QUIET)) { + result->build |= OMC_DOCKER_BUILD; + } + if (!docker_exec("build --help", OMC_DOCKER_QUIET)) { + result->build |= OMC_DOCKER_BUILD_X; + } + if (!result->build) { + // can't use docker without a build plugin + return false; + } + result->usable = true; + return true; +} |