Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(95)

Side by Side Diff: base/files/file_win.cc

Issue 1124763003: Update from https://crrev.com/327068 (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: update nacl, buildtools, fix display_change_notifier_unittest Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/files/file.h" 5 #include "base/files/file.h"
6 6
7 #include <io.h> 7 #include <io.h>
8 8
9 #include "base/files/file_path.h" 9 #include "base/files/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/metrics/sparse_histogram.h" 11 #include "base/metrics/sparse_histogram.h"
12 #include "base/threading/thread_restrictions.h" 12 #include "base/threading/thread_restrictions.h"
13 13
14 namespace base { 14 namespace base {
15 15
16 // Make sure our Whence mappings match the system headers. 16 // Make sure our Whence mappings match the system headers.
17 COMPILE_ASSERT(File::FROM_BEGIN == FILE_BEGIN && 17 COMPILE_ASSERT(File::FROM_BEGIN == FILE_BEGIN &&
18 File::FROM_CURRENT == FILE_CURRENT && 18 File::FROM_CURRENT == FILE_CURRENT &&
19 File::FROM_END == FILE_END, whence_matches_system); 19 File::FROM_END == FILE_END, whence_matches_system);
20 20
21 void File::InitializeUnsafe(const FilePath& name, uint32 flags) {
22 base::ThreadRestrictions::AssertIOAllowed();
23 DCHECK(!IsValid());
24
25 DWORD disposition = 0;
26
27 if (flags & FLAG_OPEN)
28 disposition = OPEN_EXISTING;
29
30 if (flags & FLAG_CREATE) {
31 DCHECK(!disposition);
32 disposition = CREATE_NEW;
33 }
34
35 if (flags & FLAG_OPEN_ALWAYS) {
36 DCHECK(!disposition);
37 disposition = OPEN_ALWAYS;
38 }
39
40 if (flags & FLAG_CREATE_ALWAYS) {
41 DCHECK(!disposition);
42 DCHECK(flags & FLAG_WRITE);
43 disposition = CREATE_ALWAYS;
44 }
45
46 if (flags & FLAG_OPEN_TRUNCATED) {
47 DCHECK(!disposition);
48 DCHECK(flags & FLAG_WRITE);
49 disposition = TRUNCATE_EXISTING;
50 }
51
52 if (!disposition) {
53 NOTREACHED();
54 return;
55 }
56
57 DWORD access = 0;
58 if (flags & FLAG_WRITE)
59 access = GENERIC_WRITE;
60 if (flags & FLAG_APPEND) {
61 DCHECK(!access);
62 access = FILE_APPEND_DATA;
63 }
64 if (flags & FLAG_READ)
65 access |= GENERIC_READ;
66 if (flags & FLAG_WRITE_ATTRIBUTES)
67 access |= FILE_WRITE_ATTRIBUTES;
68 if (flags & FLAG_EXECUTE)
69 access |= GENERIC_EXECUTE;
70
71 DWORD sharing = (flags & FLAG_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ;
72 if (!(flags & FLAG_EXCLUSIVE_WRITE))
73 sharing |= FILE_SHARE_WRITE;
74 if (flags & FLAG_SHARE_DELETE)
75 sharing |= FILE_SHARE_DELETE;
76
77 DWORD create_flags = 0;
78 if (flags & FLAG_ASYNC)
79 create_flags |= FILE_FLAG_OVERLAPPED;
80 if (flags & FLAG_TEMPORARY)
81 create_flags |= FILE_ATTRIBUTE_TEMPORARY;
82 if (flags & FLAG_HIDDEN)
83 create_flags |= FILE_ATTRIBUTE_HIDDEN;
84 if (flags & FLAG_DELETE_ON_CLOSE)
85 create_flags |= FILE_FLAG_DELETE_ON_CLOSE;
86 if (flags & FLAG_BACKUP_SEMANTICS)
87 create_flags |= FILE_FLAG_BACKUP_SEMANTICS;
88
89 file_.Set(CreateFile(name.value().c_str(), access, sharing, NULL,
90 disposition, create_flags, NULL));
91
92 if (file_.IsValid()) {
93 error_details_ = FILE_OK;
94 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
95
96 if (flags & (FLAG_OPEN_ALWAYS))
97 created_ = (ERROR_ALREADY_EXISTS != GetLastError());
98 else if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
99 created_ = true;
100 } else {
101 error_details_ = OSErrorToFileError(GetLastError());
102 }
103 }
104
105 bool File::IsValid() const { 21 bool File::IsValid() const {
106 return file_.IsValid(); 22 return file_.IsValid();
107 } 23 }
108 24
109 PlatformFile File::GetPlatformFile() const { 25 PlatformFile File::GetPlatformFile() const {
110 return file_.Get(); 26 return file_.Get();
111 } 27 }
112 28
113 PlatformFile File::TakePlatformFile() { 29 PlatformFile File::TakePlatformFile() {
114 return file_.Take(); 30 return file_.Take();
115 } 31 }
116 32
117 void File::Close() { 33 void File::Close() {
118 if (file_.IsValid()) { 34 if (file_.IsValid()) {
119 base::ThreadRestrictions::AssertIOAllowed(); 35 ThreadRestrictions::AssertIOAllowed();
120 file_.Close(); 36 file_.Close();
121 } 37 }
122 } 38 }
123 39
124 int64 File::Seek(Whence whence, int64 offset) { 40 int64 File::Seek(Whence whence, int64 offset) {
125 base::ThreadRestrictions::AssertIOAllowed(); 41 ThreadRestrictions::AssertIOAllowed();
126 DCHECK(IsValid()); 42 DCHECK(IsValid());
127 43
128 LARGE_INTEGER distance, res; 44 LARGE_INTEGER distance, res;
129 distance.QuadPart = offset; 45 distance.QuadPart = offset;
130 DWORD move_method = static_cast<DWORD>(whence); 46 DWORD move_method = static_cast<DWORD>(whence);
131 if (!SetFilePointerEx(file_.Get(), distance, &res, move_method)) 47 if (!SetFilePointerEx(file_.Get(), distance, &res, move_method))
132 return -1; 48 return -1;
133 return res.QuadPart; 49 return res.QuadPart;
134 } 50 }
135 51
136 int File::Read(int64 offset, char* data, int size) { 52 int File::Read(int64 offset, char* data, int size) {
137 base::ThreadRestrictions::AssertIOAllowed(); 53 ThreadRestrictions::AssertIOAllowed();
138 DCHECK(IsValid()); 54 DCHECK(IsValid());
139 DCHECK(!async_); 55 DCHECK(!async_);
140 if (size < 0) 56 if (size < 0)
141 return -1; 57 return -1;
142 58
143 LARGE_INTEGER offset_li; 59 LARGE_INTEGER offset_li;
144 offset_li.QuadPart = offset; 60 offset_li.QuadPart = offset;
145 61
146 OVERLAPPED overlapped = {0}; 62 OVERLAPPED overlapped = {0};
147 overlapped.Offset = offset_li.LowPart; 63 overlapped.Offset = offset_li.LowPart;
148 overlapped.OffsetHigh = offset_li.HighPart; 64 overlapped.OffsetHigh = offset_li.HighPart;
149 65
150 DWORD bytes_read; 66 DWORD bytes_read;
151 if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped)) 67 if (::ReadFile(file_.Get(), data, size, &bytes_read, &overlapped))
152 return bytes_read; 68 return bytes_read;
153 if (ERROR_HANDLE_EOF == GetLastError()) 69 if (ERROR_HANDLE_EOF == GetLastError())
154 return 0; 70 return 0;
155 71
156 return -1; 72 return -1;
157 } 73 }
158 74
159 int File::ReadAtCurrentPos(char* data, int size) { 75 int File::ReadAtCurrentPos(char* data, int size) {
160 base::ThreadRestrictions::AssertIOAllowed(); 76 ThreadRestrictions::AssertIOAllowed();
161 DCHECK(IsValid()); 77 DCHECK(IsValid());
162 DCHECK(!async_); 78 DCHECK(!async_);
163 if (size < 0) 79 if (size < 0)
164 return -1; 80 return -1;
165 81
166 DWORD bytes_read; 82 DWORD bytes_read;
167 if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL)) 83 if (::ReadFile(file_.Get(), data, size, &bytes_read, NULL))
168 return bytes_read; 84 return bytes_read;
169 if (ERROR_HANDLE_EOF == GetLastError()) 85 if (ERROR_HANDLE_EOF == GetLastError())
170 return 0; 86 return 0;
171 87
172 return -1; 88 return -1;
173 } 89 }
174 90
175 int File::ReadNoBestEffort(int64 offset, char* data, int size) { 91 int File::ReadNoBestEffort(int64 offset, char* data, int size) {
176 return Read(offset, data, size); 92 return Read(offset, data, size);
177 } 93 }
178 94
179 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) { 95 int File::ReadAtCurrentPosNoBestEffort(char* data, int size) {
180 return ReadAtCurrentPos(data, size); 96 return ReadAtCurrentPos(data, size);
181 } 97 }
182 98
183 int File::Write(int64 offset, const char* data, int size) { 99 int File::Write(int64 offset, const char* data, int size) {
184 base::ThreadRestrictions::AssertIOAllowed(); 100 ThreadRestrictions::AssertIOAllowed();
185 DCHECK(IsValid()); 101 DCHECK(IsValid());
186 DCHECK(!async_); 102 DCHECK(!async_);
187 103
188 LARGE_INTEGER offset_li; 104 LARGE_INTEGER offset_li;
189 offset_li.QuadPart = offset; 105 offset_li.QuadPart = offset;
190 106
191 OVERLAPPED overlapped = {0}; 107 OVERLAPPED overlapped = {0};
192 overlapped.Offset = offset_li.LowPart; 108 overlapped.Offset = offset_li.LowPart;
193 overlapped.OffsetHigh = offset_li.HighPart; 109 overlapped.OffsetHigh = offset_li.HighPart;
194 110
195 DWORD bytes_written; 111 DWORD bytes_written;
196 if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped)) 112 if (::WriteFile(file_.Get(), data, size, &bytes_written, &overlapped))
197 return bytes_written; 113 return bytes_written;
198 114
199 return -1; 115 return -1;
200 } 116 }
201 117
202 int File::WriteAtCurrentPos(const char* data, int size) { 118 int File::WriteAtCurrentPos(const char* data, int size) {
203 base::ThreadRestrictions::AssertIOAllowed(); 119 ThreadRestrictions::AssertIOAllowed();
204 DCHECK(IsValid()); 120 DCHECK(IsValid());
205 DCHECK(!async_); 121 DCHECK(!async_);
206 if (size < 0) 122 if (size < 0)
207 return -1; 123 return -1;
208 124
209 DWORD bytes_written; 125 DWORD bytes_written;
210 if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL)) 126 if (::WriteFile(file_.Get(), data, size, &bytes_written, NULL))
211 return bytes_written; 127 return bytes_written;
212 128
213 return -1; 129 return -1;
214 } 130 }
215 131
216 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) { 132 int File::WriteAtCurrentPosNoBestEffort(const char* data, int size) {
217 return WriteAtCurrentPos(data, size); 133 return WriteAtCurrentPos(data, size);
218 } 134 }
219 135
220 int64 File::GetLength() { 136 int64 File::GetLength() {
221 base::ThreadRestrictions::AssertIOAllowed(); 137 ThreadRestrictions::AssertIOAllowed();
222 DCHECK(IsValid()); 138 DCHECK(IsValid());
223 LARGE_INTEGER size; 139 LARGE_INTEGER size;
224 if (!::GetFileSizeEx(file_.Get(), &size)) 140 if (!::GetFileSizeEx(file_.Get(), &size))
225 return -1; 141 return -1;
226 142
227 return static_cast<int64>(size.QuadPart); 143 return static_cast<int64>(size.QuadPart);
228 } 144 }
229 145
230 bool File::SetLength(int64 length) { 146 bool File::SetLength(int64 length) {
231 base::ThreadRestrictions::AssertIOAllowed(); 147 ThreadRestrictions::AssertIOAllowed();
232 DCHECK(IsValid()); 148 DCHECK(IsValid());
233 149
234 // Get the current file pointer. 150 // Get the current file pointer.
235 LARGE_INTEGER file_pointer; 151 LARGE_INTEGER file_pointer;
236 LARGE_INTEGER zero; 152 LARGE_INTEGER zero;
237 zero.QuadPart = 0; 153 zero.QuadPart = 0;
238 if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT)) 154 if (!::SetFilePointerEx(file_.Get(), zero, &file_pointer, FILE_CURRENT))
239 return false; 155 return false;
240 156
241 LARGE_INTEGER length_li; 157 LARGE_INTEGER length_li;
242 length_li.QuadPart = length; 158 length_li.QuadPart = length;
243 // If length > file size, SetFilePointerEx() should extend the file 159 // If length > file size, SetFilePointerEx() should extend the file
244 // with zeroes on all Windows standard file systems (NTFS, FATxx). 160 // with zeroes on all Windows standard file systems (NTFS, FATxx).
245 if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN)) 161 if (!::SetFilePointerEx(file_.Get(), length_li, NULL, FILE_BEGIN))
246 return false; 162 return false;
247 163
248 // Set the new file length and move the file pointer to its old position. 164 // Set the new file length and move the file pointer to its old position.
249 // This is consistent with ftruncate()'s behavior, even when the file 165 // This is consistent with ftruncate()'s behavior, even when the file
250 // pointer points to a location beyond the end of the file. 166 // pointer points to a location beyond the end of the file.
251 // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not 167 // TODO(rvargas): Emulating ftruncate details seem suspicious and it is not
252 // promised by the interface (nor was promised by PlatformFile). See if this 168 // promised by the interface (nor was promised by PlatformFile). See if this
253 // implementation detail can be removed. 169 // implementation detail can be removed.
254 return ((::SetEndOfFile(file_.Get()) != FALSE) && 170 return ((::SetEndOfFile(file_.Get()) != FALSE) &&
255 (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) != 171 (::SetFilePointerEx(file_.Get(), file_pointer, NULL, FILE_BEGIN) !=
256 FALSE)); 172 FALSE));
257 } 173 }
258 174
259 bool File::Flush() {
260 base::ThreadRestrictions::AssertIOAllowed();
261 DCHECK(IsValid());
262 return ::FlushFileBuffers(file_.Get()) != FALSE;
263 }
264
265 bool File::SetTimes(Time last_access_time, Time last_modified_time) { 175 bool File::SetTimes(Time last_access_time, Time last_modified_time) {
266 base::ThreadRestrictions::AssertIOAllowed(); 176 ThreadRestrictions::AssertIOAllowed();
267 DCHECK(IsValid()); 177 DCHECK(IsValid());
268 178
269 FILETIME last_access_filetime = last_access_time.ToFileTime(); 179 FILETIME last_access_filetime = last_access_time.ToFileTime();
270 FILETIME last_modified_filetime = last_modified_time.ToFileTime(); 180 FILETIME last_modified_filetime = last_modified_time.ToFileTime();
271 return (::SetFileTime(file_.Get(), NULL, &last_access_filetime, 181 return (::SetFileTime(file_.Get(), NULL, &last_access_filetime,
272 &last_modified_filetime) != FALSE); 182 &last_modified_filetime) != FALSE);
273 } 183 }
274 184
275 bool File::GetInfo(Info* info) { 185 bool File::GetInfo(Info* info) {
276 base::ThreadRestrictions::AssertIOAllowed(); 186 ThreadRestrictions::AssertIOAllowed();
277 DCHECK(IsValid()); 187 DCHECK(IsValid());
278 188
279 BY_HANDLE_FILE_INFORMATION file_info; 189 BY_HANDLE_FILE_INFORMATION file_info;
280 if (!GetFileInformationByHandle(file_.Get(), &file_info)) 190 if (!GetFileInformationByHandle(file_.Get(), &file_info))
281 return false; 191 return false;
282 192
283 LARGE_INTEGER size; 193 LARGE_INTEGER size;
284 size.HighPart = file_info.nFileSizeHigh; 194 size.HighPart = file_info.nFileSizeHigh;
285 size.LowPart = file_info.nFileSizeLow; 195 size.LowPart = file_info.nFileSizeLow;
286 info->size = size.QuadPart; 196 info->size = size.QuadPart;
287 info->is_directory = 197 info->is_directory =
288 (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0; 198 (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
289 info->is_symbolic_link = false; // Windows doesn't have symbolic links. 199 info->is_symbolic_link = false; // Windows doesn't have symbolic links.
290 info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime); 200 info->last_modified = Time::FromFileTime(file_info.ftLastWriteTime);
291 info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime); 201 info->last_accessed = Time::FromFileTime(file_info.ftLastAccessTime);
292 info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime); 202 info->creation_time = Time::FromFileTime(file_info.ftCreationTime);
293 return true; 203 return true;
294 } 204 }
295 205
296 File::Error base::File::Lock() { 206 File::Error File::Lock() {
297 DCHECK(IsValid()); 207 DCHECK(IsValid());
298 BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); 208 BOOL result = LockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
299 if (!result) 209 if (!result)
300 return OSErrorToFileError(GetLastError()); 210 return OSErrorToFileError(GetLastError());
301 return FILE_OK; 211 return FILE_OK;
302 } 212 }
303 213
304 File::Error File::Unlock() { 214 File::Error File::Unlock() {
305 DCHECK(IsValid()); 215 DCHECK(IsValid());
306 BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD); 216 BOOL result = UnlockFile(file_.Get(), 0, 0, MAXDWORD, MAXDWORD);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 case ERROR_FILE_CORRUPT: 271 case ERROR_FILE_CORRUPT:
362 case ERROR_DISK_CORRUPT: 272 case ERROR_DISK_CORRUPT:
363 return FILE_ERROR_IO; 273 return FILE_ERROR_IO;
364 default: 274 default:
365 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows", 275 UMA_HISTOGRAM_SPARSE_SLOWLY("PlatformFile.UnknownErrors.Windows",
366 last_error); 276 last_error);
367 return FILE_ERROR_FAILED; 277 return FILE_ERROR_FAILED;
368 } 278 }
369 } 279 }
370 280
281 void File::DoInitialize(const FilePath& name, uint32 flags) {
282 ThreadRestrictions::AssertIOAllowed();
283 DCHECK(!IsValid());
284
285 DWORD disposition = 0;
286
287 if (flags & FLAG_OPEN)
288 disposition = OPEN_EXISTING;
289
290 if (flags & FLAG_CREATE) {
291 DCHECK(!disposition);
292 disposition = CREATE_NEW;
293 }
294
295 if (flags & FLAG_OPEN_ALWAYS) {
296 DCHECK(!disposition);
297 disposition = OPEN_ALWAYS;
298 }
299
300 if (flags & FLAG_CREATE_ALWAYS) {
301 DCHECK(!disposition);
302 DCHECK(flags & FLAG_WRITE);
303 disposition = CREATE_ALWAYS;
304 }
305
306 if (flags & FLAG_OPEN_TRUNCATED) {
307 DCHECK(!disposition);
308 DCHECK(flags & FLAG_WRITE);
309 disposition = TRUNCATE_EXISTING;
310 }
311
312 if (!disposition) {
313 NOTREACHED();
314 return;
315 }
316
317 DWORD access = 0;
318 if (flags & FLAG_WRITE)
319 access = GENERIC_WRITE;
320 if (flags & FLAG_APPEND) {
321 DCHECK(!access);
322 access = FILE_APPEND_DATA;
323 }
324 if (flags & FLAG_READ)
325 access |= GENERIC_READ;
326 if (flags & FLAG_WRITE_ATTRIBUTES)
327 access |= FILE_WRITE_ATTRIBUTES;
328 if (flags & FLAG_EXECUTE)
329 access |= GENERIC_EXECUTE;
330
331 DWORD sharing = (flags & FLAG_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ;
332 if (!(flags & FLAG_EXCLUSIVE_WRITE))
333 sharing |= FILE_SHARE_WRITE;
334 if (flags & FLAG_SHARE_DELETE)
335 sharing |= FILE_SHARE_DELETE;
336
337 DWORD create_flags = 0;
338 if (flags & FLAG_ASYNC)
339 create_flags |= FILE_FLAG_OVERLAPPED;
340 if (flags & FLAG_TEMPORARY)
341 create_flags |= FILE_ATTRIBUTE_TEMPORARY;
342 if (flags & FLAG_HIDDEN)
343 create_flags |= FILE_ATTRIBUTE_HIDDEN;
344 if (flags & FLAG_DELETE_ON_CLOSE)
345 create_flags |= FILE_FLAG_DELETE_ON_CLOSE;
346 if (flags & FLAG_BACKUP_SEMANTICS)
347 create_flags |= FILE_FLAG_BACKUP_SEMANTICS;
348
349 file_.Set(CreateFile(name.value().c_str(), access, sharing, NULL,
350 disposition, create_flags, NULL));
351
352 if (file_.IsValid()) {
353 error_details_ = FILE_OK;
354 async_ = ((flags & FLAG_ASYNC) == FLAG_ASYNC);
355
356 if (flags & (FLAG_OPEN_ALWAYS))
357 created_ = (ERROR_ALREADY_EXISTS != GetLastError());
358 else if (flags & (FLAG_CREATE_ALWAYS | FLAG_CREATE))
359 created_ = true;
360 } else {
361 error_details_ = OSErrorToFileError(GetLastError());
362 }
363 }
364
365 bool File::DoFlush() {
366 ThreadRestrictions::AssertIOAllowed();
367 DCHECK(IsValid());
368 return ::FlushFileBuffers(file_.Get()) != FALSE;
369 }
370
371 void File::SetPlatformFile(PlatformFile file) { 371 void File::SetPlatformFile(PlatformFile file) {
372 file_.Set(file); 372 file_.Set(file);
373 } 373 }
374 374
375 } // namespace base 375 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698