| 406 | #endif |
| 407 | |
| 408 | static int toml_read_file(const char *path, char **out_data, size_t *out_len, |
| 409 | toml_file_snapshot_t *snapshot_out) { |
| 410 | if (!path || !out_data || !out_len || !snapshot_out) { |
| 411 | return TOML_EDIT_ERR; |
| 412 | } |
| 413 | *out_data = NULL; |
| 414 | *out_len = 0; |
| 415 | memset(snapshot_out, 0, sizeof(*snapshot_out)); |
| 416 | |
| 417 | #ifdef _WIN32 |
| 418 | wchar_t *wide_path = cbm_utf8_to_wide(path); |
| 419 | if (!wide_path) { |
| 420 | return TOML_EDIT_ERR; |
| 421 | } |
| 422 | HANDLE handle = CreateFileW( |
| 423 | wide_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
| 424 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| 425 | free(wide_path); |
| 426 | if (handle == INVALID_HANDLE_VALUE) { |
| 427 | DWORD error = GetLastError(); |
| 428 | if (error != ERROR_FILE_NOT_FOUND && error != ERROR_PATH_NOT_FOUND) { |
| 429 | return TOML_EDIT_ERR; |
| 430 | } |
| 431 | char *empty = (char *)malloc(1); |
| 432 | if (!empty) { |
| 433 | return TOML_EDIT_ERR; |
| 434 | } |
| 435 | empty[0] = '\0'; |
| 436 | *out_data = empty; |
| 437 | return TOML_EDIT_OK; |
| 438 | } |
| 439 | toml_file_snapshot_t before; |
| 440 | if (toml_snapshot_from_handle(handle, &before) != TOML_EDIT_OK) { |
| 441 | CloseHandle(handle); |
| 442 | return TOML_EDIT_ERR; |
| 443 | } |
| 444 | size_t size = (size_t)before.size; |
| 445 | char *data = (char *)malloc(size + 1U); |
| 446 | if (!data) { |
| 447 | CloseHandle(handle); |
| 448 | return TOML_EDIT_ERR; |
| 449 | } |
| 450 | DWORD read_count = 0U; |
| 451 | BOOL read_ok = ReadFile(handle, data, (DWORD)size, &read_count, NULL); |
| 452 | toml_file_snapshot_t after; |
| 453 | int after_result = toml_snapshot_from_handle(handle, &after); |
| 454 | BOOL close_ok = CloseHandle(handle); |
| 455 | if (!read_ok || read_count != (DWORD)size || after_result != TOML_EDIT_OK || !close_ok || |
| 456 | !toml_snapshot_equal(&before, &after)) { |
| 457 | free(data); |
| 458 | return TOML_EDIT_ERR; |
| 459 | } |
| 460 | #else |
| 461 | #ifndef O_NOFOLLOW |
| 462 | return TOML_EDIT_ERR; |
| 463 | #else |
| 464 | int flags = O_RDONLY | O_NOFOLLOW | O_NONBLOCK; |
| 465 | #ifdef O_CLOEXEC |
no test coverage detected