Title: [277158] trunk
Revision
277158
Author
cdu...@apple.com
Date
2021-05-06 22:00:39 -0700 (Thu, 06 May 2021)

Log Message

Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
https://bugs.webkit.org/show_bug.cgi?id=225362

Reviewed by Darin Adler.

Source/_javascript_Core:

Build fix.

* Configurations/_javascript_Core.xcconfig:

Source/WTF:

Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
and get rid of platform-specific implementations.

* wtf/FileSystem.cpp:
(WTF::FileSystemImpl::toWallTime):
(WTF::FileSystemImpl::getFileModificationTime):
(WTF::FileSystemImpl::fileMetadata):
* wtf/FileSystem.h:
* wtf/glib/FileSystemGlib.cpp:
* wtf/posix/FileSystemPOSIX.cpp:
* wtf/win/FileSystemWin.cpp:

Tools:

Add API test coverage.

* TestWebKitAPI/Tests/WTF/FileSystem.cpp:
(TestWebKitAPI::TEST_F):
(TestWebKitAPI::runGetFileModificationTimeTest):

LayoutTests:

Add 0 to the list of allowed values for the size of a directory in the data transfer API as the result
is implementation-specific. On macOS, we used to return 256 on apfs and 272 on HFS+. We now return 0,
which is what Firefox does.

* editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt:
* editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html:
* fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt:
* fast/forms/file/entries-api/drag-folder-webkitEntries.html:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (277157 => 277158)


--- trunk/LayoutTests/ChangeLog	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/ChangeLog	2021-05-07 05:00:39 UTC (rev 277158)
@@ -1,3 +1,19 @@
+2021-05-06  Chris Dumez  <cdu...@apple.com>
+
+        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
+        https://bugs.webkit.org/show_bug.cgi?id=225362
+
+        Reviewed by Darin Adler.
+
+        Add 0 to the list of allowed values for the size of a directory in the data transfer API as the result
+        is implementation-specific. On macOS, we used to return 256 on apfs and 272 on HFS+. We now return 0,
+        which is what Firefox does.
+
+        * editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt:
+        * editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html:
+        * fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt:
+        * fast/forms/file/entries-api/drag-folder-webkitEntries.html:
+
 2021-05-06  Robert Jenner  <jen...@apple.com>
 
         [ macOS wk2 ] http/wpt/mediarecorder/set-srcObject-MediaStream-Blob.html (layout-test) is a flaky text failure

Modified: trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt (277157 => 277158)


--- trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt	2021-05-07 05:00:39 UTC (rev 277158)
@@ -16,7 +16,7 @@
 PASS secondDataTransferItem.kind is "file"
 PASS secondDataTransferItem.type is ""
 PASS secondFile.name is "testFiles"
-PASS secondFile.size is one of `272`, and `256`
+PASS secondFile.size is one of `0`,`272`, and `256`
 PASS secondFile.type is ""
 PASS secondEntry.isDirectory is true
 PASS secondEntry.isFile is false

Modified: trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html (277157 => 277158)


--- trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html	2021-05-07 05:00:39 UTC (rev 277158)
@@ -37,7 +37,7 @@
     shouldBeEqualToString("secondDataTransferItem.type", "");
     secondFile = secondDataTransferItem.getAsFile();
     shouldBeEqualToString("secondFile.name", "testFiles");
-    shouldBeOneOfValues("secondFile.size", [272, 256]); // Chrome returns folder size, Firefox returns 0. 256 in APFS, 272 in HFS+ 
+    shouldBeOneOfValues("secondFile.size", [0, 272, 256]); // Chrome returns folder size, Firefox returns 0. 256 in APFS, 272 in HFS+ 
     shouldBeEqualToString("secondFile.type", "");
 
     secondEntry = secondDataTransferItem.webkitGetAsEntry();

Modified: trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt (277157 => 277158)


--- trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt	2021-05-07 05:00:39 UTC (rev 277158)
@@ -16,7 +16,7 @@
 PASS files[0].size is 5
 PASS files[0].type is "text/plain"
 PASS files[1].name is "testFiles"
-PASS files[1].size is one of `272`, and `256`
+PASS files[1].size is one of `0`,`272`, and `256`
 PASS files[1].type is ""
 PASS successfullyParsed is true
 

Modified: trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries.html (277157 => 277158)


--- trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries.html	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries.html	2021-05-07 05:00:39 UTC (rev 277158)
@@ -48,7 +48,7 @@
     shouldBeEqualToString("files[0].type", "text/plain");
 
     shouldBeEqualToString("files[1].name", "testFiles");
-    shouldBeOneOfValues("files[1].size", [272, 256]);
+    shouldBeOneOfValues("files[1].size", [0, 272, 256]);
     shouldBeEqualToString("files[1].type", "");
 
     finishJSTest();

Modified: trunk/LayoutTests/resources/js-test.js (277157 => 277158)


--- trunk/LayoutTests/resources/js-test.js	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/LayoutTests/resources/js-test.js	2021-05-07 05:00:39 UTC (rev 277158)
@@ -311,7 +311,7 @@
         testFailed(_a + " should be one of " + stringifiedValues + ". Threw exception " + _exception);
     else {
         var matchedValue = _values.find(function (value) { return isResultCorrect(_av, value); });
-        if (matchedValue) {
+        if (matchedValue !== undefined) {
             testPassed(_a + " is one of " + stringifiedValues);
         } else {
             testFailed(_a + " should be one of " + stringifiedValues + ". Was " + stringify(_av) + ".");

Modified: trunk/Source/_javascript_Core/ChangeLog (277157 => 277158)


--- trunk/Source/_javascript_Core/ChangeLog	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/_javascript_Core/ChangeLog	2021-05-07 05:00:39 UTC (rev 277158)
@@ -1,3 +1,14 @@
+2021-05-06  Chris Dumez  <cdu...@apple.com>
+
+        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
+        https://bugs.webkit.org/show_bug.cgi?id=225362
+
+        Reviewed by Darin Adler.
+
+        Build fix.
+
+        * Configurations/_javascript_Core.xcconfig:
+
 2021-05-06  Eleni Maria Stea  <es...@igalia.com>
 
         Removed the assertion m_numParameters >= 0, it is always true as

Modified: trunk/Source/_javascript_Core/Configurations/_javascript_Core.xcconfig (277157 => 277158)


--- trunk/Source/_javascript_Core/Configurations/_javascript_Core.xcconfig	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/_javascript_Core/Configurations/_javascript_Core.xcconfig	2021-05-07 05:00:39 UTC (rev 277158)
@@ -27,7 +27,7 @@
 MODULEMAP_FILE = $(SRCROOT)/_javascript_Core.modulemap;
 
 // Prevent C++ standard library operator new, delete and their related exception types from being exported as weak symbols.
-OTHER_LDFLAGS_HIDE_SYMBOLS = -Wl,-unexported_symbol,__ZTISt9bad_alloc -Wl,-unexported_symbol,__ZTISt9exception -Wl,-unexported_symbol,__ZTSSt9bad_alloc -Wl,-unexported_symbol,__ZTSSt9exception -Wl,-unexported_symbol,__ZdlPvS_ -Wl,-unexported_symbol,__ZnwmPv -Wl,-unexported_symbol,__ZNKSt3__18functionIFvvEEclEv -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEEC1EOS2_ -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEEC2EOS2_ -Wl,-unexported_symbol,__ZNKSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEEclES3_S5_ -Wl,-unexported_symbol,__ZNSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEED1Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEED2Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEED1Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEED2Ev -Wl,-unexported_symbol,__ZTVNSt3__117bad_function_callE -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIPKcS4_cLb1EE11__range_endES4
 _ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIPKcS4_cLb1EE13__range_beginES4_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE14__append_rangeIPKcEENS_9enable_ifIXsr27__is_cpp17_forward_iteratorIT_EE5valueEvE4typeERNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES8_S8_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE15__append_sourceIPKcEEvRNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKT_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE14__append_rangeIPKcEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeERNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES8_S8_ -Wl,-unexported_symbol,__ZNKSt3__14__fs10filesystem18directory_iteratordeEv -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem18directory_iteratorppEv -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIA10_cPccLb1EE11__range_endEPKc -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem2
 4__is_pathable_char_arrayIA10_cPccLb1EE13__range_beginEPKc -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem4pathdVERKS2_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE15__append_sourceIA10_cEEvRNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKT_;
+OTHER_LDFLAGS_HIDE_SYMBOLS = -Wl,-unexported_symbol,__ZTISt9bad_alloc -Wl,-unexported_symbol,__ZTISt9exception -Wl,-unexported_symbol,__ZTSSt9bad_alloc -Wl,-unexported_symbol,__ZTSSt9exception -Wl,-unexported_symbol,__ZdlPvS_ -Wl,-unexported_symbol,__ZnwmPv -Wl,-unexported_symbol,__ZNKSt3__18functionIFvvEEclEv -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEEC1EOS2_ -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEEC2EOS2_ -Wl,-unexported_symbol,__ZNKSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEEclES3_S5_ -Wl,-unexported_symbol,__ZNSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEED1Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvRN3JSC17BytecodeGeneratorEPNS1_10RegisterIDEEED2Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEED1Ev -Wl,-unexported_symbol,__ZNSt3__18functionIFvvEED2Ev -Wl,-unexported_symbol,__ZTVNSt3__117bad_function_callE -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIPKcS4_cLb1EE11__range_endES4_
  -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIPKcS4_cLb1EE13__range_beginES4_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE14__append_rangeIPKcEENS_9enable_ifIXsr27__is_cpp17_forward_iteratorIT_EE5valueEvE4typeERNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES8_S8_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE15__append_sourceIPKcEEvRNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKT_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE14__append_rangeIPKcEENS_9enable_ifIXsr21__is_forward_iteratorIT_EE5valueEvE4typeERNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEES8_S8_ -Wl,-unexported_symbol,__ZNKSt3__14__fs10filesystem18directory_iteratordeEv -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem18directory_iteratorppEv -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__is_pathable_char_arrayIA10_cPccLb1EE11__range_endEPKc -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24
 __is_pathable_char_arrayIA10_cPccLb1EE13__range_beginEPKc -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem4pathdVERKS2_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem8_PathCVTIcE15__append_sourceIA10_cEEvRNS_12basic_stringIcNS_11char_traitsIcEENS_9allocatorIcEEEERKT_ -Wl,-unexported_symbol,__ZNSt3__14__fs10filesystem24__throw_filesystem_errorIJRPKcRKNS1_4pathERKNS_10error_codeEEEEvDpOT_;
 
 OTHER_LDFLAGS_BASE = $(OTHER_LDFLAGS_HIDE_SYMBOLS) -force_load "$(BUILT_PRODUCTS_DIR)/DerivedSources/_javascript_Core/libWTF.a";
 OTHER_LDFLAGS[sdk=embedded*] = $(inherited) $(OTHER_LDFLAGS_BASE);

Modified: trunk/Source/WTF/ChangeLog (277157 => 277158)


--- trunk/Source/WTF/ChangeLog	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/WTF/ChangeLog	2021-05-07 05:00:39 UTC (rev 277158)
@@ -1,3 +1,22 @@
+2021-05-06  Chris Dumez  <cdu...@apple.com>
+
+        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
+        https://bugs.webkit.org/show_bug.cgi?id=225362
+
+        Reviewed by Darin Adler.
+
+        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
+        and get rid of platform-specific implementations.
+
+        * wtf/FileSystem.cpp:
+        (WTF::FileSystemImpl::toWallTime):
+        (WTF::FileSystemImpl::getFileModificationTime):
+        (WTF::FileSystemImpl::fileMetadata):
+        * wtf/FileSystem.h:
+        * wtf/glib/FileSystemGlib.cpp:
+        * wtf/posix/FileSystemPOSIX.cpp:
+        * wtf/win/FileSystemWin.cpp:
+
 2021-05-06  Yoshiaki Jitsukawa  <yoshiaki.jitsuk...@sony.com>
 
         [OpenSSL] Implement CryptoAlgorithmRSA*

Modified: trunk/Source/WTF/wtf/FileSystem.cpp (277157 => 277158)


--- trunk/Source/WTF/wtf/FileSystem.cpp	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/WTF/wtf/FileSystem.cpp	2021-05-07 05:00:39 UTC (rev 277158)
@@ -37,6 +37,7 @@
 
 #if !OS(WINDOWS)
 #include <sys/mman.h>
+#include <sys/param.h>
 #include <sys/stat.h>
 #endif
 
@@ -105,6 +106,43 @@
     return false;
 }
 
+template<typename ClockType, typename = void> struct has_to_time_t : std::false_type { };
+template<typename ClockType> struct has_to_time_t<ClockType, std::void_t<
+    std::enable_if_t<std::is_same_v<std::time_t, decltype(ClockType::to_time_t(std::filesystem::file_time_type()))>>
+>> : std::true_type { };
+
+template <typename FileTimeType>
+typename std::enable_if_t<has_to_time_t<typename FileTimeType::clock>::value, std::time_t> toTimeT(FileTimeType fileTime)
+{
+    return decltype(fileTime)::clock::to_time_t(fileTime);
+}
+
+template <typename FileTimeType>
+typename std::enable_if_t<!has_to_time_t<typename FileTimeType::clock>::value, std::time_t> toTimeT(FileTimeType fileTime)
+{
+    return std::chrono::system_clock::to_time_t(std::chrono::time_point_cast<std::chrono::system_clock::duration>(fileTime - decltype(fileTime)::clock::now() + std::chrono::system_clock::now()));
+}
+
+static WallTime toWallTime(std::filesystem::file_time_type fileTime)
+{
+    // FIXME: Use std::chrono::file_clock::to_sys() once we can use C++20.
+    return WallTime::fromRawSeconds(toTimeT(fileTime));
+}
+
+static std::filesystem::path resolveSymlinks(std::filesystem::path path, std::error_code& ec)
+{
+#ifdef MAXSYMLINKS
+    static constexpr unsigned maxSymlinkDepth = MAXSYMLINKS;
+#else
+    static constexpr unsigned maxSymlinkDepth = 40;
+#endif
+
+    unsigned currentDepth = 0;
+    while (++currentDepth <= maxSymlinkDepth && !ec && std::filesystem::is_symlink(path, ec))
+        path = std::filesystem::read_symlink(path, ec);
+    return path;
+}
+
 String encodeForFileName(const String& inputString)
 {
     unsigned length = inputString.length();
@@ -623,5 +661,65 @@
     return !ec;
 }
 
+Optional<WallTime> getFileModificationTime(const String& path)
+{
+    std::error_code ec;
+    auto modificationTime = std::filesystem::last_write_time(fileSystemRepresentation(path).data(), ec);
+    if (ec)
+        return WTF::nullopt;
+    return toWallTime(modificationTime);
+}
+
+static Optional<FileMetadata> fileMetadataPotentiallyFollowingSymlinks(const String& path, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
+{
+    if (path.isEmpty())
+        return WTF::nullopt;
+
+    std::filesystem::path fsPath = fileSystemRepresentation(path).data();
+
+    std::error_code ec;
+    if (shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes && std::filesystem::is_symlink(fsPath, ec)) {
+        fsPath = resolveSymlinks(fsPath, ec);
+        if (ec)
+            return WTF::nullopt;
+    }
+
+    ec = { };
+    std::filesystem::directory_entry entry(fsPath, ec);
+    if (ec)
+        return WTF::nullopt;
+
+    auto modificationTime = toWallTime(entry.last_write_time(ec));
+
+    // Note that the result of attempting to determine the size of a directory is implementation-defined.
+    auto fileSize = entry.file_size(ec);
+    if (ec)
+        fileSize = 0;
+
+#if OS(UNIX)
+    std::filesystem::path::string_type filename = fsPath.filename();
+    bool isHidden = !filename.empty() && filename[0] == '.';
+#else
+    bool isHidden = false;
+#endif
+    FileMetadata::Type type = FileMetadata::Type::File;
+    if (entry.is_symlink(ec))
+        type = FileMetadata::Type::SymbolicLink;
+    else if (entry.is_directory(ec))
+        type = FileMetadata::Type::Directory;
+
+    return FileMetadata { modificationTime, static_cast<long long>(fileSize), isHidden, type };
+}
+
+Optional<FileMetadata> fileMetadata(const String& path)
+{
+    return fileMetadataPotentiallyFollowingSymlinks(path, ShouldFollowSymbolicLinks::No);
+}
+
+Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
+{
+    return fileMetadataPotentiallyFollowingSymlinks(path, ShouldFollowSymbolicLinks::Yes);
+}
+
 } // namespace FileSystemImpl
 } // namespace WTF

Modified: trunk/Source/WTF/wtf/glib/FileSystemGlib.cpp (277157 => 277158)


--- trunk/Source/WTF/wtf/glib/FileSystemGlib.cpp	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/WTF/wtf/glib/FileSystemGlib.cpp	2021-05-07 05:00:39 UTC (rev 277158)
@@ -152,51 +152,6 @@
     return WTF::nullopt;
 }
 
-Optional<WallTime> getFileModificationTime(const String& path)
-{
-    GStatBuf statResult;
-    if (!getFileStat(path, &statResult))
-        return WTF::nullopt;
-
-    return WallTime::fromRawSeconds(statResult.st_mtime);
-}
-
-static FileMetadata::Type toFileMetataType(GStatBuf statResult)
-{
-    if (S_ISDIR(statResult.st_mode))
-        return FileMetadata::Type::Directory;
-    if (S_ISLNK(statResult.st_mode))
-        return FileMetadata::Type::SymbolicLink;
-    return FileMetadata::Type::File;
-}
-
-static Optional<FileMetadata> fileMetadataUsingFunction(const String& path, bool (*statFunc)(const String&, GStatBuf*))
-{
-    GStatBuf statResult;
-    if (!statFunc(path, &statResult))
-        return WTF::nullopt;
-
-    String filename = pathGetFileName(path);
-    bool isHidden = !filename.isEmpty() && filename[0] == '.';
-
-    return FileMetadata {
-        WallTime::fromRawSeconds(statResult.st_mtime),
-        statResult.st_size,
-        isHidden,
-        toFileMetataType(statResult)
-    };
-}
-
-Optional<FileMetadata> fileMetadata(const String& path)
-{
-    return fileMetadataUsingFunction(path, &getFileLStat);
-}
-
-Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
-{
-    return fileMetadataUsingFunction(path, &getFileStat);
-}
-
 String pathByAppendingComponent(const String& path, const String& component)
 {
     if (path.endsWith(G_DIR_SEPARATOR_S))

Modified: trunk/Source/WTF/wtf/posix/FileSystemPOSIX.cpp (277157 => 277158)


--- trunk/Source/WTF/wtf/posix/FileSystemPOSIX.cpp	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/WTF/wtf/posix/FileSystemPOSIX.cpp	2021-05-07 05:00:39 UTC (rev 277158)
@@ -186,61 +186,6 @@
 #endif
 }
 
-Optional<WallTime> getFileModificationTime(const String& path)
-{
-    CString fsRep = fileSystemRepresentation(path);
-
-    if (!fsRep.data() || fsRep.data()[0] == '\0')
-        return WTF::nullopt;
-
-    struct stat fileInfo;
-
-    if (stat(fsRep.data(), &fileInfo))
-        return WTF::nullopt;
-
-    return WallTime::fromRawSeconds(fileInfo.st_mtime);
-}
-
-static FileMetadata::Type toFileMetataType(struct stat fileInfo)
-{
-    if (S_ISDIR(fileInfo.st_mode))
-        return FileMetadata::Type::Directory;
-    if (S_ISLNK(fileInfo.st_mode))
-        return FileMetadata::Type::SymbolicLink;
-    return FileMetadata::Type::File;
-}
-
-static Optional<FileMetadata> fileMetadataUsingFunction(const String& path, int (*statFunc)(const char*, struct stat*))
-{
-    CString fsRep = fileSystemRepresentation(path);
-
-    if (!fsRep.data() || fsRep.data()[0] == '\0')
-        return WTF::nullopt;
-
-    struct stat fileInfo;
-    if (statFunc(fsRep.data(), &fileInfo))
-        return WTF::nullopt;
-
-    String filename = pathGetFileName(path);
-    bool isHidden = !filename.isEmpty() && filename[0] == '.';
-    return FileMetadata {
-        WallTime::fromRawSeconds(fileInfo.st_mtime),
-        fileInfo.st_size,
-        isHidden,
-        toFileMetataType(fileInfo)
-    };
-}
-
-Optional<FileMetadata> fileMetadata(const String& path)
-{
-    return fileMetadataUsingFunction(path, &lstat);
-}
-
-Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
-{
-    return fileMetadataUsingFunction(path, &stat);
-}
-
 String pathByAppendingComponent(const String& path, const String& component)
 {
     if (path.endsWith('/'))

Modified: trunk/Source/WTF/wtf/win/FileSystemWin.cpp (277157 => 277158)


--- trunk/Source/WTF/wtf/win/FileSystemWin.cpp	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Source/WTF/wtf/win/FileSystemWin.cpp	2021-05-07 05:00:39 UTC (rev 277158)
@@ -114,17 +114,6 @@
     return getFileSizeFromByHandleFileInformationStructure(fileInformation, size);
 }
 
-Optional<WallTime> getFileModificationTime(const String& path)
-{
-    WIN32_FIND_DATAW findData;
-    if (!getFindData(path, findData))
-        return WTF::nullopt;
-
-    time_t time = 0;
-    getFileModificationTimeFromFindData(findData, time);
-    return WallTime::fromRawSeconds(time);
-}
-
 Optional<WallTime> getFileCreationTime(const String& path)
 {
     WIN32_FIND_DATAW findData;
@@ -154,63 +143,6 @@
     return String::adopt(WTFMove(buffer));
 }
 
-static inline bool isSymbolicLink(WIN32_FIND_DATAW findData)
-{
-    return findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
-}
-
-static FileMetadata::Type toFileMetadataType(WIN32_FIND_DATAW findData)
-{
-    if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
-        return FileMetadata::Type::Directory;
-    if (isSymbolicLink(findData))
-        return FileMetadata::Type::SymbolicLink;
-    return FileMetadata::Type::File;
-}
-
-static Optional<FileMetadata> findDataToFileMetadata(WIN32_FIND_DATAW findData)
-{
-    long long length;
-    if (!getFileSizeFromFindData(findData, length))
-        return WTF::nullopt;
-
-    time_t modificationTime;
-    getFileModificationTimeFromFindData(findData, modificationTime);
-
-    return FileMetadata {
-        WallTime::fromRawSeconds(modificationTime),
-        length,
-        static_cast<bool>(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN),
-        toFileMetadataType(findData)
-    };
-}
-
-Optional<FileMetadata> fileMetadata(const String& path)
-{
-    WIN32_FIND_DATAW findData;
-    if (!getFindData(path, findData))
-        return WTF::nullopt;
-
-    return findDataToFileMetadata(findData);
-}
-
-Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
-{
-    WIN32_FIND_DATAW findData;
-    if (!getFindData(path, findData))
-        return WTF::nullopt;
-
-    if (isSymbolicLink(findData)) {
-        String targetPath = getFinalPathName(path);
-        if (targetPath.isNull())
-            return WTF::nullopt;
-        if (!getFindData(targetPath, findData))
-            return WTF::nullopt;
-    }
-
-    return findDataToFileMetadata(findData);
-}
-
 String pathByAppendingComponent(const String& path, const String& component)
 {
     Vector<UChar> buffer(MAX_PATH);

Modified: trunk/Tools/ChangeLog (277157 => 277158)


--- trunk/Tools/ChangeLog	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Tools/ChangeLog	2021-05-07 05:00:39 UTC (rev 277158)
@@ -1,3 +1,16 @@
+2021-05-06  Chris Dumez  <cdu...@apple.com>
+
+        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
+        https://bugs.webkit.org/show_bug.cgi?id=225362
+
+        Reviewed by Darin Adler.
+
+        Add API test coverage.
+
+        * TestWebKitAPI/Tests/WTF/FileSystem.cpp:
+        (TestWebKitAPI::TEST_F):
+        (TestWebKitAPI::runGetFileModificationTimeTest):
+
 2021-05-06  Lauro Moura  <lmo...@igalia.com>
 
         [WPE] Garden web-process-crashed API test flakiness after SDK update

Modified: trunk/Tools/TestWebKitAPI/Tests/WTF/FileSystem.cpp (277157 => 277158)


--- trunk/Tools/TestWebKitAPI/Tests/WTF/FileSystem.cpp	2021-05-07 04:41:04 UTC (rev 277157)
+++ trunk/Tools/TestWebKitAPI/Tests/WTF/FileSystem.cpp	2021-05-07 05:00:39 UTC (rev 277158)
@@ -27,6 +27,7 @@
 #include "config.h"
 
 #include "Test.h"
+#include "Utilities.h"
 #include <wtf/FileMetadata.h>
 #include <wtf/FileSystem.h>
 #include <wtf/MainThread.h>
@@ -142,19 +143,94 @@
     EXPECT_TRUE(FileSystem::filesHaveSameVolume(bangContainingFilePath(), quoteContainingFilePath()));
 }
 
-TEST_F(FileSystemTest, GetFileMetadataSymlink)
+TEST_F(FileSystemTest, GetFileMetadataFileSymlink)
 {
     auto symlinkMetadata = FileSystem::fileMetadata(tempFileSymlinkPath());
     ASSERT_TRUE(symlinkMetadata.hasValue());
-    EXPECT_TRUE(symlinkMetadata.value().type == FileMetadata::Type::SymbolicLink);
-    EXPECT_FALSE(static_cast<size_t>(symlinkMetadata.value().length) == strlen(FileSystemTestData));
+    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
+    EXPECT_FALSE(symlinkMetadata->isHidden);
+    EXPECT_TRUE(static_cast<size_t>(symlinkMetadata->length) == strlen(FileSystemTestData));
 
     auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(tempFileSymlinkPath());
     ASSERT_TRUE(targetMetadata.hasValue());
-    EXPECT_TRUE(targetMetadata.value().type == FileMetadata::Type::File);
-    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata.value().length));
+    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::File);
+    EXPECT_FALSE(targetMetadata->isHidden);
+    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
+
+    auto actualTargetMetadata = FileSystem::fileMetadata(tempFilePath());
+    ASSERT_TRUE(actualTargetMetadata.hasValue());
+    EXPECT_TRUE(actualTargetMetadata->type == FileMetadata::Type::File);
+    EXPECT_EQ(targetMetadata->modificationTime, actualTargetMetadata->modificationTime);
+    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
+    EXPECT_FALSE(actualTargetMetadata->isHidden);
 }
 
+TEST_F(FileSystemTest, GetFileMetadataSymlinkToFileSymlink)
+{
+    // Create a symbolic link pointing the tempFileSymlinkPath().
+    auto symlinkToSymlinkPath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), "symlinkToSymlink");
+    EXPECT_TRUE(FileSystem::createSymbolicLink(tempFileSymlinkPath(), symlinkToSymlinkPath));
+
+    auto symlinkMetadata = FileSystem::fileMetadata(symlinkToSymlinkPath);
+    ASSERT_TRUE(symlinkMetadata.hasValue());
+    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
+    EXPECT_FALSE(symlinkMetadata->isHidden);
+
+    auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(symlinkToSymlinkPath);
+    ASSERT_TRUE(targetMetadata.hasValue());
+    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::File);
+    EXPECT_FALSE(targetMetadata->isHidden);
+    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
+
+    EXPECT_TRUE(FileSystem::deleteFile(symlinkToSymlinkPath));
+}
+
+TEST_F(FileSystemTest, GetFileMetadataDirectorySymlink)
+{
+    auto symlinkMetadata = FileSystem::fileMetadata(tempEmptyFolderSymlinkPath());
+    ASSERT_TRUE(symlinkMetadata.hasValue());
+    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
+    EXPECT_FALSE(symlinkMetadata->isHidden);
+
+    auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(tempEmptyFolderSymlinkPath());
+    ASSERT_TRUE(targetMetadata.hasValue());
+    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::Directory);
+    EXPECT_FALSE(targetMetadata->isHidden);
+
+    auto actualTargetMetadata = FileSystem::fileMetadata(tempEmptyFolderPath());
+    ASSERT_TRUE(actualTargetMetadata.hasValue());
+    EXPECT_TRUE(actualTargetMetadata->type == FileMetadata::Type::Directory);
+    EXPECT_EQ(targetMetadata->modificationTime, actualTargetMetadata->modificationTime);
+    EXPECT_EQ(targetMetadata->length, actualTargetMetadata->length);
+    EXPECT_FALSE(actualTargetMetadata->isHidden);
+}
+
+TEST_F(FileSystemTest, GetFileMetadataFileDoesNotExist)
+{
+    auto doesNotExistPath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), "does-not-exist");
+    auto metadata = FileSystem::fileMetadata(doesNotExistPath);
+    EXPECT_TRUE(!metadata);
+}
+
+#if OS(UNIX)
+TEST_F(FileSystemTest, GetFileMetadataHiddenFile)
+{
+    auto hiddenFilePath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), ".hiddenFile");
+    auto fileHandle = FileSystem::openFile(hiddenFilePath, FileSystem::FileOpenMode::Write);
+    EXPECT_TRUE(FileSystem::isHandleValid(fileHandle));
+    FileSystem::writeToFile(fileHandle, FileSystemTestData, strlen(FileSystemTestData));
+    FileSystem::closeFile(fileHandle);
+
+    auto metadata = FileSystem::fileMetadata(hiddenFilePath);
+    ASSERT_TRUE(metadata.hasValue());
+    EXPECT_TRUE(metadata->type == FileMetadata::Type::File);
+    EXPECT_TRUE(metadata->isHidden);
+    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(metadata->length));
+
+    EXPECT_TRUE(FileSystem::deleteFile(hiddenFilePath));
+}
+#endif
+
 TEST_F(FileSystemTest, UnicodeDirectoryName)
 {
     String path = String::fromUTF8("/test/a\u0308lo/test.txt");
@@ -541,4 +617,52 @@
     EXPECT_EQ(linkFileSize, fileSize);
 }
 
+static void runGetFileModificationTimeTest(const String& path, Function<Optional<WallTime>(const String&)>&& getFileModificationTime)
+{
+    auto modificationTime = getFileModificationTime(path);
+    EXPECT_TRUE(!!modificationTime);
+    if (!modificationTime)
+        return;
+
+    unsigned timeout = 0;
+    while (*modificationTime >= WallTime::now() && ++timeout < 20)
+        TestWebKitAPI::Util::sleep(0.1);
+    EXPECT_LT(modificationTime->secondsSinceEpoch().value(), WallTime::now().secondsSinceEpoch().value());
+
+    auto timeBeforeModification = WallTime::now();
+
+    TestWebKitAPI::Util::sleep(2);
+
+    // Modify the file.
+    auto fileHandle = FileSystem::openFile(path, FileSystem::FileOpenMode::ReadWrite);
+    EXPECT_TRUE(FileSystem::isHandleValid(fileHandle));
+    FileSystem::writeToFile(fileHandle, "foo", strlen("foo"));
+    FileSystem::closeFile(fileHandle);
+
+    auto newModificationTime = getFileModificationTime(path);
+    EXPECT_TRUE(!!newModificationTime);
+    if (!newModificationTime)
+        return;
+
+    EXPECT_GT(newModificationTime->secondsSinceEpoch().value(), modificationTime->secondsSinceEpoch().value());
+    EXPECT_GT(newModificationTime->secondsSinceEpoch().value(), timeBeforeModification.secondsSinceEpoch().value());
+}
+
+TEST_F(FileSystemTest, getFileModificationTime)
+{
+    runGetFileModificationTimeTest(tempFilePath(), [](const String& path) {
+        return FileSystem::getFileModificationTime(path);
+    });
+}
+
+TEST_F(FileSystemTest, getFileModificationTimeViaFileMetadata)
+{
+    runGetFileModificationTimeTest(tempFilePath(), [](const String& path) -> Optional<WallTime> {
+        auto metadata = FileSystem::fileMetadata(path);
+        if (!metadata)
+            return WTF::nullopt;
+        return metadata->modificationTime;
+    });
+}
+
 } // namespace TestWebKitAPI
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to