Read entire file into malloc'd buffer. Returns NULL on error. */
| 3338 | |
| 3339 | /* Read entire file into malloc'd buffer. Returns NULL on error. */ |
| 3340 | static char *read_file_str(const char *path, size_t *out_len) { |
| 3341 | FILE *f = fopen(path, "r"); |
| 3342 | if (!f) { |
| 3343 | if (out_len) { |
| 3344 | *out_len = 0; |
| 3345 | } |
| 3346 | return NULL; |
| 3347 | } |
| 3348 | (void)fseek(f, 0, SEEK_END); |
| 3349 | long size = ftell(f); |
| 3350 | (void)fseek(f, 0, SEEK_SET); |
| 3351 | if (size < 0 || size > (long)CLI_MB_10 * CLI_MB_FACTOR) { /* cap at 10 MB */ |
| 3352 | (void)fclose(f); |
| 3353 | return NULL; |
| 3354 | } |
| 3355 | |
| 3356 | char *buf = malloc((size_t)size + CLI_SKIP_ONE); |
| 3357 | if (!buf) { |
| 3358 | (void)fclose(f); |
| 3359 | return NULL; |
| 3360 | } |
| 3361 | size_t nread = fread(buf, CLI_ELEM_SIZE, (size_t)size, f); |
| 3362 | (void)fclose(f); |
| 3363 | if (nread > (size_t)size) { |
| 3364 | nread = (size_t)size; |
| 3365 | } |
| 3366 | buf[nread] = '\0'; |
| 3367 | if (out_len) { |
| 3368 | *out_len = nread; |
| 3369 | } |
| 3370 | return buf; |
| 3371 | } |
| 3372 | |
| 3373 | static int ensure_parent_dir(const char *path) { |
| 3374 | if (!path || !path[0]) { |
no outgoing calls
no test coverage detected