Adding owners for third_party
[chromium-blink-merge.git] / base / platform_file_win.cc
blob7c72f9e92e1451d5873e854e9e818c298533078b
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
3 // found in the LICENSE file.
5 #include "base/platform_file.h"
7 #include "base/file_path.h"
8 #include "base/logging.h"
9 #include "base/threading/thread_restrictions.h"
11 namespace base {
12 PlatformFile CreatePlatformFileUnsafe(const FilePath& name,
13 int flags,
14 bool* created,
15 PlatformFileError* error) {
16 base::ThreadRestrictions::AssertIOAllowed();
18 DWORD disposition = 0;
19 if (created)
20 *created = false;
22 if (flags & PLATFORM_FILE_OPEN)
23 disposition = OPEN_EXISTING;
25 if (flags & PLATFORM_FILE_CREATE) {
26 DCHECK(!disposition);
27 disposition = CREATE_NEW;
30 if (flags & PLATFORM_FILE_OPEN_ALWAYS) {
31 DCHECK(!disposition);
32 disposition = OPEN_ALWAYS;
35 if (flags & PLATFORM_FILE_CREATE_ALWAYS) {
36 DCHECK(!disposition);
37 disposition = CREATE_ALWAYS;
40 if (flags & PLATFORM_FILE_OPEN_TRUNCATED) {
41 DCHECK(!disposition);
42 DCHECK(flags & PLATFORM_FILE_WRITE);
43 disposition = TRUNCATE_EXISTING;
46 if (!disposition) {
47 NOTREACHED();
48 return NULL;
51 DWORD access = (flags & PLATFORM_FILE_READ) ? GENERIC_READ : 0;
52 if (flags & PLATFORM_FILE_WRITE)
53 access |= GENERIC_WRITE;
54 if (flags & PLATFORM_FILE_WRITE_ATTRIBUTES)
55 access |= FILE_WRITE_ATTRIBUTES;
57 DWORD sharing = (flags & PLATFORM_FILE_EXCLUSIVE_READ) ? 0 : FILE_SHARE_READ;
58 if (!(flags & PLATFORM_FILE_EXCLUSIVE_WRITE))
59 sharing |= FILE_SHARE_WRITE;
60 if (flags & PLATFORM_FILE_SHARE_DELETE)
61 sharing |= FILE_SHARE_DELETE;
63 DWORD create_flags = 0;
64 if (flags & PLATFORM_FILE_ASYNC)
65 create_flags |= FILE_FLAG_OVERLAPPED;
66 if (flags & PLATFORM_FILE_TEMPORARY)
67 create_flags |= FILE_ATTRIBUTE_TEMPORARY;
68 if (flags & PLATFORM_FILE_HIDDEN)
69 create_flags |= FILE_ATTRIBUTE_HIDDEN;
70 if (flags & PLATFORM_FILE_DELETE_ON_CLOSE)
71 create_flags |= FILE_FLAG_DELETE_ON_CLOSE;
72 if (flags & PLATFORM_FILE_BACKUP_SEMANTICS)
73 create_flags |= FILE_FLAG_BACKUP_SEMANTICS;
75 HANDLE file = CreateFile(name.value().c_str(), access, sharing, NULL,
76 disposition, create_flags, NULL);
78 if (created && (INVALID_HANDLE_VALUE != file)) {
79 if (flags & (PLATFORM_FILE_OPEN_ALWAYS))
80 *created = (ERROR_ALREADY_EXISTS != GetLastError());
81 else if (flags & (PLATFORM_FILE_CREATE_ALWAYS | PLATFORM_FILE_CREATE))
82 *created = true;
85 if (error) {
86 if (file != kInvalidPlatformFileValue)
87 *error = PLATFORM_FILE_OK;
88 else {
89 DWORD last_error = GetLastError();
90 switch (last_error) {
91 case ERROR_SHARING_VIOLATION:
92 *error = PLATFORM_FILE_ERROR_IN_USE;
93 break;
94 case ERROR_FILE_EXISTS:
95 *error = PLATFORM_FILE_ERROR_EXISTS;
96 break;
97 case ERROR_FILE_NOT_FOUND:
98 *error = PLATFORM_FILE_ERROR_NOT_FOUND;
99 break;
100 case ERROR_ACCESS_DENIED:
101 *error = PLATFORM_FILE_ERROR_ACCESS_DENIED;
102 break;
103 default:
104 *error = PLATFORM_FILE_ERROR_FAILED;
109 return file;
112 bool ClosePlatformFile(PlatformFile file) {
113 base::ThreadRestrictions::AssertIOAllowed();
114 return (CloseHandle(file) != 0);
117 int64 SeekPlatformFile(PlatformFile file,
118 PlatformFileWhence whence,
119 int64 offset) {
120 base::ThreadRestrictions::AssertIOAllowed();
121 if (file < 0 || offset < 0)
122 return -1;
124 LARGE_INTEGER distance, res;
125 distance.QuadPart = offset;
126 DWORD move_method = static_cast<DWORD>(whence);
127 if (!SetFilePointerEx(file, distance, &res, move_method))
128 return -1;
129 return res.QuadPart;
132 int ReadPlatformFile(PlatformFile file, int64 offset, char* data, int size) {
133 base::ThreadRestrictions::AssertIOAllowed();
134 if (file == kInvalidPlatformFileValue)
135 return -1;
137 LARGE_INTEGER offset_li;
138 offset_li.QuadPart = offset;
140 OVERLAPPED overlapped = {0};
141 overlapped.Offset = offset_li.LowPart;
142 overlapped.OffsetHigh = offset_li.HighPart;
144 DWORD bytes_read;
145 if (::ReadFile(file, data, size, &bytes_read, &overlapped) != 0)
146 return bytes_read;
147 else if (ERROR_HANDLE_EOF == GetLastError())
148 return 0;
150 return -1;
153 int ReadPlatformFileAtCurrentPos(PlatformFile file, char* data, int size) {
154 return ReadPlatformFile(file, 0, data, size);
157 int ReadPlatformFileNoBestEffort(PlatformFile file, int64 offset, char* data,
158 int size) {
159 return ReadPlatformFile(file, offset, data, size);
162 int ReadPlatformFileCurPosNoBestEffort(PlatformFile file,
163 char* data, int size) {
164 return ReadPlatformFile(file, 0, data, size);
167 int WritePlatformFile(PlatformFile file, int64 offset,
168 const char* data, int size) {
169 base::ThreadRestrictions::AssertIOAllowed();
170 if (file == kInvalidPlatformFileValue)
171 return -1;
173 LARGE_INTEGER offset_li;
174 offset_li.QuadPart = offset;
176 OVERLAPPED overlapped = {0};
177 overlapped.Offset = offset_li.LowPart;
178 overlapped.OffsetHigh = offset_li.HighPart;
180 DWORD bytes_written;
181 if (::WriteFile(file, data, size, &bytes_written, &overlapped) != 0)
182 return bytes_written;
184 return -1;
187 int WritePlatformFileAtCurrentPos(PlatformFile file, const char* data,
188 int size) {
189 return WritePlatformFile(file, 0, data, size);
192 int WritePlatformFileCurPosNoBestEffort(PlatformFile file,
193 const char* data, int size) {
194 return WritePlatformFile(file, 0, data, size);
197 bool TruncatePlatformFile(PlatformFile file, int64 length) {
198 base::ThreadRestrictions::AssertIOAllowed();
199 if (file == kInvalidPlatformFileValue)
200 return false;
202 // Get the current file pointer.
203 LARGE_INTEGER file_pointer;
204 LARGE_INTEGER zero;
205 zero.QuadPart = 0;
206 if (::SetFilePointerEx(file, zero, &file_pointer, FILE_CURRENT) == 0)
207 return false;
209 LARGE_INTEGER length_li;
210 length_li.QuadPart = length;
211 // If length > file size, SetFilePointerEx() should extend the file
212 // with zeroes on all Windows standard file systems (NTFS, FATxx).
213 if (!::SetFilePointerEx(file, length_li, NULL, FILE_BEGIN))
214 return false;
216 // Set the new file length and move the file pointer to its old position.
217 // This is consistent with ftruncate()'s behavior, even when the file
218 // pointer points to a location beyond the end of the file.
219 return ((::SetEndOfFile(file) != 0) &&
220 (::SetFilePointerEx(file, file_pointer, NULL, FILE_BEGIN) != 0));
223 bool FlushPlatformFile(PlatformFile file) {
224 base::ThreadRestrictions::AssertIOAllowed();
225 return ((file != kInvalidPlatformFileValue) && ::FlushFileBuffers(file));
228 bool TouchPlatformFile(PlatformFile file, const base::Time& last_access_time,
229 const base::Time& last_modified_time) {
230 base::ThreadRestrictions::AssertIOAllowed();
231 if (file == kInvalidPlatformFileValue)
232 return false;
234 FILETIME last_access_filetime = last_access_time.ToFileTime();
235 FILETIME last_modified_filetime = last_modified_time.ToFileTime();
236 return (::SetFileTime(file, NULL, &last_access_filetime,
237 &last_modified_filetime) != 0);
240 bool GetPlatformFileInfo(PlatformFile file, PlatformFileInfo* info) {
241 base::ThreadRestrictions::AssertIOAllowed();
242 if (!info)
243 return false;
245 BY_HANDLE_FILE_INFORMATION file_info;
246 if (GetFileInformationByHandle(file, &file_info) == 0)
247 return false;
249 LARGE_INTEGER size;
250 size.HighPart = file_info.nFileSizeHigh;
251 size.LowPart = file_info.nFileSizeLow;
252 info->size = size.QuadPart;
253 info->is_directory =
254 (file_info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0;
255 info->is_symbolic_link = false; // Windows doesn't have symbolic links.
256 info->last_modified = base::Time::FromFileTime(file_info.ftLastWriteTime);
257 info->last_accessed = base::Time::FromFileTime(file_info.ftLastAccessTime);
258 info->creation_time = base::Time::FromFileTime(file_info.ftCreationTime);
259 return true;
262 } // namespace base