| 2472 | } |
| 2473 | |
| 2474 | DateTime FileSystem::GetCreationTime(StringView path) |
| 2475 | { |
| 2476 | if (path.empty()) return {}; |
| 2477 | |
| 2478 | DateTime date; |
| 2479 | #if defined(DEATH_TARGET_WINDOWS) |
| 2480 | SmallVector<wchar_t, MAX_PATH + 1> pathW(path.size() + 1); |
| 2481 | Utf8::ToUtf16(pathW.data(), std::int32_t(pathW.size()), path.data(), std::int32_t(path.size())); |
| 2482 | # if defined(DEATH_TARGET_WINDOWS_RT) |
| 2483 | HANDLE hFile = ::CreateFileFromAppW(pathW.data(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
| 2484 | # else |
| 2485 | HANDLE hFile = ::CreateFileW(pathW.data(), GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL); |
| 2486 | # endif |
| 2487 | FILETIME fileTime; |
| 2488 | if (::GetFileTime(hFile, &fileTime, nullptr, nullptr)) { |
| 2489 | date = DateTime(fileTime); |
| 2490 | } |
| 2491 | ::CloseHandle(hFile); |
| 2492 | #elif defined(DEATH_TARGET_APPLE) && defined(_DARWIN_FEATURE_64_BIT_INODE) |
| 2493 | auto nullTerminatedPath = String::nullTerminatedView(path); |
| 2494 | struct stat sb; |
| 2495 | if (::stat(nullTerminatedPath.data(), &sb) == 0) { |
| 2496 | date = DateTime(sb.st_birthtimespec.tv_sec); |
| 2497 | date.SetMillisecond(sb.st_birthtimespec.tv_nsec / 1000000); |
| 2498 | } |
| 2499 | #else |
| 2500 | auto nullTerminatedPath = String::nullTerminatedView(path); |
| 2501 | # if defined(DEATH_TARGET_ANDROID) |
| 2502 | if (AndroidAssetStream::TryGetAssetPath(nullTerminatedPath)) { |
| 2503 | return date; |
| 2504 | } |
| 2505 | # endif |
| 2506 | struct stat sb; |
| 2507 | if (::stat(nullTerminatedPath.data(), &sb) == 0) { |
| 2508 | // Creation time is not available on Linux, return the last change of inode instead |
| 2509 | date = DateTime(sb.st_ctime); |
| 2510 | } |
| 2511 | #endif |
| 2512 | return date; |
| 2513 | } |
| 2514 | |
| 2515 | DateTime FileSystem::GetLastModificationTime(StringView path) |
| 2516 | { |