| 43 | /* ── Load ────────────────────────────────────────────────────── */ |
| 44 | |
| 45 | static char *config_read_file(const char *path, size_t *length_out, bool *opened_out) { |
| 46 | if (length_out) { |
| 47 | *length_out = 0; |
| 48 | } |
| 49 | if (opened_out) { |
| 50 | *opened_out = false; |
| 51 | } |
| 52 | if (!path || !length_out || !opened_out) { |
| 53 | return NULL; |
| 54 | } |
| 55 | #ifdef _WIN32 |
| 56 | wchar_t *wide_path = cbm_path_to_wide(path); |
| 57 | if (!wide_path) { |
| 58 | return NULL; |
| 59 | } |
| 60 | HANDLE file = CreateFileW(wide_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_DELETE, NULL, |
| 61 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); |
| 62 | free(wide_path); |
| 63 | if (file == INVALID_HANDLE_VALUE) { |
| 64 | return NULL; |
| 65 | } |
| 66 | *opened_out = true; |
| 67 | LARGE_INTEGER size; |
| 68 | if (!GetFileSizeEx(file, &size) || size.QuadPart <= 0 || size.QuadPart > 4096) { |
| 69 | (void)CloseHandle(file); |
| 70 | return NULL; |
| 71 | } |
| 72 | size_t length = (size_t)size.QuadPart; |
| 73 | char *buffer = malloc(length + 1U); |
| 74 | DWORD read_length = 0; |
| 75 | bool read_ok = buffer && ReadFile(file, buffer, (DWORD)length, &read_length, NULL) && |
| 76 | read_length == (DWORD)length; |
| 77 | (void)CloseHandle(file); |
| 78 | if (!read_ok) { |
| 79 | free(buffer); |
| 80 | return NULL; |
| 81 | } |
| 82 | #else |
| 83 | FILE *file = cbm_fopen(path, "rb"); |
| 84 | if (!file) { |
| 85 | return NULL; |
| 86 | } |
| 87 | *opened_out = true; |
| 88 | if (fseek(file, 0, SEEK_END) != 0) { |
| 89 | (void)fclose(file); |
| 90 | return NULL; |
| 91 | } |
| 92 | long file_length = ftell(file); |
| 93 | if (file_length <= 0 || file_length > 4096 || fseek(file, 0, SEEK_SET) != 0) { |
| 94 | (void)fclose(file); |
| 95 | return NULL; |
| 96 | } |
| 97 | size_t length = (size_t)file_length; |
| 98 | char *buffer = malloc(length + 1U); |
| 99 | bool read_ok = buffer && fread(buffer, 1, length, file) == length; |
| 100 | (void)fclose(file); |
| 101 | if (!read_ok) { |
| 102 | free(buffer); |
no test coverage detected