aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoseph Hunkeler <jhunkeler@gmail.com>2024-02-23 17:07:37 -0500
committerJoseph Hunkeler <jhunkeler@gmail.com>2024-02-23 17:07:37 -0500
commit583b74d9296ea05d75c2690129bc9cc70618fa56 (patch)
tree936db4766c10b633a4873888e4c4c1dcb9126413 /src
parentbe8164fff08e3f1c3beb03d6d1ea9f15d7963ef8 (diff)
downloadstasis-583b74d9296ea05d75c2690129bc9cc70618fa56.tar.gz
Initial commit of docker integration code
Diffstat (limited to 'src')
-rw-r--r--src/docker.c139
1 files changed, 139 insertions, 0 deletions
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;
+}