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

Side by Side Diff: net/base/file_stream_context_win.cc

Issue 12326107: Fix net::FileStream to handle all errors correctly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 9 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 | Annotate | Revision Log
« no previous file with comments | « net/base/file_stream_context_posix.cc ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 "net/base/file_stream_context.h" 5 #include "net/base/file_stream_context.h"
6 6
7 #include <windows.h> 7 #include <windows.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"
(...skipping 29 matching lines...) Expand all
40 40
41 FileStream::Context::Context(const BoundNetLog& bound_net_log) 41 FileStream::Context::Context(const BoundNetLog& bound_net_log)
42 : io_context_(), 42 : io_context_(),
43 file_(base::kInvalidPlatformFileValue), 43 file_(base::kInvalidPlatformFileValue),
44 record_uma_(false), 44 record_uma_(false),
45 async_in_progress_(false), 45 async_in_progress_(false),
46 orphaned_(false), 46 orphaned_(false),
47 bound_net_log_(bound_net_log), 47 bound_net_log_(bound_net_log),
48 error_source_(FILE_ERROR_SOURCE_COUNT) { 48 error_source_(FILE_ERROR_SOURCE_COUNT) {
49 io_context_.handler = this; 49 io_context_.handler = this;
50 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
50 } 51 }
51 52
52 FileStream::Context::Context(base::PlatformFile file, 53 FileStream::Context::Context(base::PlatformFile file,
53 const BoundNetLog& bound_net_log, 54 const BoundNetLog& bound_net_log,
54 int open_flags) 55 int open_flags)
55 : io_context_(), 56 : io_context_(),
56 file_(file), 57 file_(file),
57 record_uma_(false), 58 record_uma_(false),
58 async_in_progress_(false), 59 async_in_progress_(false),
59 orphaned_(false), 60 orphaned_(false),
60 bound_net_log_(bound_net_log), 61 bound_net_log_(bound_net_log),
61 error_source_(FILE_ERROR_SOURCE_COUNT) { 62 error_source_(FILE_ERROR_SOURCE_COUNT) {
62 io_context_.handler = this; 63 io_context_.handler = this;
64 memset(&io_context_.overlapped, 0, sizeof(io_context_.overlapped));
63 if (file_ != base::kInvalidPlatformFileValue && 65 if (file_ != base::kInvalidPlatformFileValue &&
64 (open_flags & base::PLATFORM_FILE_ASYNC)) { 66 (open_flags & base::PLATFORM_FILE_ASYNC)) {
65 OnAsyncFileOpened(); 67 OnAsyncFileOpened();
66 } 68 }
67 } 69 }
68 70
69 FileStream::Context::~Context() { 71 FileStream::Context::~Context() {
70 } 72 }
71 73
72 int64 FileStream::Context::GetFileSize() const { 74 int64 FileStream::Context::GetFileSize() const {
73 LARGE_INTEGER file_size; 75 LARGE_INTEGER file_size;
74 if (!GetFileSizeEx(file_, &file_size)) { 76 if (!GetFileSizeEx(file_, &file_size)) {
75 DWORD error = GetLastError(); 77 IOResult error = IOResult::FromOSError(GetLastError());
76 LOG(WARNING) << "GetFileSizeEx failed: " << error; 78 LOG(WARNING) << "GetFileSizeEx failed: " << error.os_error;
77 return RecordAndMapError(error, FILE_ERROR_SOURCE_GET_SIZE); 79 RecordError(error, FILE_ERROR_SOURCE_GET_SIZE);
80 return error.result;
78 } 81 }
79 82
80 return file_size.QuadPart; 83 return file_size.QuadPart;
81 } 84 }
82 85
83 int FileStream::Context::ReadAsync(IOBuffer* buf, 86 int FileStream::Context::ReadAsync(IOBuffer* buf,
84 int buf_len, 87 int buf_len,
85 const CompletionCallback& callback) { 88 const CompletionCallback& callback) {
86 DCHECK(!async_in_progress_); 89 DCHECK(!async_in_progress_);
87 error_source_ = FILE_ERROR_SOURCE_READ; 90 error_source_ = FILE_ERROR_SOURCE_READ;
88 91
89 int rv = 0;
90
91 DWORD bytes_read; 92 DWORD bytes_read;
92 if (!ReadFile(file_, buf->data(), buf_len, 93 if (!ReadFile(file_, buf->data(), buf_len,
93 &bytes_read, &io_context_.overlapped)) { 94 &bytes_read, &io_context_.overlapped)) {
94 DWORD error = GetLastError(); 95 IOResult error = IOResult::FromOSError(GetLastError());
95 if (error == ERROR_IO_PENDING) { 96 if (error.os_error == ERROR_IO_PENDING) {
96 IOCompletionIsPending(callback, buf); 97 IOCompletionIsPending(callback, buf);
97 rv = ERR_IO_PENDING; 98 } else if (error.os_error == ERROR_HANDLE_EOF) {
98 } else if (error == ERROR_HANDLE_EOF) { 99 return 0; // Report EOF by returning 0 bytes read.
99 rv = 0; // Report EOF by returning 0 bytes read.
100 } else { 100 } else {
101 LOG(WARNING) << "ReadFile failed: " << error; 101 LOG(WARNING) << "ReadFile failed: " << error.os_error;
102 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ); 102 RecordError(error, FILE_ERROR_SOURCE_READ);
103 } 103 }
104 } else { 104 return error.result;
105 IOCompletionIsPending(callback, buf);
106 rv = ERR_IO_PENDING;
107 } 105 }
108 return rv; 106
107 IOCompletionIsPending(callback, buf);
108 return ERR_IO_PENDING;
109 } 109 }
110 110
111 int FileStream::Context::ReadSync(char* buf, int buf_len) { 111 int FileStream::Context::ReadSync(char* buf, int buf_len) {
112 int rv = 0;
113
114 DWORD bytes_read; 112 DWORD bytes_read;
115 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) { 113 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) {
116 DWORD error = GetLastError(); 114 IOResult error = IOResult::FromOSError(GetLastError());
117 if (error == ERROR_HANDLE_EOF) { 115 if (error.os_error == ERROR_HANDLE_EOF) {
118 rv = 0; // Report EOF by returning 0 bytes read. 116 return 0; // Report EOF by returning 0 bytes read.
119 } else { 117 } else {
120 LOG(WARNING) << "ReadFile failed: " << error; 118 LOG(WARNING) << "ReadFile failed: " << error.os_error;
121 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ); 119 RecordError(error, FILE_ERROR_SOURCE_READ);
122 } 120 }
123 } else { 121 return error.result;
124 rv = static_cast<int>(bytes_read);
125 } 122 }
126 return rv; 123
124 return bytes_read;
127 } 125 }
128 126
129 int FileStream::Context::WriteAsync(IOBuffer* buf, 127 int FileStream::Context::WriteAsync(IOBuffer* buf,
130 int buf_len, 128 int buf_len,
131 const CompletionCallback& callback) { 129 const CompletionCallback& callback) {
132 error_source_ = FILE_ERROR_SOURCE_WRITE; 130 error_source_ = FILE_ERROR_SOURCE_WRITE;
133 131
134 int rv = 0;
135 DWORD bytes_written = 0; 132 DWORD bytes_written = 0;
136 if (!WriteFile(file_, buf->data(), buf_len, 133 if (!WriteFile(file_, buf->data(), buf_len,
137 &bytes_written, &io_context_.overlapped)) { 134 &bytes_written, &io_context_.overlapped)) {
138 DWORD error = GetLastError(); 135 IOResult error = IOResult::FromOSError(GetLastError());
139 if (error == ERROR_IO_PENDING) { 136 if (error.os_error == ERROR_IO_PENDING) {
140 IOCompletionIsPending(callback, buf); 137 IOCompletionIsPending(callback, buf);
141 rv = ERR_IO_PENDING;
142 } else { 138 } else {
143 LOG(WARNING) << "WriteFile failed: " << error; 139 LOG(WARNING) << "WriteFile failed: " << error.os_error;
144 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE); 140 RecordError(error, FILE_ERROR_SOURCE_WRITE);
145 } 141 }
146 } else { 142 return error.result;
147 IOCompletionIsPending(callback, buf);
148 rv = ERR_IO_PENDING;
149 } 143 }
150 return rv; 144
145 IOCompletionIsPending(callback, buf);
146 return ERR_IO_PENDING;
151 } 147 }
152 148
153 int FileStream::Context::WriteSync(const char* buf, int buf_len) { 149 int FileStream::Context::WriteSync(const char* buf, int buf_len) {
154 int rv = 0;
155 DWORD bytes_written = 0; 150 DWORD bytes_written = 0;
156 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) { 151 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) {
157 DWORD error = GetLastError(); 152 IOResult error = IOResult::FromOSError(GetLastError());
158 LOG(WARNING) << "WriteFile failed: " << error; 153 LOG(WARNING) << "WriteFile failed: " << error.os_error;
159 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE); 154 RecordError(error, FILE_ERROR_SOURCE_WRITE);
160 } else { 155 return error.result;
161 rv = static_cast<int>(bytes_written);
162 } 156 }
163 return rv; 157
158 return bytes_written;
164 } 159 }
165 160
166 int FileStream::Context::Truncate(int64 bytes) { 161 int FileStream::Context::Truncate(int64 bytes) {
167 BOOL result = SetEndOfFile(file_); 162 if (!SetEndOfFile(file_)) {
168 if (result) 163 IOResult error = IOResult::FromOSError(GetLastError());
169 return bytes; 164 LOG(WARNING) << "SetEndOfFile failed: " << error.os_error;
165 RecordError(error, FILE_ERROR_SOURCE_SET_EOF);
166 return error.result;
167 }
170 168
171 DWORD error = GetLastError(); 169 return bytes;
172 LOG(WARNING) << "SetEndOfFile failed: " << error;
173 return RecordAndMapError(error, FILE_ERROR_SOURCE_SET_EOF);
174 } 170 }
175 171
176 void FileStream::Context::OnAsyncFileOpened() { 172 void FileStream::Context::OnAsyncFileOpened() {
177 MessageLoopForIO::current()->RegisterIOHandler(file_, this); 173 MessageLoopForIO::current()->RegisterIOHandler(file_, this);
178 } 174 }
179 175
180 int64 FileStream::Context::SeekFileImpl(Whence whence, int64 offset) { 176 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence,
177 int64 offset) {
181 LARGE_INTEGER distance, res; 178 LARGE_INTEGER distance, res;
182 distance.QuadPart = offset; 179 distance.QuadPart = offset;
183 DWORD move_method = static_cast<DWORD>(whence); 180 DWORD move_method = static_cast<DWORD>(whence);
184 if (SetFilePointerEx(file_, distance, &res, move_method)) { 181 if (SetFilePointerEx(file_, distance, &res, move_method)) {
185 SetOffset(&io_context_.overlapped, res); 182 SetOffset(&io_context_.overlapped, res);
186 return res.QuadPart; 183 return IOResult(res.QuadPart, 0);
187 } 184 }
188 185
189 return -static_cast<int>(GetLastError()); 186 return IOResult::FromOSError(GetLastError());
190 } 187 }
191 188
192 int64 FileStream::Context::FlushFileImpl() { 189 FileStream::Context::IOResult FileStream::Context::FlushFileImpl() {
193 if (FlushFileBuffers(file_)) 190 if (FlushFileBuffers(file_))
194 return OK; 191 return IOResult(OK, 0);
195 192
196 return -static_cast<int>(GetLastError()); 193 return IOResult::FromOSError(GetLastError());
197 } 194 }
198 195
199 void FileStream::Context::IOCompletionIsPending( 196 void FileStream::Context::IOCompletionIsPending(
200 const CompletionCallback& callback, 197 const CompletionCallback& callback,
201 IOBuffer* buf) { 198 IOBuffer* buf) {
202 DCHECK(callback_.is_null()); 199 DCHECK(callback_.is_null());
203 callback_ = callback; 200 callback_ = callback;
204 in_flight_buf_ = buf; // Hold until the async operation ends. 201 in_flight_buf_ = buf; // Hold until the async operation ends.
205 async_in_progress_ = true; 202 async_in_progress_ = true;
206 } 203 }
207 204
208 void FileStream::Context::OnIOCompleted(MessageLoopForIO::IOContext* context, 205 void FileStream::Context::OnIOCompleted(MessageLoopForIO::IOContext* context,
209 DWORD bytes_read, 206 DWORD bytes_read,
210 DWORD error) { 207 DWORD error) {
211 DCHECK_EQ(&io_context_, context); 208 DCHECK_EQ(&io_context_, context);
212 DCHECK(!callback_.is_null()); 209 DCHECK(!callback_.is_null());
213 DCHECK(async_in_progress_); 210 DCHECK(async_in_progress_);
214 211
215 async_in_progress_ = false; 212 async_in_progress_ = false;
216 if (orphaned_) { 213 if (orphaned_) {
217 callback_.Reset(); 214 callback_.Reset();
218 in_flight_buf_ = NULL; 215 in_flight_buf_ = NULL;
219 CloseAndDelete(); 216 CloseAndDelete();
220 return; 217 return;
221 } 218 }
222 219
223 int result = static_cast<int>(bytes_read); 220 int result;
224 if (error && error != ERROR_HANDLE_EOF) 221 if (error == ERROR_HANDLE_EOF) {
225 result = RecordAndMapError(error, error_source_); 222 result = 0;
226 223 } else if (error) {
227 if (bytes_read) 224 IOResult error_result = IOResult::FromOSError(error);
225 RecordError(error_result, error_source_);
226 result = error_result.result;
227 } else {
228 result = bytes_read;
228 IncrementOffset(&io_context_.overlapped, bytes_read); 229 IncrementOffset(&io_context_.overlapped, bytes_read);
230 }
229 231
230 CompletionCallback temp_callback = callback_; 232 CompletionCallback temp_callback = callback_;
231 callback_.Reset(); 233 callback_.Reset();
232 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; 234 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
233 in_flight_buf_ = NULL; 235 in_flight_buf_ = NULL;
234 temp_callback.Run(result); 236 temp_callback.Run(result);
235 } 237 }
236 238
237 } // namespace net 239 } // namespace net
OLDNEW
« no previous file with comments | « net/base/file_stream_context_posix.cc ('k') | net/base/file_stream_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698