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

Side by Side 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.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <http://adblockplus.org/>, 2 * This file is part of Adblock Plus <http://adblockplus.org/>,
3 * Copyright (C) 2006-2013 Eyeo GmbH 3 * Copyright (C) 2006-2013 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include <AdblockPlus/DefaultFileSystem.h> 18 #include <AdblockPlus/DefaultFileSystem.h>
19 #include <cstdio> 19 #include <cstdio>
20 #include <cstring> 20 #include <cstring>
21 #include <fstream> 21 #include <fstream>
22 #include <stdexcept> 22 #include <stdexcept>
23 23
24 #include <cerrno>
25 #include <sys/types.h> 24 #include <sys/types.h>
26 #include <sys/stat.h>
27 25
28 #ifdef _WIN32 26 #ifdef _WIN32
29 #ifndef S_ISDIR 27 #include <windows.h>
30 #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
31 #include <Shlobj.h> 28 #include <Shlobj.h>
32 #include <Shlwapi.h> 29 #include <Shlwapi.h>
33 #endif 30 #else
34 31 #include <sys/stat.h>
35 #ifndef S_ISREG 32 #include <cerrno>
36 #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
37 #endif
38 #endif 33 #endif
39 34
40 #include "../src/Utils.h" 35 #include "../src/Utils.h"
41 36
42 using namespace AdblockPlus; 37 using namespace AdblockPlus;
43 38
44 namespace 39 namespace
45 { 40 {
46 class RuntimeErrorWithErrno : public std::runtime_error 41 class RuntimeErrorWithErrno : public std::runtime_error
47 { 42 {
(...skipping 24 matching lines...) Expand all
72 if (rename(fromPath.c_str(), toPath.c_str())) 67 if (rename(fromPath.c_str(), toPath.c_str()))
73 throw RuntimeErrorWithErrno("Failed to move " + fromPath + " to " + toPath); 68 throw RuntimeErrorWithErrno("Failed to move " + fromPath + " to " + toPath);
74 } 69 }
75 70
76 void DefaultFileSystem::Remove(const std::string& path) 71 void DefaultFileSystem::Remove(const std::string& path)
77 { 72 {
78 if (remove(path.c_str())) 73 if (remove(path.c_str()))
79 throw RuntimeErrorWithErrno("Failed to remove " + path); 74 throw RuntimeErrorWithErrno("Failed to remove " + path);
80 } 75 }
81 76
82 /*
83 * In order to get millisecond resolution for modification times, it's necessary to use the 'stat' structure defined in
84 * POSIX 2008, which has 'struct timespec st_mtim' instead of 'time_t st_mtime'. Use "#define _POSIX_C_SOURCE 200809L"
85 * before the headers to invoke. The trouble is that not all systems may have th is available, a category that includes
86 * MS Windows, and so we'll need multiple implementations.
87 */
88 FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const 77 FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const
89 { 78 {
79 FileSystem::StatResult result;
90 #ifdef WIN32 80 #ifdef WIN32
91 struct _stat nativeStat; 81 WIN32_FILE_ATTRIBUTE_DATA data;
92 const int failure = _stat(path.c_str(), &nativeStat); 82 std::wstring wpath = Utils::ToUTF16String(path, path.length());
83 if (!GetFileAttributesExW(wpath.c_str(), GetFileExInfoStandard, &data))
84 {
85 DWORD err = GetLastError();
86 if (err == ERROR_FILE_NOT_FOUND || ERROR_PATH_NOT_FOUND || ERROR_INVALID_DRI VE)
Felix Dahlke 2013/05/17 09:18:50 Shouldn't this be "err == ERROR_FILE_NOT_FOUND ||
87 return result;
88 throw RuntimeErrorWithErrno("Unable to stat " + path);
89 }
90
91 result.exists = true;
92 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
93 {
94 result.isFile = false;
95 result.isDirectory = true;
96 }
97 else
98 {
99 result.isFile = true;
100 result.isDirectory = false;
101 }
102
103 // See http://support.microsoft.com/kb/167296 on this conversion
104 #define FILE_TIME_TO_UNIX_EPOCH_OFFSET 116444736000000000LL
105 #define FILE_TIME_TO_MILLISECONDS_FACTOR 10000
106 ULARGE_INTEGER time;
107 time.LowPart = data.ftLastWriteTime.dwLowDateTime;
108 time.HighPart = data.ftLastWriteTime.dwHighDateTime;
109 result.lastModified = (time.QuadPart - FILE_TIME_TO_UNIX_EPOCH_OFFSET) /
110 FILE_TIME_TO_MILLISECONDS_FACTOR;
111 return result;
93 #else 112 #else
94 struct stat nativeStat; 113 struct stat nativeStat;
95 const int failure = stat(path.c_str(), &nativeStat); 114 const int failure = stat(path.c_str(), &nativeStat);
96 #endif 115 if (failure)
97 if (failure) { 116 {
98 if (errno == ENOENT) 117 if (errno == ENOENT)
99 return FileSystem::StatResult(); 118 return result;
100 throw RuntimeErrorWithErrno("Unable to stat " + path); 119 throw RuntimeErrorWithErrno("Unable to stat " + path);
101 } 120 }
102 FileSystem::StatResult result;
103 result.exists = true; 121 result.exists = true;
104 result.isFile = S_ISREG(nativeStat.st_mode); 122 result.isFile = S_ISREG(nativeStat.st_mode);
105 result.isDirectory = S_ISDIR(nativeStat.st_mode); 123 result.isDirectory = S_ISDIR(nativeStat.st_mode);
124
125 /*
126 * In order to get millisecond resolution for modification times, it's necessa ry to use the 'stat' structure defined in
127 * POSIX 2008, which has 'struct timespec st_mtim' instead of 'time_t st_mtime '. Use "#define _POSIX_C_SOURCE 200809L"
128 * before the headers to invoke. The trouble is that not all systems may have this available, a category that includes
129 * MS Windows, and so we'll need multiple implementations.
130 */
106 result.lastModified = static_cast<int64_t>(nativeStat.st_mtime) * 1000; 131 result.lastModified = static_cast<int64_t>(nativeStat.st_mtime) * 1000;
107 return result; 132 return result;
133 #endif
108 } 134 }
109 135
110 std::string DefaultFileSystem::Resolve(const std::string& path) const 136 std::string DefaultFileSystem::Resolve(const std::string& path) const
111 { 137 {
112 if (basePath == "") 138 if (basePath == "")
113 { 139 {
114 return path; 140 return path;
115 } 141 }
116 else 142 else
117 { 143 {
(...skipping 15 matching lines...) Expand all
133 void DefaultFileSystem::SetBasePath(const std::string& path) 159 void DefaultFileSystem::SetBasePath(const std::string& path)
134 { 160 {
135 basePath = path; 161 basePath = path;
136 162
137 if ((*basePath.rbegin() == PATH_SEPARATOR)) 163 if ((*basePath.rbegin() == PATH_SEPARATOR))
138 { 164 {
139 basePath.resize(basePath.size() - 1); 165 basePath.resize(basePath.size() - 1);
140 } 166 }
141 } 167 }
142 168
OLDNEW
« 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