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

Side by Side Diff: src/DefaultFileSystem.cpp

Issue 10421060: Make sure to work properly with Unicode paths on Windows (Closed)
Patch Set: Created May 14, 2013, 1:38 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
« no previous file with comments | « no previous file | test/DefaultFileSystem.cpp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
(...skipping 28 matching lines...) Expand all
39 namespace 39 namespace
40 { 40 {
41 class RuntimeErrorWithErrno : public std::runtime_error 41 class RuntimeErrorWithErrno : public std::runtime_error
42 { 42 {
43 public: 43 public:
44 explicit RuntimeErrorWithErrno(const std::string& message) 44 explicit RuntimeErrorWithErrno(const std::string& message)
45 : std::runtime_error(message + " (" + strerror(errno) + ")") 45 : std::runtime_error(message + " (" + strerror(errno) + ")")
46 { 46 {
47 } 47 }
48 }; 48 };
49
50 #ifdef WIN32
51 // Paths need to be converted from UTF-8 to UTF-16 on Windows.
52 std::wstring NormalizePath(const std::string& path)
53 {
54 return Utils::ToUTF16String(path, path.length());
55 }
56
57 #define rename _wrename
58 #define remove _wremove
59 #else
60 // POSIX systems: assume that file system encoding is UTF-8 and just use the
61 // file paths as they are.
62 #define NormalizePath(path) (path)
Felix Dahlke 2013/05/17 09:38:14 Would rather see a function here, macros can cause
63 #endif
49 } 64 }
50 65
51 std::tr1::shared_ptr<std::istream> 66 std::tr1::shared_ptr<std::istream>
52 DefaultFileSystem::Read(const std::string& path) const 67 DefaultFileSystem::Read(const std::string& path) const
53 { 68 {
54 return std::tr1::shared_ptr<std::istream>(new std::ifstream(path.c_str())); 69 return std::tr1::shared_ptr<std::istream>(new std::ifstream(NormalizePath(path ).c_str()));
55 } 70 }
56 71
57 void DefaultFileSystem::Write(const std::string& path, 72 void DefaultFileSystem::Write(const std::string& path,
58 std::tr1::shared_ptr<std::ostream> data) 73 std::tr1::shared_ptr<std::ostream> data)
59 { 74 {
60 std::ofstream file(path.c_str()); 75 std::ofstream file(NormalizePath(path).c_str());
61 file << Utils::Slurp(*data); 76 file << Utils::Slurp(*data);
62 } 77 }
63 78
64 void DefaultFileSystem::Move(const std::string& fromPath, 79 void DefaultFileSystem::Move(const std::string& fromPath,
65 const std::string& toPath) 80 const std::string& toPath)
66 { 81 {
67 if (rename(fromPath.c_str(), toPath.c_str())) 82 if (rename(NormalizePath(fromPath).c_str(), NormalizePath(toPath).c_str()))
68 throw RuntimeErrorWithErrno("Failed to move " + fromPath + " to " + toPath); 83 throw RuntimeErrorWithErrno("Failed to move " + fromPath + " to " + toPath);
69 } 84 }
70 85
71 void DefaultFileSystem::Remove(const std::string& path) 86 void DefaultFileSystem::Remove(const std::string& path)
72 { 87 {
73 if (remove(path.c_str())) 88 if (remove(NormalizePath(path).c_str()))
74 throw RuntimeErrorWithErrno("Failed to remove " + path); 89 throw RuntimeErrorWithErrno("Failed to remove " + path);
75 } 90 }
76 91
77 FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const 92 FileSystem::StatResult DefaultFileSystem::Stat(const std::string& path) const
78 { 93 {
79 FileSystem::StatResult result; 94 FileSystem::StatResult result;
80 #ifdef WIN32 95 #ifdef WIN32
81 WIN32_FILE_ATTRIBUTE_DATA data; 96 WIN32_FILE_ATTRIBUTE_DATA data;
82 std::wstring wpath = Utils::ToUTF16String(path, path.length()); 97 if (!GetFileAttributesExW(NormalizePath(path).c_str(), GetFileExInfoStandard, &data))
83 if (!GetFileAttributesExW(wpath.c_str(), GetFileExInfoStandard, &data))
84 { 98 {
85 DWORD err = GetLastError(); 99 DWORD err = GetLastError();
86 if (err == ERROR_FILE_NOT_FOUND || ERROR_PATH_NOT_FOUND || ERROR_INVALID_DRI VE) 100 if (err == ERROR_FILE_NOT_FOUND || ERROR_PATH_NOT_FOUND || ERROR_INVALID_DRI VE)
87 return result; 101 return result;
88 throw RuntimeErrorWithErrno("Unable to stat " + path); 102 throw RuntimeErrorWithErrno("Unable to stat " + path);
89 } 103 }
90 104
91 result.exists = true; 105 result.exists = true;
92 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 106 if (data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
93 { 107 {
(...skipping 10 matching lines...) Expand all
104 #define FILE_TIME_TO_UNIX_EPOCH_OFFSET 116444736000000000LL 118 #define FILE_TIME_TO_UNIX_EPOCH_OFFSET 116444736000000000LL
105 #define FILE_TIME_TO_MILLISECONDS_FACTOR 10000 119 #define FILE_TIME_TO_MILLISECONDS_FACTOR 10000
106 ULARGE_INTEGER time; 120 ULARGE_INTEGER time;
107 time.LowPart = data.ftLastWriteTime.dwLowDateTime; 121 time.LowPart = data.ftLastWriteTime.dwLowDateTime;
108 time.HighPart = data.ftLastWriteTime.dwHighDateTime; 122 time.HighPart = data.ftLastWriteTime.dwHighDateTime;
109 result.lastModified = (time.QuadPart - FILE_TIME_TO_UNIX_EPOCH_OFFSET) / 123 result.lastModified = (time.QuadPart - FILE_TIME_TO_UNIX_EPOCH_OFFSET) /
110 FILE_TIME_TO_MILLISECONDS_FACTOR; 124 FILE_TIME_TO_MILLISECONDS_FACTOR;
111 return result; 125 return result;
112 #else 126 #else
113 struct stat nativeStat; 127 struct stat nativeStat;
114 const int failure = stat(path.c_str(), &nativeStat); 128 const int failure = stat(NormalizePath(path).c_str(), &nativeStat);
115 if (failure) 129 if (failure)
116 { 130 {
117 if (errno == ENOENT) 131 if (errno == ENOENT)
118 return result; 132 return result;
119 throw RuntimeErrorWithErrno("Unable to stat " + path); 133 throw RuntimeErrorWithErrno("Unable to stat " + path);
120 } 134 }
121 result.exists = true; 135 result.exists = true;
122 result.isFile = S_ISREG(nativeStat.st_mode); 136 result.isFile = S_ISREG(nativeStat.st_mode);
123 result.isDirectory = S_ISDIR(nativeStat.st_mode); 137 result.isDirectory = S_ISDIR(nativeStat.st_mode);
124 138
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
163 void DefaultFileSystem::SetBasePath(const std::string& path) 177 void DefaultFileSystem::SetBasePath(const std::string& path)
164 { 178 {
165 basePath = path; 179 basePath = path;
166 180
167 if ((*basePath.rbegin() == PATH_SEPARATOR)) 181 if ((*basePath.rbegin() == PATH_SEPARATOR))
168 { 182 {
169 basePath.resize(basePath.size() - 1); 183 basePath.resize(basePath.size() - 1);
170 } 184 }
171 } 185 }
172 186
OLDNEW
« no previous file with comments | « no previous file | test/DefaultFileSystem.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld