| 2442 | } |
| 2443 | |
| 2444 | unsigned char *cbm_extract_binary_from_targz(const unsigned char *data, int data_len, |
| 2445 | int *out_len) { |
| 2446 | if (!data || data_len <= 0 || !out_len) { |
| 2447 | return NULL; |
| 2448 | } |
| 2449 | |
| 2450 | size_t total = 0; |
| 2451 | unsigned char *decompressed = gzip_decompress(data, data_len, &total); |
| 2452 | if (!decompressed) { |
| 2453 | return NULL; |
| 2454 | } |
| 2455 | |
| 2456 | /* Parse tar: find entry starting with "codebase-memory-mcp" */ |
| 2457 | size_t pos = 0; |
| 2458 | while (pos + TAR_BLOCK_SIZE <= total) { |
| 2459 | const unsigned char *hdr = decompressed + pos; |
| 2460 | |
| 2461 | if (is_tar_end_of_archive(hdr)) { |
| 2462 | break; |
| 2463 | } |
| 2464 | |
| 2465 | char name[TAR_NAME_LEN] = {0}; |
| 2466 | memcpy(name, hdr, TAR_NAME_LEN - SKIP_ONE); |
| 2467 | char size_str[TAR_SIZE_LEN] = {0}; |
| 2468 | memcpy(size_str, hdr + TAR_SIZE_OFFSET, TAR_SIZE_LEN - SKIP_ONE); |
| 2469 | long file_size = strtol(size_str, NULL, OCTAL_BASE); |
| 2470 | char typeflag = (char)hdr[TAR_TYPE_OFFSET]; |
| 2471 | pos += TAR_BLOCK_SIZE; |
| 2472 | |
| 2473 | unsigned char *found = tar_try_extract_binary(hdr, typeflag, name, decompressed, pos, |
| 2474 | file_size, total, out_len); |
| 2475 | if (found) { |
| 2476 | free(decompressed); |
| 2477 | return found; |
| 2478 | } |
| 2479 | |
| 2480 | size_t blocks = ((size_t)file_size + TAR_BLOCK_MASK) / TAR_BLOCK_SIZE; |
| 2481 | pos += blocks * TAR_BLOCK_SIZE; |
| 2482 | } |
| 2483 | |
| 2484 | free(decompressed); |
| 2485 | return NULL; /* binary not found */ |
| 2486 | } |
| 2487 | |
| 2488 | /* ── Zip extraction (in-memory, replaces external unzip) ──────── */ |
| 2489 |
no test coverage detected