Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Unified Diff: src/DefaultFileSystem.cpp

Issue 10518027: Don`t use stat() on Windows, use a Unicode-safe Windows function instead (Closed)
Patch Set: Created May 10, 2013, 3:09 p.m.
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View side-by-side diff with in-line comments
Download patch
« include/AdblockPlus/FileSystem.h ('K') | « include/AdblockPlus/FileSystem.h ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/DefaultFileSystem.cpp
===================================================================
--- a/src/DefaultFileSystem.cpp
+++ b/src/DefaultFileSystem.cpp
@@ -16,30 +16,25 @@
*/
#include <AdblockPlus/DefaultFileSystem.h>
#include <cstdio>
#include <cstring>
#include <fstream>
#include <stdexcept>
-#include <cerrno>
#include <sys/types.h>
-#include <sys/stat.h>
#ifdef _WIN32
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
+#include <windows.h>
#include <Shlobj.h>
#include <Shlwapi.h>
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
+#else
+#include <sys/stat.h>
+#include <cerrno>
#endif
#include "../src/Utils.h"
using namespace AdblockPlus;
namespace
{
@@ -74,42 +69,73 @@ void DefaultFileSystem::Move(const std::
}
void DefaultFileSystem::Remove(const std::string& path)
{
if (remove(path.c_str()))
throw RuntimeErrorWithErrno("Failed to remove " + path);
}
-/*
- * In order to get millisecond resolution for modification times, it's necessary to use the 'stat' structure defined in
- * POSIX 2008, which has 'struct timespec st_mtim' instead of 'time_t st_mtime'. Use "#define _POSIX_C_SOURCE 200809L"
- * before the headers to invoke. The trouble is that not all systems may have this available, a category that includes
- * MS Windows, and so we'll need multiple implementations.
- */
FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const
{
+ FileSystem::StatResult result;
#ifdef WIN32
- struct _stat nativeStat;
- const int failure = _stat(path.c_str(), &nativeStat);
+ WIN32_FILE_ATTRIBUTE_DATA data;
+ std::wstring wpath = Utils::ToUTF16String(path, path.length());
+ if (!GetFileAttributesExW(wpath.c_str(), GetFileExInfoStandard, &data))
+ {
+ DWORD err = GetLastError();
+ if (err == ERROR_FILE_NOT_FOUND || ERROR_PATH_NOT_FOUND || ERROR_INVALID_DRIVE)
Felix Dahlke 2013/05/17 09:18:50 Shouldn't this be "err == ERROR_FILE_NOT_FOUND ||
+ return result;
+ throw RuntimeErrorWithErrno("Unable to stat " + path);
+ }
+
+ result.exists = true;
+ if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
+ {
+ result.isFile = false;
+ result.isDirectory = true;
+ }
+ else
+ {
+ result.isFile = true;
+ result.isDirectory = false;
+ }
+
+ // See http://support.microsoft.com/kb/167296 on this conversion
+ #define FILE_TIME_TO_UNIX_EPOCH_OFFSET 116444736000000000LL
+ #define FILE_TIME_TO_MILLISECONDS_FACTOR 10000
+ ULARGE_INTEGER time;
+ time.LowPart = data.ftLastWriteTime.dwLowDateTime;
+ time.HighPart = data.ftLastWriteTime.dwHighDateTime;
+ result.lastModified = (time.QuadPart - FILE_TIME_TO_UNIX_EPOCH_OFFSET) /
+ FILE_TIME_TO_MILLISECONDS_FACTOR;
+ return result;
#else
struct stat nativeStat;
const int failure = stat(path.c_str(), &nativeStat);
-#endif
- if (failure) {
+ if (failure)
+ {
if (errno == ENOENT)
- return FileSystem::StatResult();
+ return result;
throw RuntimeErrorWithErrno("Unable to stat " + path);
}
- FileSystem::StatResult result;
result.exists = true;
result.isFile = S_ISREG(nativeStat.st_mode);
result.isDirectory = S_ISDIR(nativeStat.st_mode);
+
+ /*
+ * In order to get millisecond resolution for modification times, it's necessary to use the 'stat' structure defined in
+ * POSIX 2008, which has 'struct timespec st_mtim' instead of 'time_t st_mtime'. Use "#define _POSIX_C_SOURCE 200809L"
+ * before the headers to invoke. The trouble is that not all systems may have this available, a category that includes
+ * MS Windows, and so we'll need multiple implementations.
+ */
result.lastModified = static_cast<int64_t>(nativeStat.st_mtime) * 1000;
return result;
+#endif
}
std::string DefaultFileSystem::Resolve(const std::string& path) const
{
if (basePath == "")
{
return path;
}
« include/AdblockPlus/FileSystem.h ('K') | « include/AdblockPlus/FileSystem.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld