⚠ Archived content — this site is no longer maintained.   Current WebKit documentation is at docs.webkit.org.

Changeset 278641 in webkit


Ignore:
Timestamp:
Jun 8, 2021, 7:26:34 PM (5 years ago)
Author:
Ben Nham
Message:

Use access instead of stat in some filesystem functions
https://bugs.webkit.org/show_bug.cgi?id=226667

Reviewed by Chris Dumez.

We are spending a bit more time in WTF::FileSystemImpl functions after the move to
std::filesystem (https://bugs.webkit.org/show_bug.cgi?id=225255). In particular, several
std::filesystem functions (like the ones called by fileExists and makeAllDirectories) prefer
to use stat() over access() for file existence checks. Since our sandbox has a fast path for
access(path, F_OK) but not for stat, we ended up spending more time in sandbox evaluation in
the kernel after the move to std::filesystem.

Note that the two checks don't do exactly the same thing. access(path, F_OK) only checks for
path existence, while stat(path) additionally fetches metadata, which requires checking the
file-read-metadata permission. But in practice our code was written to be fine with just
checking for existence.

To work around this, I've re-introduced some of the old WTF::FileSystemImpl functions from
FileSystemPosix.cpp. They are the ones that are called by NetworkCache, which seems to be
the biggest consumer of these functions. The rest of the functions are still implemented
using std::filesystem.

  • wtf/FileSystem.cpp:

(WTF::FileSystemImpl::fileExists):
(WTF::FileSystemImpl::deleteFile):
(WTF::FileSystemImpl::makeAllDirectories):
(WTF::FileSystemImpl::pathByAppendingComponent):
(WTF::FileSystemImpl::pathByAppendingComponents):

  • wtf/PlatformEnableCocoa.h:
  • wtf/posix/FileSystemPOSIX.cpp:

(WTF::FileSystemImpl::fileExists):
(WTF::FileSystemImpl::deleteFile):
(WTF::FileSystemImpl::makeAllDirectories):
(WTF::FileSystemImpl::pathByAppendingComponent):
(WTF::FileSystemImpl::pathByAppendingComponents):

Location:
trunk/Source/WTF
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WTF/ChangeLog

    r278630 r278641  
     12021-06-08  Ben Nham  <nham@apple.com>
     2
     3        Use access instead of stat in some filesystem functions
     4        https://bugs.webkit.org/show_bug.cgi?id=226667
     5
     6        Reviewed by Chris Dumez.
     7
     8        We are spending a bit more time in WTF::FileSystemImpl functions after the move to
     9        std::filesystem (https://bugs.webkit.org/show_bug.cgi?id=225255). In particular, several
     10        std::filesystem functions (like the ones called by fileExists and makeAllDirectories) prefer
     11        to use stat() over access() for file existence checks. Since our sandbox has a fast path for
     12        access(path, F_OK) but not for stat, we ended up spending more time in sandbox evaluation in
     13        the kernel after the move to std::filesystem.
     14
     15        Note that the two checks don't do exactly the same thing. access(path, F_OK) only checks for
     16        path existence, while stat(path) additionally fetches metadata, which requires checking the
     17        file-read-metadata permission. But in practice our code was written to be fine with just
     18        checking for existence.
     19
     20        To work around this, I've re-introduced some of the old WTF::FileSystemImpl functions from
     21        FileSystemPosix.cpp. They are the ones that are called by NetworkCache, which seems to be
     22        the biggest consumer of these functions. The rest of the functions are still implemented
     23        using std::filesystem.
     24
     25        * wtf/FileSystem.cpp:
     26        (WTF::FileSystemImpl::fileExists):
     27        (WTF::FileSystemImpl::deleteFile):
     28        (WTF::FileSystemImpl::makeAllDirectories):
     29        (WTF::FileSystemImpl::pathByAppendingComponent):
     30        (WTF::FileSystemImpl::pathByAppendingComponents):
     31        * wtf/PlatformEnableCocoa.h:
     32        * wtf/posix/FileSystemPOSIX.cpp:
     33        (WTF::FileSystemImpl::fileExists):
     34        (WTF::FileSystemImpl::deleteFile):
     35        (WTF::FileSystemImpl::makeAllDirectories):
     36        (WTF::FileSystemImpl::pathByAppendingComponent):
     37        (WTF::FileSystemImpl::pathByAppendingComponents):
     38
    1392021-06-08  Devin Rousso  <drousso@apple.com>
    240
  • trunk/Source/WTF/wtf/FileSystem.cpp

    r278521 r278641  
    523523#if HAVE(STD_FILESYSTEM) || HAVE(STD_EXPERIMENTAL_FILESYSTEM)
    524524
    525 bool fileExists(const String& path)
    526 {
    527     std::error_code ec;
    528     // exists() returns false on error so no need to check ec.
    529     return std::filesystem::exists(toStdFileSystemPath(path), ec);
    530 }
    531 
    532 bool deleteFile(const String& path)
    533 {
    534     std::error_code ec;
    535     auto fsPath = toStdFileSystemPath(path);
    536 
    537     auto fileStatus = std::filesystem::symlink_status(fsPath, ec);
    538     if (ec || fileStatus.type() == std::filesystem::file_type::directory)
    539         return false;
    540 
    541     // remove() returns false on error so no need to check ec.
    542     return std::filesystem::remove(fsPath, ec);
    543 }
    544 
    545525bool deleteEmptyDirectory(const String& path)
    546526{
     
    598578}
    599579
    600 bool makeAllDirectories(const String& path)
    601 {
    602     std::error_code ec;
    603     std::filesystem::create_directories(toStdFileSystemPath(path), ec);
    604     return !ec;
    605 }
    606 
    607580std::optional<uint64_t> volumeFreeSpace(const String& path)
    608581{
     
    729702}
    730703
    731 String pathByAppendingComponent(const String& path, const String& component)
    732 {
    733     return fromStdFileSystemPath(toStdFileSystemPath(path) / toStdFileSystemPath(component));
    734 }
    735 
    736 String pathByAppendingComponents(StringView path, const Vector<StringView>& components)
    737 {
    738     auto fsPath = toStdFileSystemPath(path);
    739     for (auto& component : components)
    740         fsPath /= toStdFileSystemPath(component);
    741     return fromStdFileSystemPath(fsPath);
    742 }
    743 
    744704Vector<String> listDirectory(const String& path)
    745705{
     
    755715}
    756716
     717#if !ENABLE(FILESYSTEM_POSIX_FAST_PATH)
     718
     719bool fileExists(const String& path)
     720{
     721    std::error_code ec;
     722    // exists() returns false on error so no need to check ec.
     723    return std::filesystem::exists(toStdFileSystemPath(path), ec);
     724}
     725
     726bool deleteFile(const String& path)
     727{
     728    std::error_code ec;
     729    auto fsPath = toStdFileSystemPath(path);
     730
     731    auto fileStatus = std::filesystem::symlink_status(fsPath, ec);
     732    if (ec || fileStatus.type() == std::filesystem::file_type::directory)
     733        return false;
     734
     735    // remove() returns false on error so no need to check ec.
     736    return std::filesystem::remove(fsPath, ec);
     737}
     738
     739bool makeAllDirectories(const String& path)
     740{
     741    std::error_code ec;
     742    std::filesystem::create_directories(toStdFileSystemPath(path), ec);
     743    return !ec;
     744}
     745
     746String pathByAppendingComponent(const String& path, const String& component)
     747{
     748    return fromStdFileSystemPath(toStdFileSystemPath(path) / toStdFileSystemPath(component));
     749}
     750
     751String pathByAppendingComponents(StringView path, const Vector<StringView>& components)
     752{
     753    auto fsPath = toStdFileSystemPath(path);
     754    for (auto& component : components)
     755        fsPath /= toStdFileSystemPath(component);
     756    return fromStdFileSystemPath(fsPath);
     757}
     758
     759#endif
     760
    757761#endif // HAVE(STD_FILESYSTEM) || HAVE(STD_EXPERIMENTAL_FILESYSTEM)
    758762
  • trunk/Source/WTF/wtf/PlatformEnableCocoa.h

    r278630 r278641  
    221221#endif
    222222
     223#if !defined(ENABLE_FILESYSTEM_POSIX_FAST_PATH)
     224#define ENABLE_FILESYSTEM_POSIX_FAST_PATH 1
     225#endif
     226
    223227#if !defined(ENABLE_FILTERS_LEVEL_2)
    224228#define ENABLE_FILTERS_LEVEL_2 1
  • trunk/Source/WTF/wtf/posix/FileSystemPOSIX.cpp

    r278521 r278641  
    236236}
    237237
     238#if ENABLE(FILESYSTEM_POSIX_FAST_PATH)
     239
     240bool fileExists(const String& path)
     241{
     242    return access(fileSystemRepresentation(path).data(), F_OK) != -1;
     243}
     244
     245bool deleteFile(const String& path)
     246{
     247    // unlink(...) returns 0 on successful deletion of the path and non-zero in any other case (including invalid permissions or non-existent file)
     248    bool unlinked = !unlink(fileSystemRepresentation(path).data());
     249    if (!unlinked && errno != ENOENT)
     250        LOG_ERROR("File failed to delete. Error message: %s", strerror(errno));
     251
     252    return unlinked;
     253}
     254
     255bool makeAllDirectories(const String& path)
     256{
     257    auto fullPath = fileSystemRepresentation(path);
     258    if (!access(fullPath.data(), F_OK))
     259        return true;
     260
     261    char* p = fullPath.mutableData() + 1;
     262    int length = fullPath.length();
     263    if (p[length - 1] == '/')
     264        p[length - 1] = '\0';
     265    for (; *p; ++p) {
     266        if (*p == '/') {
     267            *p = '\0';
     268            if (access(fullPath.data(), F_OK)) {
     269                if (mkdir(fullPath.data(), S_IRWXU))
     270                    return false;
     271            }
     272            *p = '/';
     273        }
     274    }
     275    if (access(fullPath.data(), F_OK)) {
     276        if (mkdir(fullPath.data(), S_IRWXU))
     277            return false;
     278    }
     279
     280    return true;
     281}
     282
     283String pathByAppendingComponent(const String& path, const String& component)
     284{
     285    if (path.endsWith('/'))
     286        return path + component;
     287    return path + "/" + component;
     288}
     289
     290String pathByAppendingComponents(StringView path, const Vector<StringView>& components)
     291{
     292    StringBuilder builder;
     293    builder.append(path);
     294    bool isFirstComponent = true;
     295    for (auto& component : components) {
     296        if (isFirstComponent) {
     297            isFirstComponent = false;
     298            if (path.endsWith('/')) {
     299                builder.append(component);
     300                continue;
     301            }
     302        }
     303        builder.append('/', component);
     304    }
     305    return builder.toString();
     306}
     307
     308#endif
     309
    238310} // namespace FileSystemImpl
    239311} // namespace WTF
Note: See TracChangeset for help on using the changeset viewer.