NetworkCacheFileSystem.cpp [plain text]
#include "config.h"
#include "NetworkCacheFileSystem.h"
#if ENABLE(NETWORK_CACHE)
#include <WebCore/FileSystem.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/time.h>
#include <wtf/text/CString.h>
#if USE(SOUP)
#include <gio/gio.h>
#include <wtf/glib/GRefPtr.h>
#endif
namespace WebKit {
namespace NetworkCache {
static DirectoryEntryType directoryEntryType(uint8_t dtype)
{
switch (dtype) {
case DT_DIR:
return DirectoryEntryType::Directory;
case DT_REG:
return DirectoryEntryType::File;
default:
ASSERT_NOT_REACHED();
return DirectoryEntryType::File;
}
}
void traverseDirectory(const String& path, const std::function<void (const String&, DirectoryEntryType)>& function)
{
DIR* dir = opendir(WebCore::fileSystemRepresentation(path).data());
if (!dir)
return;
dirent* dp;
while ((dp = readdir(dir))) {
if (dp->d_type != DT_DIR && dp->d_type != DT_REG)
continue;
const char* name = dp->d_name;
if (!strcmp(name, ".") || !strcmp(name, ".."))
continue;
auto nameString = String::fromUTF8(name);
if (nameString.isNull())
continue;
function(nameString, directoryEntryType(dp->d_type));
}
closedir(dir);
}
void deleteDirectoryRecursively(const String& path)
{
traverseDirectory(path, [&path](const String& name, DirectoryEntryType type) {
String entryPath = WebCore::pathByAppendingComponent(path, name);
switch (type) {
case DirectoryEntryType::File:
WebCore::deleteFile(entryPath);
break;
case DirectoryEntryType::Directory:
deleteDirectoryRecursively(entryPath);
break;
}
});
WebCore::deleteEmptyDirectory(path);
}
FileTimes fileTimes(const String& path)
{
#if HAVE(STAT_BIRTHTIME)
struct stat fileInfo;
if (stat(WebCore::fileSystemRepresentation(path).data(), &fileInfo))
return { };
return { std::chrono::system_clock::from_time_t(fileInfo.st_birthtime), std::chrono::system_clock::from_time_t(fileInfo.st_mtime) };
#elif USE(SOUP)
GRefPtr<GFile> file = adoptGRef(g_file_new_for_path(WebCore::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 { std::chrono::system_clock::from_time_t(g_ascii_strtoull(birthtimeString, nullptr, 10)),
std::chrono::system_clock::from_time_t(g_file_info_get_attribute_uint64(fileInfo.get(), "time::modified")) };
#endif
}
void updateFileModificationTimeIfNeeded(const String& path)
{
auto times = fileTimes(path);
if (times.creation != times.modification) {
if (std::chrono::system_clock::now() - times.modification < std::chrono::hours(1))
return;
}
utimes(WebCore::fileSystemRepresentation(path).data(), nullptr);
}
}
}
#endif // ENABLE(NETWORK_CACHE)