Read entire file into malloc'd buffer. Returns NULL on error. */
| 3143 | |
| 3144 | /* Read entire file into malloc'd buffer. Returns NULL on error. */ |
| 3145 | static char *read_file_str(const char *path, size_t *out_len) { |
| 3146 | FILE *f = fopen(path, "r"); |
| 3147 | if (!f) { |
| 3148 | if (out_len) { |
| 3149 | *out_len = 0; |
| 3150 | } |
| 3151 | return NULL; |
| 3152 | } |
| 3153 | (void)fseek(f, 0, SEEK_END); |
| 3154 | long size = ftell(f); |
| 3155 | (void)fseek(f, 0, SEEK_SET); |
| 3156 | if (size < 0 || size > (long)CLI_MB_10 * CLI_MB_FACTOR) { /* cap at 10 MB */ |
| 3157 | (void)fclose(f); |
| 3158 | return NULL; |
| 3159 | } |
| 3160 | |
| 3161 | char *buf = malloc((size_t)size + CLI_SKIP_ONE); |
| 3162 | if (!buf) { |
| 3163 | (void)fclose(f); |
| 3164 | return NULL; |
| 3165 | } |
| 3166 | size_t nread = fread(buf, CLI_ELEM_SIZE, (size_t)size, f); |
| 3167 | (void)fclose(f); |
| 3168 | if (nread > (size_t)size) { |
| 3169 | nread = (size_t)size; |
| 3170 | } |
| 3171 | buf[nread] = '\0'; |
| 3172 | if (out_len) { |
| 3173 | *out_len = nread; |
| 3174 | } |
| 3175 | return buf; |
| 3176 | } |
| 3177 | |
| 3178 | static int ensure_parent_dir(const char *path) { |
| 3179 | if (!path || !path[0]) { |
no outgoing calls
no test coverage detected