diff options
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/core/conda.c | 29 | ||||
| -rw-r--r-- | src/lib/core/include/utils.h | 18 | ||||
| -rw-r--r-- | src/lib/core/utils.c | 46 |
3 files changed, 85 insertions, 8 deletions
diff --git a/src/lib/core/conda.c b/src/lib/core/conda.c index 444cfaa..5c7779f 100644 --- a/src/lib/core/conda.c +++ b/src/lib/core/conda.c @@ -36,9 +36,10 @@ int micromamba_install(const struct MicromambaInfo *info) { // https://github.com/mamba-org/micromamba-releases/releases/download/${version}/micromamba-${arch} // Micromamba hosts binaries on github and on their own website. Prefer github. + // The "latest" binary from micromamba's site is compressed with bzip2 (06/2026) const char *url_fmts[] = { info->download_url, - "https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-%s-%s", + "https://github.com/mamba-org/micromamba-releases/releases/latest/download/micromamba-%s-%s.tar.bz2", "https://micro.mamba.pm/api/micromamba/%s-%s/latest", }; const size_t url_fmts_max = sizeof(url_fmts) / sizeof(url_fmts[0]); @@ -84,14 +85,26 @@ int micromamba_install(const struct MicromambaInfo *info) { snprintf(mmbin, sizeof(mmbin), "%s/micromamba", info->micromamba_prefix); 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); - int untarcmd_status = system(untarcmd); - if (untarcmd_status) { - return -1; + + if (is_file_compressed(installer_path)) { + char untarcmd[PATH_MAX * 2] = {0}; + 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; + } + } else { + if (copy2(installer_path, mmbin, CT_PERM)) { + SYSERROR("unable to copy %s to %s", installer_path, mmbin); + return -1; + } + if (chmod(mmbin, 0755)) { + SYSERROR("unable to set permissions: %s (%s)", mmbin, strerror(errno)); + return -1; + } } } return 0; diff --git a/src/lib/core/include/utils.h b/src/lib/core/include/utils.h index 98b8ae8..3f0fe9f 100644 --- a/src/lib/core/include/utils.h +++ b/src/lib/core/include/utils.h @@ -492,4 +492,22 @@ int get_random_bytes(char *result, size_t maxlen); int non_format_len(const char *s); char *center_text(const char *s, size_t maxwidth); + +/** + * Check magic bytes against known compression formats + * + * ```c + * const char *filename = "/path/to/file.zip"; + * if (is_file_compressed(filename)) { + * // file is compressed + * } else { + * // file is not compressed + * } + * ``` + * + * @param filename path to maybe-compressed file + * @return 0 if not compressed + * @return 1 if compressed + */ +int is_file_compressed(const char *filename); #endif //STASIS_UTILS_H diff --git a/src/lib/core/utils.c b/src/lib/core/utils.c index b4a520d..152c5c5 100644 --- a/src/lib/core/utils.c +++ b/src/lib/core/utils.c @@ -1273,3 +1273,49 @@ char *center_text(const char *s, const size_t maxwidth) { return result; } +int is_file_compressed(const char *filename) { + FILE *fp = fopen(filename, "rb"); + if (!fp) { + SYSERROR("Unable to open for reading: %s", filename); + return -1; + } + + // Container for magic bytes + struct Magic { + const unsigned char *byte; + const size_t size; + }; + + // Array of magic bytes for different compression types + const struct Magic magic[] = { + {(unsigned char *) "BZh", 3}, // bzip2 + {(unsigned char *) "\x1f\x8b", 2}, // gzip + {(unsigned char *) "\xfd\x37\x7a\x58\x5a\x00", 6}, // xz + {(unsigned char *) "PK\03\04", 3}, // zip + {(unsigned char *) "PK\05\06", 3}, // zip (empty) + {(unsigned char *) "PK\07\08", 3}, // zip (spanned) + {(unsigned char *) "\xfd\x2f\xb5\x28", 4} // zstd + }; + unsigned char buf[8] = {0}; // unsigned long + size_t bytes_read = 0; + bytes_read = fread(buf, 1, sizeof(buf), fp); + if (bytes_read < sizeof(buf)) { + SYSWARN("consumed fewer than %zu bytes (%zu) from %s", sizeof(buf), bytes_read, filename); + fclose(fp); + // well, the file isn't compressed. + return 0; + } + fclose(fp); + + // Compare known magic bytes to consumed data + for (size_t i = 0; i < sizeof(magic) / sizeof(magic[0]); i++) { + if (memcmp(buf, magic[i].byte, magic[i].size) == 0) { + // match + return 1; + } + } + + // no match + return 0; +} + |
