NetworkCacheFileSystem.cpp [plain text]
#include "config.h"
#include "NetworkCacheFileSystem.h"
#include "Logging.h"
#include <wtf/Assertions.h>
#include <wtf/FileSystem.h>
#include <wtf/Function.h>
#include <wtf/text/CString.h>
#if !OS(WINDOWS)
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#else
#include <windows.h>
#endif
#if PLATFORM(IOS_FAMILY) && !PLATFORM(IOS_FAMILY_SIMULATOR)
#include <sys/attr.h>
#include <unistd.h>
#endif
#if USE(SOUP)
#include <gio/gio.h>
#include <wtf/glib/GRefPtr.h>
#endif
namespace WebKit {
namespace NetworkCache {
void traverseDirectory(const String& path, const Function<void (const String&, DirectoryEntryType)>& function)
{
auto entries = FileSystem::listDirectory(path, "*"_s);
for (auto& entry : entries) {
auto type = FileSystem::fileIsDirectory(entry, FileSystem::ShouldFollowSymbolicLinks::No) ? DirectoryEntryType::Directory : DirectoryEntryType::File;
function(FileSystem::pathGetFileName(entry), type);
}
}
void deleteDirectoryRecursively(const String& path)
{
traverseDirectory(path, [&path](const String& name, DirectoryEntryType type) {
String entryPath = FileSystem::pathByAppendingComponent(path, name);
switch (type) {
case DirectoryEntryType::File:
FileSystem::deleteFile(entryPath);
break;
case DirectoryEntryType::Directory:
deleteDirectoryRecursively(entryPath);
break;
}
});
FileSystem::deleteEmptyDirectory(path);
}
FileTimes fileTimes(const String& path)
{
#if HAVE(STAT_BIRTHTIME)
struct stat fileInfo;
if (stat(FileSystem::fileSystemRepresentation(path).data(), &fileInfo))
return { };
return { WallTime::fromRawSeconds(fileInfo.st_birthtime), WallTime::fromRawSeconds(fileInfo.st_mtime) };
#elif USE(SOUP)
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(FileSystem::fileSystemRepresentation(path).data()));
GRefPtr<GFileInfo> fileInfo = adoptGRef(g_file_query_info(file.get(), "xattr::birthtime,time::modified", G_FILE_QUERY_INFO_NONE, nullptr, nullptr));
if (!fileInfo)
return { };
const char* birthtimeString = g_file_info_get_attribute_string(fileInfo.get(), "xattr::birthtime");
if (!birthtimeString)
return { };
return { WallTime::fromRawSeconds(g_ascii_strtoull(birthtimeString, nullptr, 10)),
WallTime::fromRawSeconds(g_file_info_get_attribute_uint64(fileInfo.get(), "time::modified")) };
#elif OS(WINDOWS)
auto createTime = FileSystem::getFileCreationTime(path);
auto modifyTime = FileSystem::getFileModificationTime(path);
return { createTime.valueOr(WallTime()), modifyTime.valueOr(WallTime()) };
#endif
}
void updateFileModificationTimeIfNeeded(const String& path)
{
auto times = fileTimes(path);
if (times.creation != times.modification) {
if (WallTime::now() - times.modification < 1_h)
return;
}
#if !OS(WINDOWS)
utimes(FileSystem::fileSystemRepresentation(path).data(), nullptr);
#else
FILETIME time;
GetSystemTimeAsFileTime(&time);
auto file = CreateFile(path.wideCharacters().data(), GENERIC_WRITE, 0, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
if (file == INVALID_HANDLE_VALUE)
return;
SetFileTime(file, &time, &time, &time);
CloseHandle(file);
#endif
}
}
}