| 1377 | #endif |
| 1378 | |
| 1379 | static int jl_read_file(const char *path, char **content_out, size_t *length_out, bool *missing_out, |
| 1380 | jl_file_snapshot_t *snapshot_out) { |
| 1381 | *content_out = NULL; |
| 1382 | *length_out = 0; |
| 1383 | *missing_out = false; |
| 1384 | memset(snapshot_out, 0, sizeof(*snapshot_out)); |
| 1385 | #ifdef _WIN32 |
| 1386 | wchar_t *wide_path = cbm_utf8_to_wide(path); |
| 1387 | if (!wide_path) { |
| 1388 | return -1; |
| 1389 | } |
| 1390 | HANDLE handle = CreateFileW( |
| 1391 | wide_path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, |
| 1392 | OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OPEN_REPARSE_POINT, NULL); |
| 1393 | free(wide_path); |
| 1394 | if (handle == INVALID_HANDLE_VALUE) { |
| 1395 | DWORD error = GetLastError(); |
| 1396 | if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { |
| 1397 | *missing_out = true; |
| 1398 | return 0; |
| 1399 | } |
| 1400 | return -1; |
| 1401 | } |
| 1402 | jl_file_snapshot_t before; |
| 1403 | if (jl_snapshot_from_handle(handle, &before) != 0) { |
| 1404 | CloseHandle(handle); |
| 1405 | return -1; |
| 1406 | } |
| 1407 | size_t length = (size_t)before.size; |
| 1408 | char *content = malloc(length + 1U); |
| 1409 | if (!content) { |
| 1410 | CloseHandle(handle); |
| 1411 | return -1; |
| 1412 | } |
| 1413 | DWORD read_count = 0U; |
| 1414 | BOOL read_ok = ReadFile(handle, content, (DWORD)length, &read_count, NULL); |
| 1415 | jl_file_snapshot_t after; |
| 1416 | int after_result = jl_snapshot_from_handle(handle, &after); |
| 1417 | BOOL close_ok = CloseHandle(handle); |
| 1418 | if (!read_ok || read_count != (DWORD)length || after_result != 0 || !close_ok || |
| 1419 | !jl_snapshot_state_equal(&before, &after)) { |
| 1420 | free(content); |
| 1421 | return -1; |
| 1422 | } |
| 1423 | #else |
| 1424 | #ifndef O_NOFOLLOW |
| 1425 | (void)path; |
| 1426 | return -1; |
| 1427 | #else |
| 1428 | int flags = O_RDONLY | O_NOFOLLOW | O_NONBLOCK; |
| 1429 | #ifdef O_CLOEXEC |
| 1430 | flags |= O_CLOEXEC; |
| 1431 | #endif |
| 1432 | int descriptor = open(path, flags); |
| 1433 | if (descriptor < 0) { |
| 1434 | if (errno == ENOENT) { |
| 1435 | struct stat path_state; |
| 1436 | if (lstat(path, &path_state) == 0 || errno != ENOENT) { |
no test coverage detected