| 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; |
| } |