Changeset 277158 in webkit


Ignore:
Timestamp:
May 6, 2021 10:00:39 PM (3 years ago)
Author:
Chris Dumez
Message:

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

Reviewed by Darin Adler.

Source/JavaScriptCore:

Build fix.

  • Configurations/JavaScriptCore.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:
Location:
trunk
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/LayoutTests/ChangeLog

    r277154 r277158  
     12021-05-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
     4        https://bugs.webkit.org/show_bug.cgi?id=225362
     5
     6        Reviewed by Darin Adler.
     7
     8        Add 0 to the list of allowed values for the size of a directory in the data transfer API as the result
     9        is implementation-specific. On macOS, we used to return 256 on apfs and 272 on HFS+. We now return 0,
     10        which is what Firefox does.
     11
     12        * editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt:
     13        * editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html:
     14        * fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt:
     15        * fast/forms/file/entries-api/drag-folder-webkitEntries.html:
     16
    1172021-05-06  Robert Jenner  <jenner@apple.com>
    218
  • trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry-expected.txt

    r232417 r277158  
    1717PASS secondDataTransferItem.type is ""
    1818PASS secondFile.name is "testFiles"
    19 PASS secondFile.size is one of `272`, and `256`
     19PASS secondFile.size is one of `0`,`272`, and `256`
    2020PASS secondFile.type is ""
    2121PASS secondEntry.isDirectory is true
  • trunk/LayoutTests/editing/pasteboard/entries-api/datatransfer-items-drop-getAsEntry.html

    r232417 r277158  
    3838    secondFile = secondDataTransferItem.getAsFile();
    3939    shouldBeEqualToString("secondFile.name", "testFiles");
    40     shouldBeOneOfValues("secondFile.size", [272, 256]); // Chrome returns folder size, Firefox returns 0. 256 in APFS, 272 in HFS+
     40    shouldBeOneOfValues("secondFile.size", [0, 272, 256]); // Chrome returns folder size, Firefox returns 0. 256 in APFS, 272 in HFS+
    4141    shouldBeEqualToString("secondFile.type", "");
    4242
  • trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries-expected.txt

    r232417 r277158  
    1717PASS files[0].type is "text/plain"
    1818PASS files[1].name is "testFiles"
    19 PASS files[1].size is one of `272`, and `256`
     19PASS files[1].size is one of `0`,`272`, and `256`
    2020PASS files[1].type is ""
    2121PASS successfullyParsed is true
  • trunk/LayoutTests/fast/forms/file/entries-api/drag-folder-webkitEntries.html

    r232417 r277158  
    4949
    5050    shouldBeEqualToString("files[1].name", "testFiles");
    51     shouldBeOneOfValues("files[1].size", [272, 256]);
     51    shouldBeOneOfValues("files[1].size", [0, 272, 256]);
    5252    shouldBeEqualToString("files[1].type", "");
    5353
  • trunk/LayoutTests/resources/js-test.js

    r275427 r277158  
    312312    else {
    313313        var matchedValue = _values.find(function (value) { return isResultCorrect(_av, value); });
    314         if (matchedValue) {
     314        if (matchedValue !== undefined) {
    315315            testPassed(_a + " is one of " + stringifiedValues);
    316316        } else {
  • trunk/Source/JavaScriptCore/ChangeLog

    r277153 r277158  
     12021-05-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
     4        https://bugs.webkit.org/show_bug.cgi?id=225362
     5
     6        Reviewed by Darin Adler.
     7
     8        Build fix.
     9
     10        * Configurations/JavaScriptCore.xcconfig:
     11
    1122021-05-06  Eleni Maria Stea  <estea@igalia.com>
    213
  • trunk/Source/JavaScriptCore/Configurations/JavaScriptCore.xcconfig

    r276906 r277158  
    2828
    2929// Prevent C++ standard library operator new, delete and their related exception types from being exported as weak symbols.
    30 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_;
     30OTHER_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_;
    3131
    3232OTHER_LDFLAGS_BASE = $(OTHER_LDFLAGS_HIDE_SYMBOLS) -force_load "$(BUILT_PRODUCTS_DIR)/DerivedSources/JavaScriptCore/libWTF.a";
  • trunk/Source/WTF/ChangeLog

    r277142 r277158  
     12021-05-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
     4        https://bugs.webkit.org/show_bug.cgi?id=225362
     5
     6        Reviewed by Darin Adler.
     7
     8        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
     9        and get rid of platform-specific implementations.
     10
     11        * wtf/FileSystem.cpp:
     12        (WTF::FileSystemImpl::toWallTime):
     13        (WTF::FileSystemImpl::getFileModificationTime):
     14        (WTF::FileSystemImpl::fileMetadata):
     15        * wtf/FileSystem.h:
     16        * wtf/glib/FileSystemGlib.cpp:
     17        * wtf/posix/FileSystemPOSIX.cpp:
     18        * wtf/win/FileSystemWin.cpp:
     19
    1202021-05-06  Yoshiaki Jitsukawa  <yoshiaki.jitsukawa@sony.com>
    221
  • trunk/Source/WTF/wtf/FileSystem.cpp

    r276936 r277158  
    3838#if !OS(WINDOWS)
    3939#include <sys/mman.h>
     40#include <sys/param.h>
    4041#include <sys/stat.h>
    4142#endif
     
    106107}
    107108
     109template<typename ClockType, typename = void> struct has_to_time_t : std::false_type { };
     110template<typename ClockType> struct has_to_time_t<ClockType, std::void_t<
     111    std::enable_if_t<std::is_same_v<std::time_t, decltype(ClockType::to_time_t(std::filesystem::file_time_type()))>>
     112>> : std::true_type { };
     113
     114template <typename FileTimeType>
     115typename std::enable_if_t<has_to_time_t<typename FileTimeType::clock>::value, std::time_t> toTimeT(FileTimeType fileTime)
     116{
     117    return decltype(fileTime)::clock::to_time_t(fileTime);
     118}
     119
     120template <typename FileTimeType>
     121typename std::enable_if_t<!has_to_time_t<typename FileTimeType::clock>::value, std::time_t> toTimeT(FileTimeType fileTime)
     122{
     123    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()));
     124}
     125
     126static WallTime toWallTime(std::filesystem::file_time_type fileTime)
     127{
     128    // FIXME: Use std::chrono::file_clock::to_sys() once we can use C++20.
     129    return WallTime::fromRawSeconds(toTimeT(fileTime));
     130}
     131
     132static std::filesystem::path resolveSymlinks(std::filesystem::path path, std::error_code& ec)
     133{
     134#ifdef MAXSYMLINKS
     135    static constexpr unsigned maxSymlinkDepth = MAXSYMLINKS;
     136#else
     137    static constexpr unsigned maxSymlinkDepth = 40;
     138#endif
     139
     140    unsigned currentDepth = 0;
     141    while (++currentDepth <= maxSymlinkDepth && !ec && std::filesystem::is_symlink(path, ec))
     142        path = std::filesystem::read_symlink(path, ec);
     143    return path;
     144}
     145
    108146String encodeForFileName(const String& inputString)
    109147{
     
    624662}
    625663
     664Optional<WallTime> getFileModificationTime(const String& path)
     665{
     666    std::error_code ec;
     667    auto modificationTime = std::filesystem::last_write_time(fileSystemRepresentation(path).data(), ec);
     668    if (ec)
     669        return WTF::nullopt;
     670    return toWallTime(modificationTime);
     671}
     672
     673static Optional<FileMetadata> fileMetadataPotentiallyFollowingSymlinks(const String& path, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
     674{
     675    if (path.isEmpty())
     676        return WTF::nullopt;
     677
     678    std::filesystem::path fsPath = fileSystemRepresentation(path).data();
     679
     680    std::error_code ec;
     681    if (shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes && std::filesystem::is_symlink(fsPath, ec)) {
     682        fsPath = resolveSymlinks(fsPath, ec);
     683        if (ec)
     684            return WTF::nullopt;
     685    }
     686
     687    ec = { };
     688    std::filesystem::directory_entry entry(fsPath, ec);
     689    if (ec)
     690        return WTF::nullopt;
     691
     692    auto modificationTime = toWallTime(entry.last_write_time(ec));
     693
     694    // Note that the result of attempting to determine the size of a directory is implementation-defined.
     695    auto fileSize = entry.file_size(ec);
     696    if (ec)
     697        fileSize = 0;
     698
     699#if OS(UNIX)
     700    std::filesystem::path::string_type filename = fsPath.filename();
     701    bool isHidden = !filename.empty() && filename[0] == '.';
     702#else
     703    bool isHidden = false;
     704#endif
     705    FileMetadata::Type type = FileMetadata::Type::File;
     706    if (entry.is_symlink(ec))
     707        type = FileMetadata::Type::SymbolicLink;
     708    else if (entry.is_directory(ec))
     709        type = FileMetadata::Type::Directory;
     710
     711    return FileMetadata { modificationTime, static_cast<long long>(fileSize), isHidden, type };
     712}
     713
     714Optional<FileMetadata> fileMetadata(const String& path)
     715{
     716    return fileMetadataPotentiallyFollowingSymlinks(path, ShouldFollowSymbolicLinks::No);
     717}
     718
     719Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
     720{
     721    return fileMetadataPotentiallyFollowingSymlinks(path, ShouldFollowSymbolicLinks::Yes);
     722}
     723
    626724} // namespace FileSystemImpl
    627725} // namespace WTF
  • trunk/Source/WTF/wtf/glib/FileSystemGlib.cpp

    r276879 r277158  
    153153}
    154154
    155 Optional<WallTime> getFileModificationTime(const String& path)
    156 {
    157     GStatBuf statResult;
    158     if (!getFileStat(path, &statResult))
    159         return WTF::nullopt;
    160 
    161     return WallTime::fromRawSeconds(statResult.st_mtime);
    162 }
    163 
    164 static FileMetadata::Type toFileMetataType(GStatBuf statResult)
    165 {
    166     if (S_ISDIR(statResult.st_mode))
    167         return FileMetadata::Type::Directory;
    168     if (S_ISLNK(statResult.st_mode))
    169         return FileMetadata::Type::SymbolicLink;
    170     return FileMetadata::Type::File;
    171 }
    172 
    173 static Optional<FileMetadata> fileMetadataUsingFunction(const String& path, bool (*statFunc)(const String&, GStatBuf*))
    174 {
    175     GStatBuf statResult;
    176     if (!statFunc(path, &statResult))
    177         return WTF::nullopt;
    178 
    179     String filename = pathGetFileName(path);
    180     bool isHidden = !filename.isEmpty() && filename[0] == '.';
    181 
    182     return FileMetadata {
    183         WallTime::fromRawSeconds(statResult.st_mtime),
    184         statResult.st_size,
    185         isHidden,
    186         toFileMetataType(statResult)
    187     };
    188 }
    189 
    190 Optional<FileMetadata> fileMetadata(const String& path)
    191 {
    192     return fileMetadataUsingFunction(path, &getFileLStat);
    193 }
    194 
    195 Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
    196 {
    197     return fileMetadataUsingFunction(path, &getFileStat);
    198 }
    199 
    200155String pathByAppendingComponent(const String& path, const String& component)
    201156{
  • trunk/Source/WTF/wtf/posix/FileSystemPOSIX.cpp

    r276879 r277158  
    187187}
    188188
    189 Optional<WallTime> getFileModificationTime(const String& path)
    190 {
    191     CString fsRep = fileSystemRepresentation(path);
    192 
    193     if (!fsRep.data() || fsRep.data()[0] == '\0')
    194         return WTF::nullopt;
    195 
    196     struct stat fileInfo;
    197 
    198     if (stat(fsRep.data(), &fileInfo))
    199         return WTF::nullopt;
    200 
    201     return WallTime::fromRawSeconds(fileInfo.st_mtime);
    202 }
    203 
    204 static FileMetadata::Type toFileMetataType(struct stat fileInfo)
    205 {
    206     if (S_ISDIR(fileInfo.st_mode))
    207         return FileMetadata::Type::Directory;
    208     if (S_ISLNK(fileInfo.st_mode))
    209         return FileMetadata::Type::SymbolicLink;
    210     return FileMetadata::Type::File;
    211 }
    212 
    213 static Optional<FileMetadata> fileMetadataUsingFunction(const String& path, int (*statFunc)(const char*, struct stat*))
    214 {
    215     CString fsRep = fileSystemRepresentation(path);
    216 
    217     if (!fsRep.data() || fsRep.data()[0] == '\0')
    218         return WTF::nullopt;
    219 
    220     struct stat fileInfo;
    221     if (statFunc(fsRep.data(), &fileInfo))
    222         return WTF::nullopt;
    223 
    224     String filename = pathGetFileName(path);
    225     bool isHidden = !filename.isEmpty() && filename[0] == '.';
    226     return FileMetadata {
    227         WallTime::fromRawSeconds(fileInfo.st_mtime),
    228         fileInfo.st_size,
    229         isHidden,
    230         toFileMetataType(fileInfo)
    231     };
    232 }
    233 
    234 Optional<FileMetadata> fileMetadata(const String& path)
    235 {
    236     return fileMetadataUsingFunction(path, &lstat);
    237 }
    238 
    239 Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
    240 {
    241     return fileMetadataUsingFunction(path, &stat);
    242 }
    243 
    244189String pathByAppendingComponent(const String& path, const String& component)
    245190{
  • trunk/Source/WTF/wtf/win/FileSystemWin.cpp

    r276879 r277158  
    115115}
    116116
    117 Optional<WallTime> getFileModificationTime(const String& path)
    118 {
    119     WIN32_FIND_DATAW findData;
    120     if (!getFindData(path, findData))
    121         return WTF::nullopt;
    122 
    123     time_t time = 0;
    124     getFileModificationTimeFromFindData(findData, time);
    125     return WallTime::fromRawSeconds(time);
    126 }
    127 
    128117Optional<WallTime> getFileCreationTime(const String& path)
    129118{
     
    153142    buffer.shrink(wcslen(wcharFrom(buffer.data())));
    154143    return String::adopt(WTFMove(buffer));
    155 }
    156 
    157 static inline bool isSymbolicLink(WIN32_FIND_DATAW findData)
    158 {
    159     return findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
    160 }
    161 
    162 static FileMetadata::Type toFileMetadataType(WIN32_FIND_DATAW findData)
    163 {
    164     if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
    165         return FileMetadata::Type::Directory;
    166     if (isSymbolicLink(findData))
    167         return FileMetadata::Type::SymbolicLink;
    168     return FileMetadata::Type::File;
    169 }
    170 
    171 static Optional<FileMetadata> findDataToFileMetadata(WIN32_FIND_DATAW findData)
    172 {
    173     long long length;
    174     if (!getFileSizeFromFindData(findData, length))
    175         return WTF::nullopt;
    176 
    177     time_t modificationTime;
    178     getFileModificationTimeFromFindData(findData, modificationTime);
    179 
    180     return FileMetadata {
    181         WallTime::fromRawSeconds(modificationTime),
    182         length,
    183         static_cast<bool>(findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN),
    184         toFileMetadataType(findData)
    185     };
    186 }
    187 
    188 Optional<FileMetadata> fileMetadata(const String& path)
    189 {
    190     WIN32_FIND_DATAW findData;
    191     if (!getFindData(path, findData))
    192         return WTF::nullopt;
    193 
    194     return findDataToFileMetadata(findData);
    195 }
    196 
    197 Optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
    198 {
    199     WIN32_FIND_DATAW findData;
    200     if (!getFindData(path, findData))
    201         return WTF::nullopt;
    202 
    203     if (isSymbolicLink(findData)) {
    204         String targetPath = getFinalPathName(path);
    205         if (targetPath.isNull())
    206             return WTF::nullopt;
    207         if (!getFindData(targetPath, findData))
    208             return WTF::nullopt;
    209     }
    210 
    211     return findDataToFileMetadata(findData);
    212144}
    213145
  • trunk/Tools/ChangeLog

    r277157 r277158  
     12021-05-06  Chris Dumez  <cdumez@apple.com>
     2
     3        Port Filesystem::fileMetadata() & Filesystem::getFileModificationTime() to std::filesystem
     4        https://bugs.webkit.org/show_bug.cgi?id=225362
     5
     6        Reviewed by Darin Adler.
     7
     8        Add API test coverage.
     9
     10        * TestWebKitAPI/Tests/WTF/FileSystem.cpp:
     11        (TestWebKitAPI::TEST_F):
     12        (TestWebKitAPI::runGetFileModificationTimeTest):
     13
    1142021-05-06  Lauro Moura  <lmoura@igalia.com>
    215
  • trunk/Tools/TestWebKitAPI/Tests/WTF/FileSystem.cpp

    r277113 r277158  
    2828
    2929#include "Test.h"
     30#include "Utilities.h"
    3031#include <wtf/FileMetadata.h>
    3132#include <wtf/FileSystem.h>
     
    143144}
    144145
    145 TEST_F(FileSystemTest, GetFileMetadataSymlink)
     146TEST_F(FileSystemTest, GetFileMetadataFileSymlink)
    146147{
    147148    auto symlinkMetadata = FileSystem::fileMetadata(tempFileSymlinkPath());
    148149    ASSERT_TRUE(symlinkMetadata.hasValue());
    149     EXPECT_TRUE(symlinkMetadata.value().type == FileMetadata::Type::SymbolicLink);
    150     EXPECT_FALSE(static_cast<size_t>(symlinkMetadata.value().length) == strlen(FileSystemTestData));
     150    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
     151    EXPECT_FALSE(symlinkMetadata->isHidden);
     152    EXPECT_TRUE(static_cast<size_t>(symlinkMetadata->length) == strlen(FileSystemTestData));
    151153
    152154    auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(tempFileSymlinkPath());
    153155    ASSERT_TRUE(targetMetadata.hasValue());
    154     EXPECT_TRUE(targetMetadata.value().type == FileMetadata::Type::File);
    155     EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata.value().length));
    156 }
     156    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::File);
     157    EXPECT_FALSE(targetMetadata->isHidden);
     158    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
     159
     160    auto actualTargetMetadata = FileSystem::fileMetadata(tempFilePath());
     161    ASSERT_TRUE(actualTargetMetadata.hasValue());
     162    EXPECT_TRUE(actualTargetMetadata->type == FileMetadata::Type::File);
     163    EXPECT_EQ(targetMetadata->modificationTime, actualTargetMetadata->modificationTime);
     164    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
     165    EXPECT_FALSE(actualTargetMetadata->isHidden);
     166}
     167
     168TEST_F(FileSystemTest, GetFileMetadataSymlinkToFileSymlink)
     169{
     170    // Create a symbolic link pointing the tempFileSymlinkPath().
     171    auto symlinkToSymlinkPath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), "symlinkToSymlink");
     172    EXPECT_TRUE(FileSystem::createSymbolicLink(tempFileSymlinkPath(), symlinkToSymlinkPath));
     173
     174    auto symlinkMetadata = FileSystem::fileMetadata(symlinkToSymlinkPath);
     175    ASSERT_TRUE(symlinkMetadata.hasValue());
     176    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
     177    EXPECT_FALSE(symlinkMetadata->isHidden);
     178
     179    auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(symlinkToSymlinkPath);
     180    ASSERT_TRUE(targetMetadata.hasValue());
     181    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::File);
     182    EXPECT_FALSE(targetMetadata->isHidden);
     183    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata->length));
     184
     185    EXPECT_TRUE(FileSystem::deleteFile(symlinkToSymlinkPath));
     186}
     187
     188TEST_F(FileSystemTest, GetFileMetadataDirectorySymlink)
     189{
     190    auto symlinkMetadata = FileSystem::fileMetadata(tempEmptyFolderSymlinkPath());
     191    ASSERT_TRUE(symlinkMetadata.hasValue());
     192    EXPECT_TRUE(symlinkMetadata->type == FileMetadata::Type::SymbolicLink);
     193    EXPECT_FALSE(symlinkMetadata->isHidden);
     194
     195    auto targetMetadata = FileSystem::fileMetadataFollowingSymlinks(tempEmptyFolderSymlinkPath());
     196    ASSERT_TRUE(targetMetadata.hasValue());
     197    EXPECT_TRUE(targetMetadata->type == FileMetadata::Type::Directory);
     198    EXPECT_FALSE(targetMetadata->isHidden);
     199
     200    auto actualTargetMetadata = FileSystem::fileMetadata(tempEmptyFolderPath());
     201    ASSERT_TRUE(actualTargetMetadata.hasValue());
     202    EXPECT_TRUE(actualTargetMetadata->type == FileMetadata::Type::Directory);
     203    EXPECT_EQ(targetMetadata->modificationTime, actualTargetMetadata->modificationTime);
     204    EXPECT_EQ(targetMetadata->length, actualTargetMetadata->length);
     205    EXPECT_FALSE(actualTargetMetadata->isHidden);
     206}
     207
     208TEST_F(FileSystemTest, GetFileMetadataFileDoesNotExist)
     209{
     210    auto doesNotExistPath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), "does-not-exist");
     211    auto metadata = FileSystem::fileMetadata(doesNotExistPath);
     212    EXPECT_TRUE(!metadata);
     213}
     214
     215#if OS(UNIX)
     216TEST_F(FileSystemTest, GetFileMetadataHiddenFile)
     217{
     218    auto hiddenFilePath = FileSystem::pathByAppendingComponent(tempEmptyFolderPath(), ".hiddenFile");
     219    auto fileHandle = FileSystem::openFile(hiddenFilePath, FileSystem::FileOpenMode::Write);
     220    EXPECT_TRUE(FileSystem::isHandleValid(fileHandle));
     221    FileSystem::writeToFile(fileHandle, FileSystemTestData, strlen(FileSystemTestData));
     222    FileSystem::closeFile(fileHandle);
     223
     224    auto metadata = FileSystem::fileMetadata(hiddenFilePath);
     225    ASSERT_TRUE(metadata.hasValue());
     226    EXPECT_TRUE(metadata->type == FileMetadata::Type::File);
     227    EXPECT_TRUE(metadata->isHidden);
     228    EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(metadata->length));
     229
     230    EXPECT_TRUE(FileSystem::deleteFile(hiddenFilePath));
     231}
     232#endif
    157233
    158234TEST_F(FileSystemTest, UnicodeDirectoryName)
     
    542618}
    543619
     620static void runGetFileModificationTimeTest(const String& path, Function<Optional<WallTime>(const String&)>&& getFileModificationTime)
     621{
     622    auto modificationTime = getFileModificationTime(path);
     623    EXPECT_TRUE(!!modificationTime);
     624    if (!modificationTime)
     625        return;
     626
     627    unsigned timeout = 0;
     628    while (*modificationTime >= WallTime::now() && ++timeout < 20)
     629        TestWebKitAPI::Util::sleep(0.1);
     630    EXPECT_LT(modificationTime->secondsSinceEpoch().value(), WallTime::now().secondsSinceEpoch().value());
     631
     632    auto timeBeforeModification = WallTime::now();
     633
     634    TestWebKitAPI::Util::sleep(2);
     635
     636    // Modify the file.
     637    auto fileHandle = FileSystem::openFile(path, FileSystem::FileOpenMode::ReadWrite);
     638    EXPECT_TRUE(FileSystem::isHandleValid(fileHandle));
     639    FileSystem::writeToFile(fileHandle, "foo", strlen("foo"));
     640    FileSystem::closeFile(fileHandle);
     641
     642    auto newModificationTime = getFileModificationTime(path);
     643    EXPECT_TRUE(!!newModificationTime);
     644    if (!newModificationTime)
     645        return;
     646
     647    EXPECT_GT(newModificationTime->secondsSinceEpoch().value(), modificationTime->secondsSinceEpoch().value());
     648    EXPECT_GT(newModificationTime->secondsSinceEpoch().value(), timeBeforeModification.secondsSinceEpoch().value());
     649}
     650
     651TEST_F(FileSystemTest, getFileModificationTime)
     652{
     653    runGetFileModificationTimeTest(tempFilePath(), [](const String& path) {
     654        return FileSystem::getFileModificationTime(path);
     655    });
     656}
     657
     658TEST_F(FileSystemTest, getFileModificationTimeViaFileMetadata)
     659{
     660    runGetFileModificationTimeTest(tempFilePath(), [](const String& path) -> Optional<WallTime> {
     661        auto metadata = FileSystem::fileMetadata(path);
     662        if (!metadata)
     663            return WTF::nullopt;
     664        return metadata->modificationTime;
     665    });
     666}
     667
    544668} // namespace TestWebKitAPI
Note: See TracChangeset for help on using the changeset viewer.