From bccb39c88e157a90659e8226e2fadad7dc258130 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 22 Feb 2026 00:39:33 -0500 Subject: Bugfix: Avoid segfault on freeing uninitialized Wheel struct --- src/lib/core/wheel.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src/lib/core') diff --git a/src/lib/core/wheel.c b/src/lib/core/wheel.c index c7e485a..79b5a21 100644 --- a/src/lib/core/wheel.c +++ b/src/lib/core/wheel.c @@ -113,6 +113,9 @@ struct Wheel *get_wheel_info(const char *basepath, const char *name, char *to_ma void wheel_free(struct Wheel **wheel) { struct Wheel *w = (*wheel); + if (!w) { + return; + } guard_free(w->path_name); guard_free(w->file_name); guard_free(w->distribution); -- cgit From 5430730ae86c53a93633b1cdcc88a31bd832bb98 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 22 Feb 2026 00:40:29 -0500 Subject: Bugfix: git describe output should always produce long output if a tag exists --- src/lib/core/utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/core') diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c index 00d747f..34dee45 100644 --- a/src/lib/core/utils.c +++ b/src/lib/core/utils.c @@ -376,7 +376,7 @@ char *git_describe(const char *path) { return NULL; } - FILE *pp = popen("git describe --first-parent --always --tags", "r"); + FILE *pp = popen("git describe --first-parent --long --always --tags", "r"); if (!pp) { return NULL; } -- cgit From f8a564e5a45d0e98fe3c556aa158d20b6a29ffd7 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 22 Feb 2026 00:43:40 -0500 Subject: Add method to get a byte string of random alpha-numeric values * get_random_generator_file() * get_random_bytes() --- src/lib/core/include/utils.h | 12 +++++++++++ src/lib/core/utils.c | 50 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+) (limited to 'src/lib/core') diff --git a/src/lib/core/include/utils.h b/src/lib/core/include/utils.h index ea98faf..335a7e4 100644 --- a/src/lib/core/include/utils.h +++ b/src/lib/core/include/utils.h @@ -27,6 +27,15 @@ #define LINE_SEP "\n" #endif +#if defined(STASIS_OS_LINUX) +#define STASIS_RANDOM_GENERATOR_FILE "/dev/urandom" +#elif defined(STASIS_OS_DARWIN) +#define STASIS_RANDOM_GENERATOR_FILE "/dev/random" +#else +#define STASIS_RANDOM_GENERATOR_FILE NULL +#define NEED_SRAND 1 +#endif + #define STASIS_XML_PRETTY_PRINT_PROG "xmllint" #define STASIS_XML_PRETTY_PRINT_ARGS "--format" @@ -470,4 +479,7 @@ void seconds_to_human_readable(int v, char *result, size_t maxlen); #define STR_TO_TIMEOUT_INVALID_TIME_SCALE (-2) int str_to_timeout(char *s); +const char *get_random_generator_file(); +int get_random_bytes(char *result, size_t maxlen); + #endif //STASIS_UTILS_H diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c index 34dee45..142e2b8 100644 --- a/src/lib/core/utils.c +++ b/src/lib/core/utils.c @@ -1120,3 +1120,53 @@ void seconds_to_human_readable(const int v, char *result, const size_t maxlen) { snprintf(result + strlen(result), maxlen, "%ds", seconds); } +const char *get_random_generator_file() { + return STASIS_RANDOM_GENERATOR_FILE; +} + +#ifdef NEED_SRAND +static char stasis_srand_initialized = 0; +#endif + +int get_random_bytes(char *result, size_t maxlen) { +#ifdef NEED_SRAND + if (!srand_initialized) { + srand(time(NULL)); + srand_initialized = 1; + } +#endif + size_t bytes = 0; + const char *filename = get_random_generator_file(); + FILE *fp = NULL; + if (filename != NULL) { + fp = fopen(filename, "rb"); + if (!fp) { + SYSERROR("%s", "unable to open random generator"); + return -1; + } + } + + do { + int ch = 0; + if (fp) { + ch = fgetc(fp); + } else { + ch = rand() % 255; + } + if (fp && ferror(fp)) { + SYSERROR("%s", "unable to read from random generator"); + return -1; + } + if (isalnum(ch)) { + result[bytes] = (char) ch; + bytes++; + } + } while (bytes < maxlen); + + if (fp) { + fclose(fp); + } + result[bytes ? bytes - 1 : 0] = '\0'; + return 0; +} + -- cgit From 36e5df6e8e01120e077dbb6eb087349f3c93b78d Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Sun, 22 Feb 2026 00:46:37 -0500 Subject: docker_script() now passes arguments to docker_exec * Implicit 'docker run --rm' removed --- src/lib/core/docker.c | 4 ++-- src/lib/core/include/docker.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/lib/core') diff --git a/src/lib/core/docker.c b/src/lib/core/docker.c index 4723446..87e5e0e 100644 --- a/src/lib/core/docker.c +++ b/src/lib/core/docker.c @@ -19,11 +19,11 @@ int docker_exec(const char *args, unsigned flags) { return proc.returncode; } -int docker_script(const char *image, char *data, unsigned flags) { +int docker_script(const char *image, char *args, char *data, unsigned flags) { (void)flags; // TODO: placeholder char cmd[PATH_MAX] = {0}; - snprintf(cmd, sizeof(cmd) - 1, "docker run --rm -i %s /bin/sh -", image); + snprintf(cmd, sizeof(cmd) - 1, "docker run -i %s \"%s\" /bin/sh -", args ? args : "", image); FILE *outfile = popen(cmd, "w"); if (!outfile) { diff --git a/src/lib/core/include/docker.h b/src/lib/core/include/docker.h index 7585d86..96734f8 100644 --- a/src/lib/core/include/docker.h +++ b/src/lib/core/include/docker.h @@ -83,7 +83,7 @@ int docker_exec(const char *args, unsigned flags); * @return */ int docker_build(const char *dirpath, const char *args, int engine); -int docker_script(const char *image, char *data, unsigned flags); +int docker_script(const char *image, char *args, char *data, unsigned flags); int docker_save(const char *image, const char *destdir, const char *compression_program); void docker_sanitize_tag(char *str); int docker_validate_compression_program(char *prog); -- cgit From 039c1c3e231b975d57fdc2e24105dbbbe54a513c Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 12:38:32 -0500 Subject: Add wheel_builder CLI arguments --- src/lib/core/include/core.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/lib/core') diff --git a/src/lib/core/include/core.h b/src/lib/core/include/core.h index 5a3fa85..c895267 100644 --- a/src/lib/core/include/core.h +++ b/src/lib/core/include/core.h @@ -51,7 +51,9 @@ struct STASIS_GLOBAL { char *tmpdir; //!< Path to temporary storage directory char *conda_install_prefix; //!< Path to install conda char *sysconfdir; //!< Path where STASIS reads its configuration files (mission directory, etc) - int task_timeout; ///< Time in seconds before task is terminated + int task_timeout; ///!< Time in seconds before task is terminated + char *wheel_builder; ///!< Backend to build wheels (build, cibuildwheel, manylinux) + char *wheel_builder_manylinux_image; ///!< Image to use for a Manylinux build struct { char *tox_posargs; char *conda_reactivate; -- cgit From ff9e706905483fceae82c27161d929ee0654c894 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 12:41:03 -0500 Subject: Bugfix: Remove redundant string copy after duplication --- src/lib/core/strlist.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src/lib/core') diff --git a/src/lib/core/strlist.c b/src/lib/core/strlist.c index a0db5f3..b742d37 100644 --- a/src/lib/core/strlist.c +++ b/src/lib/core/strlist.c @@ -47,7 +47,6 @@ void strlist_append(struct StrList **pStrList, char *str) { (*pStrList)->data = tmp; (*pStrList)->data[(*pStrList)->num_inuse] = strdup(str); (*pStrList)->data[(*pStrList)->num_alloc] = NULL; - strcpy((*pStrList)->data[(*pStrList)->num_inuse], str); (*pStrList)->num_inuse++; (*pStrList)->num_alloc++; } -- cgit From 4dcd5e96f858e400491f0587c36ed3b57177b5ca Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 12:49:12 -0500 Subject: Bugfix: Repository URL not freed when no match occurs --- src/lib/core/template_func_proto.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/core') diff --git a/src/lib/core/template_func_proto.c b/src/lib/core/template_func_proto.c index 8324389..3e1cd99 100644 --- a/src/lib/core/template_func_proto.c +++ b/src/lib/core/template_func_proto.c @@ -55,8 +55,8 @@ int get_github_release_notes_auto_tplfunc_entrypoint(void *frame, void *data_out strlist_append(¬es_list, note); guard_free(note); } - guard_free(repository); } + guard_free(repository); } } // Return all notes as a single string -- cgit From f7009d9b1d9e5f6bbc4dc66f2f6db41516f45fe4 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 12:51:52 -0500 Subject: Free wheel_builder members --- src/lib/core/globals.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/core') diff --git a/src/lib/core/globals.c b/src/lib/core/globals.c index 834213b..63555a2 100644 --- a/src/lib/core/globals.c +++ b/src/lib/core/globals.c @@ -53,6 +53,8 @@ void globals_free() { guard_free(globals.conda_install_prefix); guard_strlist_free(&globals.conda_packages); guard_strlist_free(&globals.pip_packages); + guard_free(globals.wheel_builder); + guard_free(globals.wheel_builder_manylinux_image); guard_free(globals.jfrog.arch); guard_free(globals.jfrog.os); guard_free(globals.jfrog.url); -- cgit From d643ad74eca21bcba0039cdb8b3768614d6b02ef Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 13:30:30 -0500 Subject: Add backwards compatible way to emit only stdout, or stderr from docker command --- src/lib/core/docker.c | 17 +++++++++++++++-- src/lib/core/include/docker.h | 2 ++ 2 files changed, 17 insertions(+), 2 deletions(-) (limited to 'src/lib/core') diff --git a/src/lib/core/docker.c b/src/lib/core/docker.c index 87e5e0e..fb25ddb 100644 --- a/src/lib/core/docker.c +++ b/src/lib/core/docker.c @@ -1,17 +1,30 @@ #include "docker.h" -int docker_exec(const char *args, unsigned flags) { +int docker_exec(const char *args, const 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); + + unsigned final_flags = 0; if (flags & STASIS_DOCKER_QUIET) { + final_flags |= STASIS_DOCKER_QUIET_STDOUT; + final_flags |= STASIS_DOCKER_QUIET_STDERR; + } else { + final_flags = flags; + } + + if (final_flags & STASIS_DOCKER_QUIET_STDOUT) { strcpy(proc.f_stdout, "/dev/null"); + } + if (final_flags & STASIS_DOCKER_QUIET_STDERR) { strcpy(proc.f_stderr, "/dev/null"); - } else { + } + + if (!final_flags) { msg(STASIS_MSG_L2, "Executing: %s\n", cmd); } diff --git a/src/lib/core/include/docker.h b/src/lib/core/include/docker.h index 96734f8..dd67f21 100644 --- a/src/lib/core/include/docker.h +++ b/src/lib/core/include/docker.h @@ -6,6 +6,8 @@ //! Flag to squelch output from docker_exec() #define STASIS_DOCKER_QUIET 1 << 1 +#define STASIS_DOCKER_QUIET_STDOUT 1 << 2 +#define STASIS_DOCKER_QUIET_STDERR 1 << 3 //! Flag for older style docker build #define STASIS_DOCKER_BUILD 1 << 1 -- cgit From 199a4fd10080dd3e68997c392d6ab22b9c7db034 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 13:30:51 -0500 Subject: Flags are constant --- src/lib/core/docker.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/lib/core') diff --git a/src/lib/core/docker.c b/src/lib/core/docker.c index fb25ddb..39357ad 100644 --- a/src/lib/core/docker.c +++ b/src/lib/core/docker.c @@ -32,7 +32,7 @@ int docker_exec(const char *args, const unsigned flags) { return proc.returncode; } -int docker_script(const char *image, char *args, char *data, unsigned flags) { +int docker_script(const char *image, char *args, char *data, const unsigned flags) { (void)flags; // TODO: placeholder char cmd[PATH_MAX] = {0}; -- cgit From aebc1473e97fdc42b4aea0c6a14fb6d8dcce996e Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 13:33:01 -0500 Subject: Improve envctl_do_required output * On failure the user has a better idea of what needs to be fixed --- src/lib/core/envctl.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'src/lib/core') diff --git a/src/lib/core/envctl.c b/src/lib/core/envctl.c index b036611..d8d1b3d 100644 --- a/src/lib/core/envctl.c +++ b/src/lib/core/envctl.c @@ -92,23 +92,28 @@ unsigned envctl_get_flags(const struct EnvCtl *envctl, const char *name) { } void envctl_do_required(const struct EnvCtl *envctl, int verbose) { + int failed = 0; for (size_t i = 0; i < envctl->num_used; i++) { - struct EnvCtl_Item *item = envctl->item[i]; + const struct EnvCtl_Item *item = envctl->item[i]; const char *name = item->name; envctl_except_fn *callback = item->callback; if (verbose) { - msg(STASIS_MSG_L2, "Verifying %s\n", name); + msg(STASIS_MSG_L2, "Verifying %s [%s]\n", name, item->flags & STASIS_ENVCTL_REQUIRED ? "required" : "optional"); } - int code = callback((const void *) item, (const void *) name); + const int code = callback((const void *) item, (const void *) name); if (code == STASIS_ENVCTL_RET_IGNORE || code == STASIS_ENVCTL_RET_SUCCESS) { continue; } if (code == STASIS_ENVCTL_RET_FAIL) { - fprintf(stderr, "\n%s must be set. Exiting.\n", name); - exit(1); + msg(STASIS_MSG_ERROR, "\n%s%s must be defined.\n", name, STASIS_COLOR_RESET); + failed++; } - fprintf(stderr, "\nan unknown envctl callback code occurred: %d\n", code); + msg(STASIS_MSG_ERROR, "\nan unknown envctl callback code occurred: %d\n", code); + } + + if (failed) { + msg(STASIS_MSG_ERROR, "Environment check failed with %d error(s)\n", failed); exit(1); } } -- cgit From 5bd544a6cb88b10d477dd24b956bc7ceddeb706b Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 16:11:30 -0500 Subject: Add strlist_appendf function (future use) --- src/lib/core/include/strlist.h | 1 + src/lib/core/strlist.c | 22 ++++++++++++++++++++++ 2 files changed, 23 insertions(+) (limited to 'src/lib/core') diff --git a/src/lib/core/include/strlist.h b/src/lib/core/include/strlist.h index 18c60eb..1aaae3e 100644 --- a/src/lib/core/include/strlist.h +++ b/src/lib/core/include/strlist.h @@ -46,6 +46,7 @@ void strlist_append_strlist(struct StrList *pStrList1, struct StrList *pStrList2 void strlist_append(struct StrList **pStrList, char *str); void strlist_append_array(struct StrList *pStrList, char **arr); void strlist_append_tokenize(struct StrList *pStrList, char *str, char *delim); +int strlist_appendf(struct StrList **pStrList, const char *fmt, ...); struct StrList *strlist_copy(struct StrList *pStrList); int strlist_cmp(struct StrList *a, struct StrList *b); void strlist_free(struct StrList **pStrList); diff --git a/src/lib/core/strlist.c b/src/lib/core/strlist.c index b742d37..3479c44 100644 --- a/src/lib/core/strlist.c +++ b/src/lib/core/strlist.c @@ -229,6 +229,28 @@ void strlist_append_strlist(struct StrList *pStrList1, struct StrList *pStrList2 guard_free(tmp); } +/** + * Append a formatted string + * Behavior is identical to asprintf-family of functions + * @param pStrList `StrList` + * @param fmt printf format string + * @param ... format arguments + * @return same as vasnprintf + */ +int strlist_appendf(struct StrList **pStrList, const char *fmt, ...) { + char *s = NULL; + va_list ap; + va_start(ap, fmt); + const int len = vasprintf(&s, fmt, ap); + va_end(ap); + + if (pStrList && *pStrList && len >= 0) { + strlist_append(pStrList, s); + } + guard_free(s); + return len; +} + /** * Produce a new copy of a `StrList` * @param pStrList `StrList` -- cgit From 45d5cbb70b7120a1a9c8cfac81d8ae8748d12815 Mon Sep 17 00:00:00 2001 From: Joseph Hunkeler Date: Thu, 5 Mar 2026 21:54:32 -0500 Subject: Add TODOs --- src/lib/core/utils.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/lib/core') diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c index 142e2b8..e106193 100644 --- a/src/lib/core/utils.c +++ b/src/lib/core/utils.c @@ -376,6 +376,7 @@ char *git_describe(const char *path) { return NULL; } + // TODO: Use `-C [path]` if the version of git installed supports it FILE *pp = popen("git describe --first-parent --long --always --tags", "r"); if (!pp) { return NULL; @@ -401,6 +402,7 @@ char *git_rev_parse(const char *path, char *args) { return NULL; } + // TODO: Use `-C [path]` if the version of git installed supports it sprintf(cmd, "git rev-parse %s", args); FILE *pp = popen(cmd, "r"); if (!pp) { -- cgit