| 317 | /* ── File utilities ───────────────────────────────────────────── */ |
| 318 | |
| 319 | int cbm_copy_file(const char *src, const char *dst) { |
| 320 | FILE *in = fopen(src, "rb"); |
| 321 | if (!in) { |
| 322 | return CLI_ERR; |
| 323 | } |
| 324 | |
| 325 | FILE *out = fopen(dst, "wb"); |
| 326 | if (!out) { |
| 327 | (void)fclose(in); |
| 328 | return CLI_ERR; |
| 329 | } |
| 330 | |
| 331 | char buf[CLI_BUF_8K]; |
| 332 | int err = 0; |
| 333 | while (!feof(in) && !ferror(in)) { |
| 334 | size_t n = fread(buf, CLI_ELEM_SIZE, sizeof(buf), in); |
| 335 | if (n == 0) { |
| 336 | break; |
| 337 | } |
| 338 | if (fwrite(buf, CLI_ELEM_SIZE, n, out) != n) { |
| 339 | err = CLI_TRUE; |
| 340 | break; |
| 341 | } |
| 342 | } |
| 343 | |
| 344 | if (err || ferror(in)) { |
| 345 | (void)fclose(in); |
| 346 | (void)fclose(out); |
| 347 | return CLI_ERR; |
| 348 | } |
| 349 | |
| 350 | (void)fclose(in); |
| 351 | int rc = fclose(out); |
| 352 | return rc == 0 ? 0 : CLI_ERR; |
| 353 | } |
| 354 | |
| 355 | /* Return true if two paths refer to the same on-disk file. Used to avoid |
| 356 | * copying the running binary onto itself during install (cbm_copy_file would |
no outgoing calls
no test coverage detected