Download and verify before disruption, then activate under daemon locks. */
| 11296 | |
| 11297 | /* Download and verify before disruption, then activate under daemon locks. */ |
| 11298 | static int download_verify_install(const char *url, const char *ext, const char *os, |
| 11299 | const char *arch, bool want_ui, const char *bin_dest, |
| 11300 | const char *home, bool delete_indexes) { |
| 11301 | char tmp_archive[CLI_BUF_256]; |
| 11302 | int archive_path_length = |
| 11303 | snprintf(tmp_archive, sizeof(tmp_archive), "%s/cbm-update-XXXXXX", cbm_tmpdir()); |
| 11304 | if (archive_path_length <= 0 || (size_t)archive_path_length >= sizeof(tmp_archive)) { |
| 11305 | return CLI_TRUE; |
| 11306 | } |
| 11307 | int archive_descriptor = cbm_mkstemp(tmp_archive); |
| 11308 | if (archive_descriptor < 0) { |
| 11309 | return CLI_TRUE; |
| 11310 | } |
| 11311 | #ifdef _WIN32 |
| 11312 | int archive_close_status = _close(archive_descriptor); |
| 11313 | #else |
| 11314 | int archive_close_status = close(archive_descriptor); |
| 11315 | #endif |
| 11316 | if (archive_close_status != 0) { |
| 11317 | cbm_unlink(tmp_archive); |
| 11318 | return CLI_TRUE; |
| 11319 | } |
| 11320 | |
| 11321 | int rc = cbm_download_to_file(url, tmp_archive); |
| 11322 | if (rc != 0) { |
| 11323 | (void)fprintf(stderr, "error: download failed (exit %d)\n", rc); |
| 11324 | cbm_unlink(tmp_archive); |
| 11325 | return CLI_TRUE; |
| 11326 | } |
| 11327 | |
| 11328 | char archive_name[CLI_BUF_256]; |
| 11329 | /* Must match build_update_url: linux uses the static "-portable" asset. */ |
| 11330 | const char *portable = (strcmp(os, "linux") == 0) ? "-portable" : ""; |
| 11331 | snprintf(archive_name, sizeof(archive_name), "codebase-memory-mcp-%s%s-%s%s.%s", |
| 11332 | want_ui ? "ui-" : "", os, arch, portable, ext); |
| 11333 | /* Fail closed: install only a positively-verified download. A mismatch, |
| 11334 | * a missing checksum entry, or an unavailable hash tool (crc != 0) all |
| 11335 | * abort rather than install an unverified binary. */ |
| 11336 | int crc = verify_download_checksum(tmp_archive, archive_name); |
| 11337 | if (crc != 0) { |
| 11338 | (void)fprintf(stderr, "error: refusing to install an unverified download\n"); |
| 11339 | cbm_unlink(tmp_archive); |
| 11340 | return CLI_TRUE; |
| 11341 | } |
| 11342 | |
| 11343 | if (extract_and_install_binary((extract_install_args_t){ |
| 11344 | .tmp_archive = tmp_archive, |
| 11345 | .ext = ext, |
| 11346 | .bin_dest = bin_dest, |
| 11347 | .home = home, |
| 11348 | .delete_indexes = delete_indexes, |
| 11349 | }) != 0) { |
| 11350 | return CLI_TRUE; |
| 11351 | } |
| 11352 | return 0; |
| 11353 | } |
| 11354 | |
| 11355 | /* Select update variant. Returns 0=standard, 1=ui, -1=error. */ |
no test coverage detected