+2017-09-03 Chris Dumez <cdumez@apple.com>
+
+ Have getFileMetadata() return a std::optional<FileMetadata>
+ https://bugs.webkit.org/show_bug.cgi?id=176293
+
+ Reviewed by Darin Adler.
+
+ Have getFileMetadata() return a std::optional<FileMetadata> instead of
+ using an out parameter for the metadata.
+
+ * Modules/entriesapi/DOMFileSystem.cpp:
+ (WebCore::listDirectoryWithMetadata):
+ (WebCore::validatePathIsExpectedType):
+ (WebCore::DOMFileSystem::getEntry):
+ * html/FileListCreator.cpp:
+ (WebCore::appendDirectoryFiles):
+ * platform/FileSystem.cpp:
+ (WebCore::fileIsDirectory):
+ * platform/FileSystem.h:
+ * platform/glib/FileSystemGlib.cpp:
+ (WebCore::getFileMetadata):
+ * platform/network/BlobDataFileReference.cpp:
+ (WebCore::BlobDataFileReference::startTrackingModifications):
+ * platform/network/mac/BlobDataFileReferenceMac.mm:
+ (WebCore::BlobDataFileReference::generateReplacementFile):
+ * platform/posix/FileSystemPOSIX.cpp:
+ (WebCore::getFileMetadata):
+ * platform/win/FileSystemWin.cpp:
+ (WebCore::getFileMetadata):
+
2017-09-03 Sam Weinig <sam@webkit.org>
Remove CanvasProxy
Vector<ListedChild> listedChildren;
listedChildren.reserveInitialCapacity(childPaths.size());
for (auto& childPath : childPaths) {
- FileMetadata metadata;
- if (!getFileMetadata(childPath, metadata, ShouldFollowSymbolicLinks::No))
+ auto metadata = fileMetadata(childPath);
+ if (!metadata)
continue;
- listedChildren.uncheckedAppend(ListedChild { pathGetFileName(childPath), metadata.type });
+ listedChildren.uncheckedAppend(ListedChild { pathGetFileName(childPath), metadata.value().type });
}
return WTFMove(listedChildren);
}
for (auto& child : listedChildren.returnValue()) {
String virtualPath = parentVirtualPath + "/" + child.filename;
switch (child.type) {
- case FileMetadata::TypeFile:
+ case FileMetadata::Type::File:
entries.uncheckedAppend(FileSystemFileEntry::create(context, fileSystem, virtualPath));
break;
- case FileMetadata::TypeDirectory:
+ case FileMetadata::Type::Directory:
entries.uncheckedAppend(FileSystemDirectoryEntry::create(context, fileSystem, virtualPath));
break;
default:
{
ASSERT(!isMainThread());
- FileMetadata metadata;
- if (!getFileMetadata(fullPath, metadata, ShouldFollowSymbolicLinks::No))
+ auto metadata = fileMetadata(fullPath);
+ if (!metadata)
return Exception { NotFoundError, ASCIILiteral("Path does not exist") };
- if (metadata.type != expectedType)
+ if (metadata.value().type != expectedType)
return Exception { TypeMismatchError, "Entry at path does not have expected type" };
return WTFMove(virtualPath);
ASSERT(virtualPath[0] == '/');
auto fullPath = evaluatePath(virtualPath);
m_workQueue->dispatch([this, context = makeRef(context), fullPath = crossThreadCopy(fullPath), virtualPath = crossThreadCopy(virtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
- auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::TypeDirectory);
+ auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::Type::Directory);
callOnMainThread([this, context = WTFMove(context), validatedVirtualPath = crossThreadCopy(validatedVirtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
if (validatedVirtualPath.hasException())
completionCallback(validatedVirtualPath.releaseException());
}
m_workQueue->dispatch([this, context = makeRef(context), fullPath = crossThreadCopy(fullPath), resolvedVirtualPath = crossThreadCopy(resolvedVirtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
- FileMetadata metadata;
- getFileMetadata(fullPath, metadata, ShouldFollowSymbolicLinks::No);
- callOnMainThread([this, context = WTFMove(context), resolvedVirtualPath = crossThreadCopy(resolvedVirtualPath), entryType = metadata.type, completionCallback = WTFMove(completionCallback)]() mutable {
- switch (entryType) {
- case FileMetadata::TypeDirectory:
+ std::optional<FileMetadata::Type> entryType;
+ if (auto metadata = fileMetadata(fullPath))
+ entryType = metadata.value().type;
+ callOnMainThread([this, context = WTFMove(context), resolvedVirtualPath = crossThreadCopy(resolvedVirtualPath), entryType, completionCallback = WTFMove(completionCallback)]() mutable {
+ if (!entryType) {
+ completionCallback(Exception { NotFoundError, ASCIILiteral("Cannot find entry at given path") });
+ return;
+ }
+ switch (entryType.value()) {
+ case FileMetadata::Type::Directory:
completionCallback(Ref<FileSystemEntry> { FileSystemDirectoryEntry::create(context, *this, resolvedVirtualPath) });
break;
- case FileMetadata::TypeFile:
+ case FileMetadata::Type::File:
completionCallback(Ref<FileSystemEntry> { FileSystemFileEntry::create(context, *this, resolvedVirtualPath) });
break;
default:
auto virtualPath = fileEntry.virtualPath();
auto fullPath = evaluatePath(virtualPath);
m_workQueue->dispatch([this, context = makeRef(context), fullPath = crossThreadCopy(fullPath), virtualPath = crossThreadCopy(virtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
- auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::TypeFile);
+ auto validatedVirtualPath = validatePathIsExpectedType(fullPath, WTFMove(virtualPath), FileMetadata::Type::File);
callOnMainThread([this, context = WTFMove(context), fullPath = crossThreadCopy(fullPath), validatedVirtualPath = crossThreadCopy(validatedVirtualPath), completionCallback = WTFMove(completionCallback)]() mutable {
if (validatedVirtualPath.hasException())
completionCallback(validatedVirtualPath.releaseException());
static void appendDirectoryFiles(const String& directory, const String& relativePath, Vector<RefPtr<File>>& fileObjects)
{
for (auto& childPath : listDirectory(directory, "*")) {
- FileMetadata metadata;
- if (!getFileMetadata(childPath, metadata, ShouldFollowSymbolicLinks::No))
+ auto metadata = fileMetadata(childPath);
+ if (!metadata)
continue;
- if (metadata.isHidden)
+ if (metadata.value().isHidden)
continue;
String childRelativePath = relativePath + "/" + pathGetFileName(childPath);
- if (metadata.type == FileMetadata::TypeDirectory)
+ if (metadata.value().type == FileMetadata::Type::Directory)
appendDirectoryFiles(childPath, childRelativePath, fileObjects);
- else if (metadata.type == FileMetadata::TypeFile)
+ else if (metadata.value().type == FileMetadata::Type::File)
fileObjects.append(File::createWithRelativePath(childPath, childRelativePath));
}
}
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#ifndef FileMetadata_h
-#define FileMetadata_h
-
-#include "FileSystem.h"
-#include <wtf/text/WTFString.h>
+#pragma once
namespace WebCore {
struct FileMetadata {
- FileMetadata() = default;
-
// The last modification time of the file, in seconds.
- // The value 0.0 means that the time is not set.
- double modificationTime { invalidFileTime() };
+ double modificationTime;
// The length of the file in bytes.
- // The value -1 means that the length is not set.
- long long length { -1 };
+ long long length;
- bool isHidden { false };
+ bool isHidden;
- enum Type { TypeUnknown, TypeFile, TypeDirectory, TypeSymbolicLink };
- Type type { TypeUnknown };
+ enum class Type { File, Directory, SymbolicLink };
+ Type type;
};
} // namespace WebCore
-
-#endif // FileMetadata_h
bool fileIsDirectory(const String& path, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
{
- FileMetadata metadata;
- if (!getFileMetadata(path, metadata, shouldFollowSymbolicLinks))
+ auto metadata = shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes ? fileMetadataFollowingSymlinks(path) : fileMetadata(path);
+ if (!metadata)
return false;
- return metadata.type == FileMetadata::TypeDirectory;
+ return metadata.value().type == FileMetadata::Type::Directory;
}
} // namespace WebCore
WEBCORE_EXPORT bool getFileSize(PlatformFileHandle, long long& result);
WEBCORE_EXPORT bool getFileModificationTime(const String&, time_t& result);
WEBCORE_EXPORT bool getFileCreationTime(const String&, time_t& result); // Not all platforms store file creation time.
-WEBCORE_EXPORT bool getFileMetadata(const String&, FileMetadata&, ShouldFollowSymbolicLinks);
+WEBCORE_EXPORT std::optional<FileMetadata> fileMetadata(const String& path);
+WEBCORE_EXPORT std::optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path);
bool fileIsDirectory(const String&, ShouldFollowSymbolicLinks);
WEBCORE_EXPORT String pathByAppendingComponent(const String& path, const String& component);
String pathByAppendingComponents(const String& path, const Vector<String>& components);
return true;
}
-bool getFileMetadata(const String& path, FileMetadata& metadata, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
+static FileMetadata::Type toFileMetataType(GStatBuf statResult)
{
- 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;
+}
- if (shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes) {
- if (!getFileStat(path, &statResult))
- return false;
- } else {
- if (!getFileLStat(path, &statResult))
- return false;
- }
+static std::optional<FileMetadata> fileMetadataUsingFunction(const String& path, bool (*statFunc)(const String&, GStatBuf*))
+{
+ GStatBuf statResult;
+ if (!statFunc(path, &statResult))
+ return std::nullopt;
String filename = pathGetFileName(path);
- metadata.isHidden = !filename.isEmpty() && filename[0] == '.';
- metadata.modificationTime = statResult.st_mtime;
- metadata.length = statResult.st_size;
- if (S_ISDIR(statResult.st_mode))
- metadata.type = FileMetadata::TypeDirectory;
- else if (S_ISLNK(statResult.st_mode))
- metadata.type = FileMetadata::TypeSymbolicLink;
- else
- metadata.type = FileMetadata::TypeFile;
- return true;
+ bool isHidden = !filename.isEmpty() && filename[0] == '.';
+
+ return FileMetadata {
+ static_cast<double>(statResult.st_mtime),
+ statResult.st_size,
+ isHidden,
+ toFileMetataType(statResult)
+ };
+}
+
+std::optional<FileMetadata> fileMetadata(const String& path)
+{
+ return fileMetadataUsingFunction(path, &getFileLStat);
+}
+
+std::optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
+{
+ return fileMetadataUsingFunction(path, &getFileStat);
}
String pathByAppendingComponent(const String& path, const String& component)
#include "File.h"
#include "FileMetadata.h"
+#include "FileSystem.h"
namespace WebCore {
#endif
// FIXME: Some platforms provide better ways to listen for file system object changes, consider using these.
- FileMetadata metadata;
- if (!getFileMetadata(m_path, metadata, ShouldFollowSymbolicLinks::Yes))
+ auto metadata = fileMetadataFollowingSymlinks(m_path);
+ if (!metadata)
return;
- m_expectedModificationTime = metadata.modificationTime;
+ m_expectedModificationTime = metadata.value().modificationTime;
#if ENABLE(FILE_REPLACEMENT)
if (m_replacementShouldBeGenerated)
return;
#endif
- m_size = metadata.length;
+ m_size = metadata.value().length;
}
void BlobDataFileReference::prepareForFileAccess()
#if ENABLE(FILE_REPLACEMENT)
#include "FileMetadata.h"
+#include "FileSystem.h"
#include <wtf/SoftLinking.h>
#include <wtf/text/CString.h>
m_replacementShouldBeGenerated = false;
if (!m_replacementPath.isNull()) {
- FileMetadata metadata;
- if (getFileMetadata(m_replacementPath, metadata, ShouldFollowSymbolicLinks::Yes))
- m_size = metadata.length;
+ if (auto metadata = fileMetadataFollowingSymlinks(m_replacementPath))
+ m_size = metadata.value().length;
}
revokeFileAccess();
return true;
}
-bool getFileMetadata(const String& path, FileMetadata& metadata, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
+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 std::optional<FileMetadata> fileMetadataUsingFunction(const String& path, int (*statFunc)(const char*, struct stat*))
{
CString fsRep = fileSystemRepresentation(path);
if (!fsRep.data() || fsRep.data()[0] == '\0')
- return false;
+ return std::nullopt;
struct stat fileInfo;
-
- if (shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes) {
- if (stat(fsRep.data(), &fileInfo))
- return false;
- } else {
- if (lstat(fsRep.data(), &fileInfo))
- return false;
- }
+ if (statFunc(fsRep.data(), &fileInfo))
+ return std::nullopt;
String filename = pathGetFileName(path);
+ bool isHidden = !filename.isEmpty() && filename[0] == '.';
+ return FileMetadata {
+ static_cast<double>(fileInfo.st_mtime),
+ fileInfo.st_size,
+ isHidden,
+ toFileMetataType(fileInfo)
+ };
+}
- metadata.modificationTime = fileInfo.st_mtime;
- metadata.isHidden = !filename.isEmpty() && filename[0] == '.';
- metadata.length = fileInfo.st_size;
- if (S_ISDIR(fileInfo.st_mode))
- metadata.type = FileMetadata::TypeDirectory;
- else if (S_ISLNK(fileInfo.st_mode))
- metadata.type = FileMetadata::TypeSymbolicLink;
- else
- metadata.type = FileMetadata::TypeFile;
- return true;
+std::optional<FileMetadata> fileMetadata(const String& path)
+{
+ return fileMetadataUsingFunction(path, &lstat);
+}
+
+std::optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
+{
+ return fileMetadataUsingFunction(path, &stat);
}
bool createSymbolicLink(const String& targetPath, const String& symbolicLinkPath)
return String::adopt(WTFMove(buffer));
}
-bool getFileMetadata(const String& path, FileMetadata& metadata, ShouldFollowSymbolicLinks shouldFollowSymbolicLinks)
+static inline 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 std::optional<FileMetadata> findDataToFileMetadata(WIN32_FIND_DATAW findData)
+{
+ long long length;
+ if (!getFileSizeFromFindData(findData, length))
+ return std::nullopt;
+
+ time_t modificationTime;
+ getFileModificationTimeFromFindData(findData, modificationTime);
+
+ return FileMetadata {
+ static_cast<double>(modificationTime),
+ length,
+ findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN,
+ toFileMetadataType(findData)
+ };
+}
+
+std::optional<FileMetadata> fileMetadata(const String& path)
{
WIN32_FIND_DATAW findData;
if (!getFindData(path, findData))
- return false;
+ return std::nullopt;
- bool isSymbolicLink = findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT && findData.dwReserved0 == IO_REPARSE_TAG_SYMLINK;
- if (isSymbolicLink && shouldFollowSymbolicLinks == ShouldFollowSymbolicLinks::Yes) {
+ return findDataToFileMetadata(findData);
+}
+
+std::optional<FileMetadata> fileMetadataFollowingSymlinks(const String& path)
+{
+ WIN32_FIND_DATAW findData;
+ if (!getFindData(path, findData))
+ return std::nullopt;
+
+ if (isSymbolicLink(findData)) {
String targetPath = getFinalPathName(path);
if (targetPath.isNull())
- return false;
+ return std::nullopt;
if (!getFindData(targetPath, findData))
- return false;
- isSymbolicLink = false;
+ return std::nullopt;
}
- if (!getFileSizeFromFindData(findData, metadata.length))
- return false;
-
- time_t modificationTime;
- getFileModificationTimeFromFindData(findData, modificationTime);
- metadata.modificationTime = modificationTime;
- metadata.isHidden = findData.dwFileAttributes & FILE_ATTRIBUTE_HIDDEN;
- if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
- metadata.type = FileMetadata::TypeDirectory;
- else if (isSymbolicLink)
- metadata.type = FileMetadata::TypeSymbolicLink;
- else
- metadata.type = FileMetadata::TypeFile;
-
- return true;
+ return findDataToFileMetadata(findData);
}
bool createSymbolicLink(const String& targetPath, const String& symbolicLinkPath)
+2017-09-03 Chris Dumez <cdumez@apple.com>
+
+ Have getFileMetadata() return a std::optional<FileMetadata>
+ https://bugs.webkit.org/show_bug.cgi?id=176293
+
+ Reviewed by Darin Adler.
+
+ * TestWebKitAPI/Tests/WebCore/FileSystem.cpp:
+ (TestWebKitAPI::TEST_F):
+
2017-09-02 Filip Pizlo <fpizlo@apple.com>
WSL should support structs
TEST_F(FileSystemTest, GetFileMetadataSymlink)
{
- FileMetadata symlinkMetadata;
- EXPECT_TRUE(getFileMetadata(tempFileSymlinkPath(), symlinkMetadata, ShouldFollowSymbolicLinks::No));
- EXPECT_TRUE(symlinkMetadata.type == FileMetadata::TypeSymbolicLink);
- EXPECT_FALSE(static_cast<size_t>(symlinkMetadata.length) == strlen(FileSystemTestData));
-
- FileMetadata targetMetadata;
- EXPECT_TRUE(getFileMetadata(tempFileSymlinkPath(), targetMetadata, ShouldFollowSymbolicLinks::Yes));
- EXPECT_TRUE(targetMetadata.type == FileMetadata::TypeFile);
- EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata.length));
+ auto symlinkMetadata = fileMetadata(tempFileSymlinkPath());
+ ASSERT_TRUE(symlinkMetadata.has_value());
+ EXPECT_TRUE(symlinkMetadata.value().type == FileMetadata::Type::SymbolicLink);
+ EXPECT_FALSE(static_cast<size_t>(symlinkMetadata.value().length) == strlen(FileSystemTestData));
+
+ auto targetMetadata = fileMetadataFollowingSymlinks(tempFileSymlinkPath());
+ ASSERT_TRUE(targetMetadata.has_value());
+ EXPECT_TRUE(targetMetadata.value().type == FileMetadata::Type::File);
+ EXPECT_EQ(strlen(FileSystemTestData), static_cast<size_t>(targetMetadata.value().length));
}
}