diff --git a/libs/map/map_tests/bookmarks_test.cpp b/libs/map/map_tests/bookmarks_test.cpp index 61d44ed9d..31a9f4308 100644 --- a/libs/map/map_tests/bookmarks_test.cpp +++ b/libs/map/map_tests/bookmarks_test.cpp @@ -1029,9 +1029,9 @@ UNIT_CLASS_TEST(Runner, Bookmarks_SpecialXMLNames) BookmarkManager bmManager(BM_CALLBACKS); bmManager.EnableTestMode(true); - auto const file1Name = "file1"; + auto const fileNameFromMemory = ""; BookmarkManager::KMLDataCollection kmlDataCollection1; - kmlDataCollection1.emplace_back(file1Name /* filePath */, + kmlDataCollection1.emplace_back(fileNameFromMemory /* filePath */, LoadKmlData(MemReader(kmlString3, strlen(kmlString3)), KmlFileType::Text)); bmManager.CreateCategories(std::move(kmlDataCollection1)); @@ -1056,29 +1056,29 @@ UNIT_CLASS_TEST(Runner, Bookmarks_SpecialXMLNames) bmManager.GetEditSession().DeleteBmCategory(catId, true); - auto const file2Name = "file2"; + auto const fileNameOnDisk = "file1"; BookmarkManager::KMLDataCollection kmlDataCollection2; - kmlDataCollection2.emplace_back(file1Name /* filePath */, LoadKmlFile(fileNameTmp, GetActiveKmlFileType())); + kmlDataCollection2.emplace_back(fileNameOnDisk /* filePath */, LoadKmlFile(fileNameTmp, GetActiveKmlFileType())); bmManager.CreateCategories(std::move(kmlDataCollection2)); BookmarkManager::KMLDataCollection kmlDataCollection3; - kmlDataCollection3.emplace_back(file2Name /* filePath */, + kmlDataCollection3.emplace_back(fileNameFromMemory /* filePath */, LoadKmlData(MemReader(kmlString3, strlen(kmlString3)), KmlFileType::Text)); bmManager.CreateCategories(std::move(kmlDataCollection3)); TEST_EQUAL(bmManager.GetBmGroupsCount(), 2, ()); - auto const catId2 = bmManager.GetSortedBmGroupIdList().front(); - auto const catId3 = bmManager.GetSortedBmGroupIdList().back(); + auto const lastModifiedCatId = bmManager.GetSortedBmGroupIdList().front(); + auto const olderCatId = bmManager.GetSortedBmGroupIdList().back(); - TEST_EQUAL(bmManager.GetUserMarkIds(catId2).size(), 1, ()); - TEST_EQUAL(bmManager.GetCategoryName(catId2), expectedName, ()); - TEST_EQUAL(bmManager.GetCategoryFileName(catId2), file1Name, ()); - TEST_EQUAL(bmManager.GetCategoryFileName(catId3), file2Name, ()); + TEST_EQUAL(bmManager.GetUserMarkIds(lastModifiedCatId).size(), 1, ()); + TEST_EQUAL(bmManager.GetCategoryName(olderCatId), expectedName, ()); + TEST_EQUAL(bmManager.GetCategoryFileName(lastModifiedCatId), fileNameFromMemory, ()); + TEST_EQUAL(bmManager.GetCategoryFileName(olderCatId), fileNameOnDisk, ()); - auto const bmId1 = *bmManager.GetUserMarkIds(catId2).begin(); + auto const bmId1 = *bmManager.GetUserMarkIds(lastModifiedCatId).begin(); auto const * bm1 = bmManager.GetBookmark(bmId1); - auto const bmId2 = *bmManager.GetUserMarkIds(catId3).begin(); + auto const bmId2 = *bmManager.GetUserMarkIds(olderCatId).begin(); auto const * bm2 = bmManager.GetBookmark(bmId2); TEST(EqualBookmarks(*bm1, *bm2), ()); TEST_EQUAL(kml::GetDefaultStr(bm1->GetName()), "![X1]{X2}(X3)", ()); diff --git a/libs/platform/platform_android.cpp b/libs/platform/platform_android.cpp index 964602984..82ff39ed7 100644 --- a/libs/platform/platform_android.cpp +++ b/libs/platform/platform_android.cpp @@ -232,6 +232,9 @@ time_t Platform::GetFileCreationTime(std::string const & path) struct stat st; if (0 == stat(path.c_str(), &st)) return st.st_atim.tv_sec; + + LOG(LERROR, ("GetFileCreationTime stat failed for", path, "with error", strerror(errno))); + // TODO(AB): Refactor to return std::optional. return 0; } @@ -241,5 +244,8 @@ time_t Platform::GetFileModificationTime(std::string const & path) struct stat st; if (0 == stat(path.c_str(), &st)) return st.st_mtim.tv_sec; + + LOG(LERROR, ("GetFileModificationTime stat failed for", path, "with error", strerror(errno))); + // TODO(AB): Refactor to return std::optional. return 0; } diff --git a/libs/platform/platform_linux.cpp b/libs/platform/platform_linux.cpp index 27208fa1e..e2ab1dfcc 100644 --- a/libs/platform/platform_linux.cpp +++ b/libs/platform/platform_linux.cpp @@ -260,16 +260,30 @@ void Platform::GetSystemFontNames(FilesList & res) const // static time_t Platform::GetFileCreationTime(std::string const & path) { -// In older Linux versions there is no reliable way to get file creation time. -#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 28 + // In older Linux versions there is no reliable way to get file creation time with GLIBC. + // Musl supports statx since 2018. +#if !defined(__GLIBC__) || (__GLIBC__ >= 2 && __GLIBC_MINOR__ >= 28) struct statx st; if (0 == statx(AT_FDCWD, path.c_str(), 0, STATX_BTIME, &st)) - return st.stx_btime.tv_sec; + { + // Orbstack on MacOS returns zero birth time, see https://github.com/orbstack/orbstack/issues/2064 + if (st.stx_btime.tv_sec != 0) + return st.stx_btime.tv_sec; + + LOG(LWARNING, ("statx returned zero birth time for", path, + ", using the earliest time from access, modification or status change instead.")); + return std::min(st.stx_atime.tv_sec, std::min(st.stx_mtime.tv_sec, st.stx_ctime.tv_sec)); + } + + LOG(LERROR, ("GetFileCreationTime statx failed for", path, "with error", strerror(errno))); #else struct stat st; if (0 == stat(path.c_str(), &st)) return std::min(st.st_atim.tv_sec, st.st_mtim.tv_sec); + + LOG(LERROR, ("GetFileCreationTime stat failed for", path, "with error", strerror(errno))); #endif + // TODO(AB): Refactor to return std::optional. return 0; } @@ -279,5 +293,8 @@ time_t Platform::GetFileModificationTime(std::string const & path) struct stat st; if (0 == stat(path.c_str(), &st)) return st.st_mtim.tv_sec; + + LOG(LERROR, ("GetFileModificationTime stat failed for", path, "with error", strerror(errno))); + // TODO(AB): Refactor to return std::optional. return 0; } diff --git a/libs/platform/platform_mac.mm b/libs/platform/platform_mac.mm index 7a18a1348..ec5d74825 100644 --- a/libs/platform/platform_mac.mm +++ b/libs/platform/platform_mac.mm @@ -190,6 +190,9 @@ time_t Platform::GetFileCreationTime(std::string const & path) struct stat st; if (0 == stat(path.c_str(), &st)) return st.st_birthtimespec.tv_sec; + + LOG(LERROR, ("GetFileCreationTime stat failed for", path, "with error", strerror(errno))); + // TODO(AB): Refactor to return std::optional. return 0; } @@ -199,5 +202,8 @@ time_t Platform::GetFileModificationTime(std::string const & path) struct stat st; if (0 == stat(path.c_str(), &st)) return st.st_mtimespec.tv_sec; + + LOG(LERROR, ("GetFileModificationTime stat failed for", path, "with error", strerror(errno))); + // TODO(AB): Refactor to return std::optional. return 0; } diff --git a/libs/platform/platform_win.cpp b/libs/platform/platform_win.cpp index 75111f43a..7becc89e9 100644 --- a/libs/platform/platform_win.cpp +++ b/libs/platform/platform_win.cpp @@ -220,7 +220,10 @@ time_t GetFileTime(std::string const & path, FileTimeType fileTimeType) { HANDLE hFile = CreateFileA(path.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) - return 0; + { + LOG(LERROR, ("GetFileTime CreateFileA failed for", path, "with error", strerror(errno))); + return 0; // TODO(AB): Refactor to return std::optional. + } SCOPE_GUARD(autoClose, bind(&CloseHandle, hFile)); @@ -234,8 +237,11 @@ time_t GetFileTime(std::string const & path, FileTimeType fileTimeType) case FileTimeType::Modification: ftLastWrite = &ft; break; } - if (!GetFileTime(hFile, ftCreate, nullptr, ftLastWrite)) - return 0; + if (!::GetFileTime(hFile, ftCreate, nullptr, ftLastWrite)) + { + LOG(LERROR, ("GetFileTime ::GetFileTime failed for", path, "with error", strerror(errno))); + return 0; // TODO(AB): Refactor to return std::optional. + } ULARGE_INTEGER ull; ull.LowPart = ft.dwLowDateTime; @@ -247,12 +253,14 @@ time_t GetFileTime(std::string const & path, FileTimeType fileTimeType) // static time_t Platform::GetFileCreationTime(std::string const & path) { + // TODO(AB): Refactor to return std::optional. return GetFileTime(path, FileTimeType::Creation); } // static time_t Platform::GetFileModificationTime(std::string const & path) { + // TODO(AB): Refactor to return std::optional. return GetFileTime(path, FileTimeType::Modification); }