diff options
| -rw-r--r-- | cmake/GitVersion.cmake | 2 | ||||
| -rw-r--r-- | src/cli/stasis_indexer/helpers.c | 1 | ||||
| -rw-r--r-- | src/cli/stasis_indexer/stasis_indexer_main.c | 8 | ||||
| -rw-r--r-- | src/lib/core/conda.c | 51 | ||||
| -rw-r--r-- | src/lib/core/include/conda.h | 4 | ||||
| -rw-r--r-- | src/lib/core/ini.c | 62 | ||||
| -rw-r--r-- | src/lib/delivery/delivery.c | 4 | ||||
| -rw-r--r-- | src/lib/delivery/delivery_export.c | 18 | ||||
| -rw-r--r-- | src/lib/delivery/delivery_init.c | 11 | ||||
| -rw-r--r-- | tests/test_conda.c | 14 |
10 files changed, 126 insertions, 49 deletions
diff --git a/cmake/GitVersion.cmake b/cmake/GitVersion.cmake index c9c6159..005667d 100644 --- a/cmake/GitVersion.cmake +++ b/cmake/GitVersion.cmake @@ -15,7 +15,7 @@ function(get_version_from_git) endif() execute_process( - COMMAND ${GIT_EXECUTABLE} describe --first-parent --long --dirty --tags --always + COMMAND ${GIT_EXECUTABLE} describe --long --dirty --tags --always WORKING_DIRECTORY ${CMAKE_SOURCE_DIR} OUTPUT_VARIABLE GIT_TAG OUTPUT_STRIP_TRAILING_WHITESPACE diff --git a/src/cli/stasis_indexer/helpers.c b/src/cli/stasis_indexer/helpers.c index 86a20e4..425d209 100644 --- a/src/cli/stasis_indexer/helpers.c +++ b/src/cli/stasis_indexer/helpers.c @@ -156,6 +156,7 @@ int micromamba_configure(const struct Delivery *ctx, struct MicromambaInfo *m) { } m->conda_prefix = globals.conda_install_prefix; m->micromamba_prefix = micromamba_prefix; + m->download_dir = ctx->storage.tmpdir; const size_t pathvar_len = strlen(getenv("PATH")) + strlen(m->micromamba_prefix) + strlen(m->conda_prefix) + 3 + 4 + 1; // ^^^^^^^^^^^^^^^^^^ diff --git a/src/cli/stasis_indexer/stasis_indexer_main.c b/src/cli/stasis_indexer/stasis_indexer_main.c index d71c341..ed938b7 100644 --- a/src/cli/stasis_indexer/stasis_indexer_main.c +++ b/src/cli/stasis_indexer/stasis_indexer_main.c @@ -212,6 +212,10 @@ int main(const int argc, char *argv[]) { if (optind < argc) { rootdirs_total = argc - current_index; rootdirs = calloc(rootdirs_total + 1, sizeof(*rootdirs)); + if (!rootdirs) { + SYSERROR("%s", "unable to allocate memory for rootdirs array"); + exit(1); + } int i = 0; while (optind < argc) { @@ -223,6 +227,10 @@ int main(const int argc, char *argv[]) { } // use first positional argument rootdirs[i] = realpath(argv[optind], NULL); + if (!rootdirs[i]) { + SYSERROR("%s", "Unable to allocate memory for root directory"); + exit(1); + } optind++; break; } diff --git a/src/lib/core/conda.c b/src/lib/core/conda.c index 731cf80..4557c5c 100644 --- a/src/lib/core/conda.c +++ b/src/lib/core/conda.c @@ -19,11 +19,22 @@ int micromamba(const struct MicromambaInfo *info, char *command, ...) { sys.machine[sizeof(sys.machine) - 1] = '\0'; } + if (!info->download_dir || isempty(info->download_dir)) { + SYSERROR("%s", "micromamba inf->download_dir is NULL, or empty"); + return -1; + } + + if (mkdirs(info->download_dir, 0755) < 0) { + SYSERROR("Unable to create info->download_dir: %s", info->download_dir); + return -1; + } + char url[PATH_MAX] = {0}; snprintf(url, sizeof(url), "https://micro.mamba.pm/api/micromamba/%s-%s/latest", sys.sysname, sys.machine); - char installer_path[PATH_MAX]; - snprintf(installer_path, sizeof(installer_path), "%s/latest", getenv("TMPDIR") ? getenv("TMPDIR") : "/tmp"); + const char installer_name[] = "mm_latest"; + char installer_path[PATH_MAX] = {0}; + snprintf(installer_path, sizeof(installer_path), "%s/%s", info->download_dir, installer_name); if (access(installer_path, F_OK)) { char *errmsg = NULL; @@ -41,7 +52,9 @@ int micromamba(const struct MicromambaInfo *info, char *command, ...) { if (access(mmbin, F_OK)) { char untarcmd[PATH_MAX * 2]; mkdirs(info->micromamba_prefix, 0755); - snprintf(untarcmd, sizeof(untarcmd), "tar -xvf %s -C %s --strip-components=1 bin/micromamba 1>/dev/null", installer_path, info->micromamba_prefix); + snprintf(untarcmd, sizeof(untarcmd), + "tar -xvf %s -C %s --strip-components=1 bin/micromamba 1>/dev/null", + installer_path, info->micromamba_prefix); int untarcmd_status = system(untarcmd); if (untarcmd_status) { return -1; @@ -137,7 +150,7 @@ const char *pkg_index_provides_strerror(int code) { return PKG_ERROR_STR[code]; } -int pkg_index_provides(int mode, const char *index, const char *spec) { +int pkg_index_provides(int mode, const char *index, const char *spec, const char *logdir) { char cmd[PATH_MAX] = {0}; char spec_local[255] = {0}; @@ -153,7 +166,14 @@ int pkg_index_provides(int mode, const char *index, const char *spec) { lstrip(spec_local); strip(spec_local); - char logfile[] = "/tmp/stasis/STASIS-package_exists.XXXXXX"; + if (mkdirs(logdir, 0700) < 0) { + SYSERROR("Unable to create log directory: %s", logdir ? logdir : "NULL"); + return -1; + } + const char logfile_template[] = "STASIS-package_exists.XXXXXX"; + char logfile[PATH_MAX] = {0}; + snprintf(logfile, sizeof(logfile), "%s/%s", logdir, logfile_template); + int logfd = mkstemp(logfile); if (logfd < 0) { perror(logfile); @@ -187,11 +207,24 @@ int pkg_index_provides(int mode, const char *index, const char *spec) { return PKG_INDEX_PROVIDES_E_INTERNAL_MODE_UNKNOWN; } +#if defined(DEBUG) + const int debug_log = 1; +#else + const debug_log = 0; +#endif + // Print errors only when shell() itself throws one // If some day we want to see the errors thrown by pip too, use this // condition instead: (status != 0) + if (debug_log) { + SYSDEBUG("Executing: %s", cmd); + } status = shell(&proc, cmd); - if (status < 0) { + + if (debug_log) { + SYSDEBUG("Log file: %s", logfile); + } + if (status < 0 || debug_log) { FILE *fp = fdopen(logfd, "r"); if (!fp) { remove(logfile); @@ -201,7 +234,11 @@ int pkg_index_provides(int mode, const char *index, const char *spec) { fflush(stdout); fflush(stderr); while (fgets(line, sizeof(line) - 1, fp) != NULL) { - fprintf(stderr, "%s", line); + if (debug_log) { + SYSDEBUG("%s", strip(line)); + } else { + fprintf(stderr, "%s", line); + } } fflush(stderr); fclose(fp); diff --git a/src/lib/core/include/conda.h b/src/lib/core/include/conda.h index f3d481c..cc9426d 100644 --- a/src/lib/core/include/conda.h +++ b/src/lib/core/include/conda.h @@ -29,6 +29,7 @@ struct MicromambaInfo { char *micromamba_prefix; //!< Path to write micromamba binary char *conda_prefix; //!< Path to install conda base tree + char *download_dir; //!< Path to store micromamba installer }; /** @@ -219,12 +220,13 @@ int conda_index(const char *path); * @param mode USE_CONDA * @param index a file system path or url pointing to a simple index or conda channel * @param spec a pip package specification (e.g. `name==1.2.3`) + * @param logdir the directory to store the output log * @param spec a conda package specification (e.g. `name=1.2.3`) * @return PKG_NOT_FOUND, if not found * @return PKG_FOUND, if found * @return PKG_E_INDEX_PROVIDES_{ERROR}, on error (see conda.h) */ -int pkg_index_provides(int mode, const char *index, const char *spec); +int pkg_index_provides(int mode, const char *index, const char *spec, const char *logdir); const char *pkg_index_provides_strerror(int code); char *conda_get_active_environment(); diff --git a/src/lib/core/ini.c b/src/lib/core/ini.c index 12541f5..c37030c 100644 --- a/src/lib/core/ini.c +++ b/src/lib/core/ini.c @@ -347,6 +347,10 @@ int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *v section->data_count++; } else { struct INIData *data = ini_data_get(*ini, section_name, key); + if (!data) { + SYSERROR("%s:%s: key does not exist", section_name, key); + return -1; + } size_t value_len_old = strlen(data->value); size_t value_len = strlen(value); size_t value_len_new = value_len_old + value_len; @@ -355,9 +359,9 @@ int ini_data_append(struct INIFILE **ini, char *section_name, char *key, char *v if (!value_tmp) { SYSERROR("Unable to increase data->value size to %zu bytes", value_len_new + 2); return -1; - } else { - data->value = value_tmp; } + data->value = value_tmp; + strncat(data->value, value, value_len_new - strlen(data->value)); } return 0; @@ -422,6 +426,7 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) { for (size_t x = 0; x < ini->section_count; x++) { struct INISection *section = ini->section[x]; char *section_name = section->key; + fprintf(*stream, "[%s]" LINE_SEP, section_name); for (size_t y = 0; y < ini->section[x]->data_count; y++) { @@ -430,6 +435,7 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) { char *key = data->key; char *value = data->value; unsigned *hint = &data->type_hint; + memset(outvalue, 0, sizeof(outvalue)); if (key && value) { @@ -442,6 +448,9 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) { xvalue = ini_getval_str(ini, section_name, key, (int) mode, &err); value = xvalue; } + + const size_t buf_size = sizeof(outvalue); + size_t buf_len = 0; char **parts = split(value, LINE_SEP, 0); for (size_t p = 0; parts && parts[p] != NULL; p++) { char *render = NULL; @@ -456,19 +465,16 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) { return -1; } - size_t len = 0; + buf_len = strlen(outvalue); if (*hint == INIVAL_TYPE_STR_ARRAY) { - int leading_space = isspace(*render); + const int leading_space = isspace(*render); if (leading_space) { - len = sizeof(outvalue) - (size_t) snprintf(NULL, 0, "%s" LINE_SEP, render); - snprintf(outvalue + strlen(outvalue), len, "%s" LINE_SEP, render); + snprintf(outvalue + buf_len, buf_size - buf_len, "%s" LINE_SEP, render); } else { - len = sizeof(outvalue) - (size_t) snprintf(NULL, 0, " %s" LINE_SEP, render); - snprintf(outvalue + strlen(outvalue), len, " %s" LINE_SEP, render); + snprintf(outvalue + buf_len, buf_size - buf_len, " %s" LINE_SEP, render); } } else { - len = sizeof(outvalue) - (size_t) snprintf(NULL, 0, "%s", render); - snprintf(outvalue + strlen(outvalue), len, "%s", render); + snprintf(outvalue + buf_len, buf_size - buf_len, "%s", render); } if (mode == INI_WRITE_PRESERVE) { guard_free(render); @@ -476,7 +482,12 @@ int ini_write(struct INIFILE *ini, FILE **stream, unsigned mode) { } guard_array_free(parts); strip(outvalue); - strncat(outvalue, LINE_SEP, sizeof(outvalue) - strlen(outvalue) - 1); + + // update length of outvalue + buf_len = strlen(outvalue); + + snprintf(outvalue + buf_len, buf_size - buf_len, "%s", LINE_SEP); + fprintf(*stream, "%s = %s%s", ini->section[x]->data[y]->key, *hint == INIVAL_TYPE_STR_ARRAY ? LINE_SEP : "", outvalue); guard_free(value); } else { @@ -499,12 +510,9 @@ char *unquote(char *s) { void ini_free(struct INIFILE **ini) { for (size_t section = 0; section < (*ini)->section_count; section++) { - SYSDEBUG("freeing section: %s", (*ini)->section[section]->key); for (size_t data = 0; data < (*ini)->section[section]->data_count; data++) { if ((*ini)->section[section]->data[data]) { - SYSDEBUG("freeing data key: %s", (*ini)->section[section]->data[data]->key); guard_free((*ini)->section[section]->data[data]->key); - SYSDEBUG("freeing data value: %s", (*ini)->section[section]->data[data]->value); guard_free((*ini)->section[section]->data[data]->value); guard_free((*ini)->section[section]->data[data]); } @@ -545,15 +553,15 @@ struct INIFILE *ini_open(const char *filename) { unsigned hint = 0; int multiline_data = 0; int no_data = 0; - char inikey[2][255]; + char inikey[2][255] = {0}; char *key = inikey[0]; char *key_last = inikey[1]; char value[STASIS_BUFSIZ] = {0}; - memset(inikey, 0, sizeof(inikey)); - // Read file for (size_t i = 0; fgets(line, sizeof(line), fp) != NULL; i++) { + const size_t key_last_size = sizeof(inikey[1]); + const size_t key_size = sizeof(inikey[0]); if (no_data && multiline_data) { if (!isempty(line)) { no_data = 0; @@ -562,7 +570,7 @@ struct INIFILE *ini_open(const char *filename) { } memset(value, 0, sizeof(value)); } else { - memset(key, 0, sizeof(inikey[0])); + memset(key, 0, key_size); } // Find pointer to first comment character char *comment = strpbrk(line, ";#"); @@ -586,7 +594,7 @@ struct INIFILE *ini_open(const char *filename) { // Test for section header: [string] if (startswith(line, "[")) { // The previous key is irrelevant now - memset(key_last, 0, sizeof(inikey[1])); + memset(key_last, 0, key_last_size); char *section_name = substring_between(line, "[]"); if (!section_name) { @@ -628,15 +636,16 @@ struct INIFILE *ini_open(const char *filename) { if (operator) { size_t key_len = operator - line; - memset(key, 0, sizeof(inikey[0])); + memset(key, 0, key_size); + strncpy(key, line, key_len); - key[key_len] = '\0'; + key[key_size - 1] = '\0'; lstrip(key); strip(key); - memset(key_last, 0, sizeof(inikey[1])); - strncpy(key_last, key, sizeof(inikey[1]) - 1); - key_last[sizeof(inikey[1]) - 1] = '\0'; + memset(key_last, 0, key_last_size); + strncpy(key_last, key, key_last_size - 1); + key_last[key_last_size - 1] = '\0'; reading_value = 1; if (strlen(operator) > 1) { @@ -645,6 +654,7 @@ struct INIFILE *ini_open(const char *filename) { strncpy(value, "", sizeof(value) - 1); } value[sizeof(value) - 1] = '\0'; + if (isempty(value)) { //printf("%s is probably long raw data\n", key); hint = INIVAL_TYPE_STR_ARRAY; @@ -657,8 +667,8 @@ struct INIFILE *ini_open(const char *filename) { } strip(value); } else { - strncpy(key, key_last, sizeof(inikey[0]) - 1); - key[sizeof(inikey[0]) - 1] = '\0'; + strncpy(key, key_last, key_size - 1); + key[key_size - 1] = '\0'; strncpy(value, line, sizeof(value) - 1); value[sizeof(value) - 1] = '\0'; } diff --git a/src/lib/delivery/delivery.c b/src/lib/delivery/delivery.c index d4fe08c..45b3b35 100644 --- a/src/lib/delivery/delivery.c +++ b/src/lib/delivery/delivery.c @@ -453,9 +453,9 @@ void delivery_defer_packages(struct Delivery *ctx, int type) { int upstream_exists = 0; if (DEFER_PIP == type) { - upstream_exists = pkg_index_provides(PKG_USE_PIP, PYPI_INDEX_DEFAULT, name); + upstream_exists = pkg_index_provides(PKG_USE_PIP, PYPI_INDEX_DEFAULT, name, ctx->storage.tmpdir); } else if (DEFER_CONDA == type) { - upstream_exists = pkg_index_provides(PKG_USE_CONDA, NULL, name); + upstream_exists = pkg_index_provides(PKG_USE_CONDA, NULL, name, ctx->storage.tmpdir); } if (PKG_INDEX_PROVIDES_FAILED(upstream_exists)) { diff --git a/src/lib/delivery/delivery_export.c b/src/lib/delivery/delivery_export.c index c12a365..e67fdfb 100644 --- a/src/lib/delivery/delivery_export.c +++ b/src/lib/delivery/delivery_export.c @@ -2,26 +2,44 @@ static void delivery_export_configuration(const struct Delivery *ctx) { msg(STASIS_MSG_L2, "Exporting delivery configuration\n"); + + SYSDEBUG("Entering configuration directory: %s", ctx->storage.delivery_dir); if (!pushd(ctx->storage.cfgdump_dir)) { char filename[PATH_MAX] = {0}; + SYSDEBUG("%s", "Populating filename"); snprintf(filename, sizeof(filename), "%s.ini", ctx->info.release_name); + SYSDEBUG("filename: %s", filename); + + SYSDEBUG("%s: opening", filename); FILE *spec = fopen(filename, "w+"); if (!spec) { msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed %s\n", filename); exit(1); } + SYSDEBUG("%s: writing", filename); ini_write(ctx->_stasis_ini_fp.delivery, &spec, INI_WRITE_RAW); + SYSDEBUG("%s: writing done", filename); fclose(spec); + SYSDEBUG("%s: closing", filename); + SYSDEBUG("%s", "Zeroing filename"); memset(filename, 0, sizeof(filename)); + SYSDEBUG("%s", "Populating rendered filename"); snprintf(filename, sizeof(filename), "%s-rendered.ini", ctx->info.release_name); + SYSDEBUG("filename: %s", filename); + + SYSDEBUG("%s: opening", filename); spec = fopen(filename, "w+"); if (!spec) { msg(STASIS_MSG_ERROR | STASIS_MSG_L2, "failed %s\n", filename); exit(1); } + SYSDEBUG("%s: writing", filename); ini_write(ctx->_stasis_ini_fp.delivery, &spec, INI_WRITE_PRESERVE); + SYSDEBUG("%s: writing done", filename); + SYSDEBUG("%s: closing", filename); fclose(spec); + SYSDEBUG("Returning from %s", ctx->storage.cfgdump_dir); popd(); } else { SYSERROR("Failed to enter directory: %s", ctx->storage.delivery_dir); diff --git a/src/lib/delivery/delivery_init.c b/src/lib/delivery/delivery_init.c index 17f3899..ec05a0f 100644 --- a/src/lib/delivery/delivery_init.c +++ b/src/lib/delivery/delivery_init.c @@ -14,7 +14,7 @@ int delivery_init_tmpdir(struct Delivery *ctx) { int unusable = 1; errno = 0; - int need_setenv = 0; + //int need_setenv = 0; const char *x = getenv("TMPDIR"); if (x) { guard_free(ctx->storage.tmpdir); @@ -30,7 +30,7 @@ int delivery_init_tmpdir(struct Delivery *ctx) { SYSERROR("%s", "unable to allocate tmpdir"); goto l_delivery_init_tmpdir_fatal; } - need_setenv = 1; + //need_setenv = 1; } if (!ctx->storage.tmpdir) { @@ -95,9 +95,10 @@ int delivery_init_tmpdir(struct Delivery *ctx) { } } unusable = 0; - if (need_setenv) { - setenv("TMPDIR", ctx->storage.tmpdir, 1); - } + // TODO: Figure out why this breaks EVERYTHING + //if (need_setenv) { + // setenv("TMPDIR", ctx->storage.tmpdir, 1); + //} l_delivery_init_tmpdir_fatal: guard_free(tmpdir); diff --git a/tests/test_conda.c b/tests/test_conda.c index 9f0e718..e32c9f2 100644 --- a/tests/test_conda.c +++ b/tests/test_conda.c @@ -18,10 +18,10 @@ void test_micromamba() { int result; }; struct testcase tc[] = { - {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "info", .result = 0}, - {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "env list", .result = 0}, - {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "run python3 -V", .result = 0}, - {.mminfo = {.micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "no_such_option", .result = 109}, + {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "info", .result = 0}, + {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "env list", .result = 0}, + {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "run python3 -V", .result = 0}, + {.mminfo = {.download_dir = cwd_workspace, .micromamba_prefix = mm_prefix, .conda_prefix = c_prefix}, .cmd = "no_such_option", .result = 109}, }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { @@ -31,7 +31,7 @@ void test_micromamba() { result = result >> 8; } STASIS_ASSERT(result == item->result, "unexpected exit value"); - SYSERROR("micromamba command: '%s' (returned: %d)", item->cmd, result); + SYSDEBUG("micromamba command: '%s' (returned: %d)", item->cmd, result); } } @@ -143,7 +143,7 @@ void test_pip_index_provides() { }; for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { struct testcase *test = &tc[i]; - int result = pkg_index_provides(PKG_USE_PIP, test->pindex, test->name); + int result = pkg_index_provides(PKG_USE_PIP, test->pindex, test->name, "."); STASIS_ASSERT(result == test->expected, "Unexpected result"); if (PKG_INDEX_PROVIDES_FAILED(result)) { fprintf(stderr, "error: %s\n", pkg_index_provides_strerror(result)); @@ -175,7 +175,7 @@ void test_conda_provides() { for (size_t i = 0; i < sizeof(tc) / sizeof(*tc); i++) { struct testcase *test = &tc[i]; - int result = pkg_index_provides(PKG_USE_CONDA, NULL, test->name); + int result = pkg_index_provides(PKG_USE_CONDA, NULL, test->name, "."); printf("%s returned %d, expecting %d\n", test->name, result, test->expected); STASIS_ASSERT(result == test->expected, "Unexpected result"); } |
