build: finish cross-platform release tooling
This commit is contained in:
+61
-29
@@ -22,43 +22,75 @@
|
||||
#define ERRBODY_MAX 4096
|
||||
#define LLM_MAX_RETRIES 3
|
||||
|
||||
/* Point libcurl at a CA bundle on Windows.
|
||||
static int ca_file_ok(const char *path) {
|
||||
if (!path || !path[0])
|
||||
return 0;
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f)
|
||||
return 0;
|
||||
fclose(f);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Point libcurl at a CA bundle.
|
||||
*
|
||||
* An OpenSSL-based libcurl keeps the path it was built with -- MSYS2's is
|
||||
* "/mingw64/etc/ssl/certs/ca-bundle.crt", which resolves to nothing once the
|
||||
* binary runs outside an MSYS2 shell, and that build ignores CURL_CA_BUNDLE.
|
||||
* Every HTTPS request then dies with CURLE_SSL_CACERT_BADFILE (77).
|
||||
* libcurl keeps the bundle path it was built with. On Windows an OpenSSL
|
||||
* build carries MSYS2's "/mingw64/etc/ssl/certs/ca-bundle.crt"; the static
|
||||
* Linux release is built on one distro and runs on all of them, whose bundles
|
||||
* live in different places. A path that does not exist fails every HTTPS
|
||||
* request with CURLE_SSL_CACERT_BADFILE (77).
|
||||
*
|
||||
* Order: $CST_CA_BUNDLE, then ca-bundle.crt beside the executable. If neither
|
||||
* exists nothing is set, so a libcurl linked against Schannel (the Windows
|
||||
* certificate store) behaves exactly as before. */
|
||||
static void llm_apply_ca_bundle(CURL *curl) {
|
||||
#if defined(_WIN32)
|
||||
* Order: $CST_CA_BUNDLE; on Windows ca-bundle.crt beside the executable (if
|
||||
* absent nothing is set, so Schannel uses the certificate store); elsewhere
|
||||
* $SSL_CERT_FILE, libcurl's own default if that file exists, then the usual
|
||||
* distro locations. Decided once per process. */
|
||||
void cst_curl_apply_ca(void *curl) {
|
||||
static char ca[OS_PATH_MAX];
|
||||
static int checked;
|
||||
if (!checked) {
|
||||
checked = 1;
|
||||
static atomic_int state; /* 0 unchecked, 1 checking, 2 done */
|
||||
int expect = 0;
|
||||
if (atomic_compare_exchange_strong(&state, &expect, 1)) {
|
||||
const char *env = getenv("CST_CA_BUNDLE");
|
||||
if (env && env[0]) {
|
||||
if (ca_file_ok(env)) {
|
||||
snprintf(ca, sizeof(ca), "%s", env);
|
||||
} else {
|
||||
char dir[OS_PATH_MAX];
|
||||
if (os_exe_dir(dir, sizeof(dir)) == 0)
|
||||
os_path_join(ca, sizeof(ca), dir, "ca-bundle.crt");
|
||||
}
|
||||
if (ca[0]) {
|
||||
FILE *f = fopen(ca, "rb");
|
||||
if (f)
|
||||
fclose(f);
|
||||
#if defined(_WIN32)
|
||||
char dir[OS_PATH_MAX], p[OS_PATH_MAX];
|
||||
if (os_exe_dir(dir, sizeof(dir)) == 0 &&
|
||||
os_path_join(p, sizeof(p), dir, "ca-bundle.crt") == 0 &&
|
||||
ca_file_ok(p))
|
||||
snprintf(ca, sizeof(ca), "%s", p);
|
||||
#else
|
||||
static const char *const known[] = {
|
||||
"/etc/ssl/certs/ca-certificates.crt", /* Debian, Ubuntu, Arch, Alpine */
|
||||
"/etc/pki/tls/certs/ca-bundle.crt", /* Fedora, RHEL */
|
||||
"/etc/ssl/cert.pem", /* macOS, BSD, Alpine */
|
||||
"/etc/ssl/ca-bundle.pem", /* openSUSE */
|
||||
"/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
|
||||
};
|
||||
const char *pick = NULL;
|
||||
const char *sslenv = getenv("SSL_CERT_FILE");
|
||||
const curl_version_info_data *vi = curl_version_info(CURLVERSION_NOW);
|
||||
if (ca_file_ok(sslenv))
|
||||
pick = sslenv;
|
||||
else if (vi && ca_file_ok(vi->cainfo))
|
||||
pick = NULL; /* libcurl's built-in default already works */
|
||||
else
|
||||
ca[0] = '\0';
|
||||
for (size_t i = 0; i < sizeof(known) / sizeof(known[0]); i++)
|
||||
if (ca_file_ok(known[i])) {
|
||||
pick = known[i];
|
||||
break;
|
||||
}
|
||||
if (pick)
|
||||
snprintf(ca, sizeof(ca), "%s", pick);
|
||||
#endif
|
||||
}
|
||||
atomic_store(&state, 2);
|
||||
} else {
|
||||
while (atomic_load(&state) != 2)
|
||||
;
|
||||
}
|
||||
if (ca[0])
|
||||
curl_easy_setopt(curl, CURLOPT_CAINFO, ca);
|
||||
#else
|
||||
(void)curl;
|
||||
#endif
|
||||
curl_easy_setopt((CURL *)curl, CURLOPT_CAINFO, ca);
|
||||
}
|
||||
|
||||
#include "cst_attach.h"
|
||||
@@ -988,7 +1020,7 @@ int cst_llm_chat_stream(const cst_llm_request_t *req, char *err,
|
||||
ret = -1;
|
||||
break;
|
||||
}
|
||||
llm_apply_ca_bundle(curl);
|
||||
cst_curl_apply_ca(curl);
|
||||
sse_reset(&s);
|
||||
s.curl = curl;
|
||||
if (rec_dir && rec_dir[0]) {
|
||||
@@ -1233,7 +1265,7 @@ int cst_llm_list_models_meta(const char *api_base, const char *api_key,
|
||||
snprintf(err, err_sz, "curl init failed");
|
||||
return -1;
|
||||
}
|
||||
llm_apply_ca_bundle(curl);
|
||||
cst_curl_apply_ca(curl);
|
||||
char url[1024];
|
||||
size_t bl = strlen(api_base);
|
||||
while (bl && api_base[bl - 1] == '/')
|
||||
|
||||
Reference in New Issue
Block a user