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

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

Issue 12320003: Fix net::FileStream to handle POSIX errors correctly. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 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
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/file_path.h" 9 #include "base/file_path.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
65 OnAsyncFileOpened(); 65 OnAsyncFileOpened();
66 } 66 }
67 } 67 }
68 68
69 FileStream::Context::~Context() { 69 FileStream::Context::~Context() {
70 } 70 }
71 71
72 int64 FileStream::Context::GetFileSize() const { 72 int64 FileStream::Context::GetFileSize() const {
73 LARGE_INTEGER file_size; 73 LARGE_INTEGER file_size;
74 if (!GetFileSizeEx(file_, &file_size)) { 74 if (!GetFileSizeEx(file_, &file_size)) {
75 DWORD error = GetLastError(); 75 IOResult error = IOResult::FromOSError(GetLastError());
76 LOG(WARNING) << "GetFileSizeEx failed: " << error; 76 LOG(WARNING) << "GetFileSizeEx failed: " << error.os_error;
77 return RecordAndMapError(error, FILE_ERROR_SOURCE_GET_SIZE); 77 RecordError(error, FILE_ERROR_SOURCE_GET_SIZE);
78 return error.result;
78 } 79 }
79 80
80 return file_size.QuadPart; 81 return file_size.QuadPart;
81 } 82 }
82 83
83 int FileStream::Context::ReadAsync(IOBuffer* buf, 84 int FileStream::Context::ReadAsync(IOBuffer* buf,
84 int buf_len, 85 int buf_len,
85 const CompletionCallback& callback) { 86 const CompletionCallback& callback) {
86 DCHECK(!async_in_progress_); 87 DCHECK(!async_in_progress_);
87 error_source_ = FILE_ERROR_SOURCE_READ; 88 error_source_ = FILE_ERROR_SOURCE_READ;
88 89
89 int rv = 0;
90
91 DWORD bytes_read; 90 DWORD bytes_read;
92 if (!ReadFile(file_, buf->data(), buf_len, 91 if (!ReadFile(file_, buf->data(), buf_len,
93 &bytes_read, &io_context_.overlapped)) { 92 &bytes_read, &io_context_.overlapped)) {
94 DWORD error = GetLastError(); 93 IOResult error = IOResult::FromOSError(GetLastError());
95 if (error == ERROR_IO_PENDING) { 94 if (error.os_error == ERROR_IO_PENDING) {
96 IOCompletionIsPending(callback, buf); 95 IOCompletionIsPending(callback, buf);
97 rv = ERR_IO_PENDING; 96 } else if (error.os_error == ERROR_HANDLE_EOF) {
98 } else if (error == ERROR_HANDLE_EOF) { 97 return 0; // Report EOF by returning 0 bytes read.
99 rv = 0; // Report EOF by returning 0 bytes read.
100 } else { 98 } else {
101 LOG(WARNING) << "ReadFile failed: " << error; 99 LOG(WARNING) << "ReadFile failed: " << error.os_error;
102 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ); 100 RecordError(error, FILE_ERROR_SOURCE_READ);
103 } 101 }
104 } else { 102 return error.result;
105 IOCompletionIsPending(callback, buf);
106 rv = ERR_IO_PENDING;
107 } 103 }
108 return rv; 104
105 return bytes_read;
mmenke 2013/02/22 16:24:59 Skimming over the MSDN docs, the old behavior look
Sergey Ulanov 2013/02/22 21:04:06 This method would have to be updated either way (f
mmenke 2013/02/22 21:13:17 It's not about the size, it's about the unrelated
Sergey Ulanov 2013/02/22 21:51:47 Yeah, I understand and agree that in general it wo
109 } 106 }
110 107
111 int FileStream::Context::ReadSync(char* buf, int buf_len) { 108 int FileStream::Context::ReadSync(char* buf, int buf_len) {
112 int rv = 0;
113
114 DWORD bytes_read; 109 DWORD bytes_read;
115 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) { 110 if (!ReadFile(file_, buf, buf_len, &bytes_read, NULL)) {
116 DWORD error = GetLastError(); 111 IOResult error = IOResult::FromOSError(GetLastError());
117 if (error == ERROR_HANDLE_EOF) { 112 if (error.os_error == ERROR_HANDLE_EOF) {
118 rv = 0; // Report EOF by returning 0 bytes read. 113 return 0; // Report EOF by returning 0 bytes read.
119 } else { 114 } else {
120 LOG(WARNING) << "ReadFile failed: " << error; 115 LOG(WARNING) << "ReadFile failed: " << error.os_error;
121 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ); 116 RecordError(error, FILE_ERROR_SOURCE_READ);
122 } 117 }
123 } else { 118 return error.result;
124 rv = static_cast<int>(bytes_read);
125 } 119 }
126 return rv; 120
121 return bytes_read;
127 } 122 }
128 123
129 int FileStream::Context::WriteAsync(IOBuffer* buf, 124 int FileStream::Context::WriteAsync(IOBuffer* buf,
130 int buf_len, 125 int buf_len,
131 const CompletionCallback& callback) { 126 const CompletionCallback& callback) {
132 error_source_ = FILE_ERROR_SOURCE_WRITE; 127 error_source_ = FILE_ERROR_SOURCE_WRITE;
133 128
134 int rv = 0;
135 DWORD bytes_written = 0; 129 DWORD bytes_written = 0;
136 if (!WriteFile(file_, buf->data(), buf_len, 130 if (!WriteFile(file_, buf->data(), buf_len,
137 &bytes_written, &io_context_.overlapped)) { 131 &bytes_written, &io_context_.overlapped)) {
138 DWORD error = GetLastError(); 132 IOResult error = IOResult::FromOSError(GetLastError());
139 if (error == ERROR_IO_PENDING) { 133 if (error.os_error == ERROR_IO_PENDING) {
140 IOCompletionIsPending(callback, buf); 134 IOCompletionIsPending(callback, buf);
141 rv = ERR_IO_PENDING;
142 } else { 135 } else {
143 LOG(WARNING) << "WriteFile failed: " << error; 136 LOG(WARNING) << "WriteFile failed: " << error.os_error;
144 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE); 137 RecordError(error, FILE_ERROR_SOURCE_WRITE);
145 } 138 }
146 } else { 139 return error.result;
147 IOCompletionIsPending(callback, buf);
148 rv = ERR_IO_PENDING;
149 } 140 }
150 return rv; 141
142 return bytes_written;
mmenke 2013/02/22 16:24:59 See above comment.
Sergey Ulanov 2013/02/22 21:04:06 Same here.
151 } 143 }
152 144
153 int FileStream::Context::WriteSync(const char* buf, int buf_len) { 145 int FileStream::Context::WriteSync(const char* buf, int buf_len) {
154 int rv = 0;
155 DWORD bytes_written = 0; 146 DWORD bytes_written = 0;
156 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) { 147 if (!WriteFile(file_, buf, buf_len, &bytes_written, NULL)) {
157 DWORD error = GetLastError(); 148 IOResult error = IOResult::FromOSError(GetLastError());
158 LOG(WARNING) << "WriteFile failed: " << error; 149 LOG(WARNING) << "WriteFile failed: " << error.os_error;
159 rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE); 150 RecordError(error, FILE_ERROR_SOURCE_WRITE);
160 } else { 151 return error.result;
161 rv = static_cast<int>(bytes_written);
162 } 152 }
163 return rv; 153
154 return bytes_written;
164 } 155 }
165 156
166 int FileStream::Context::Truncate(int64 bytes) { 157 int FileStream::Context::Truncate(int64 bytes) {
167 BOOL result = SetEndOfFile(file_); 158 if (!SetEndOfFile(file_)) {
168 if (result) 159 IOResult error = IOResult::FromOSError(GetLastError());
169 return bytes; 160 LOG(WARNING) << "SetEndOfFile failed: " << error.os_error;
161 RecordError(error, FILE_ERROR_SOURCE_SET_EOF);
162 return error.result;
163 }
170 164
171 DWORD error = GetLastError(); 165 return bytes;
172 LOG(WARNING) << "SetEndOfFile failed: " << error;
173 return RecordAndMapError(error, FILE_ERROR_SOURCE_SET_EOF);
174 } 166 }
175 167
176 void FileStream::Context::OnAsyncFileOpened() { 168 void FileStream::Context::OnAsyncFileOpened() {
177 MessageLoopForIO::current()->RegisterIOHandler(file_, this); 169 MessageLoopForIO::current()->RegisterIOHandler(file_, this);
178 } 170 }
179 171
180 int64 FileStream::Context::SeekFileImpl(Whence whence, int64 offset) { 172 FileStream::Context::IOResult FileStream::Context::SeekFileImpl(Whence whence,
173 int64 offset) {
181 LARGE_INTEGER distance, res; 174 LARGE_INTEGER distance, res;
182 distance.QuadPart = offset; 175 distance.QuadPart = offset;
183 DWORD move_method = static_cast<DWORD>(whence); 176 DWORD move_method = static_cast<DWORD>(whence);
184 if (SetFilePointerEx(file_, distance, &res, move_method)) { 177 if (SetFilePointerEx(file_, distance, &res, move_method)) {
185 SetOffset(&io_context_.overlapped, res); 178 SetOffset(&io_context_.overlapped, res);
186 return res.QuadPart; 179 return IOResult(res.QuadPart, 0);
187 } 180 }
188 181
189 return -static_cast<int>(GetLastError()); 182 return IOResult::FromOSError(GetLastError());
190 } 183 }
191 184
192 int64 FileStream::Context::FlushFileImpl() { 185 FileStream::Context::IOResult FileStream::Context::FlushFileImpl() {
193 if (FlushFileBuffers(file_)) 186 if (FlushFileBuffers(file_))
194 return OK; 187 return IOResult(OK, 0);
195 188
196 return -static_cast<int>(GetLastError()); 189 return IOResult::FromOSError(GetLastError());
197 } 190 }
198 191
199 void FileStream::Context::IOCompletionIsPending( 192 void FileStream::Context::IOCompletionIsPending(
200 const CompletionCallback& callback, 193 const CompletionCallback& callback,
201 IOBuffer* buf) { 194 IOBuffer* buf) {
202 DCHECK(callback_.is_null()); 195 DCHECK(callback_.is_null());
203 callback_ = callback; 196 callback_ = callback;
204 in_flight_buf_ = buf; // Hold until the async operation ends. 197 in_flight_buf_ = buf; // Hold until the async operation ends.
205 async_in_progress_ = true; 198 async_in_progress_ = true;
206 } 199 }
207 200
208 void FileStream::Context::OnIOCompleted(MessageLoopForIO::IOContext* context, 201 void FileStream::Context::OnIOCompleted(MessageLoopForIO::IOContext* context,
209 DWORD bytes_read, 202 DWORD bytes_read,
210 DWORD error) { 203 DWORD error) {
211 DCHECK_EQ(&io_context_, context); 204 DCHECK_EQ(&io_context_, context);
212 DCHECK(!callback_.is_null()); 205 DCHECK(!callback_.is_null());
213 DCHECK(async_in_progress_); 206 DCHECK(async_in_progress_);
214 207
215 async_in_progress_ = false; 208 async_in_progress_ = false;
216 if (orphaned_) { 209 if (orphaned_) {
217 callback_.Reset(); 210 callback_.Reset();
218 in_flight_buf_ = NULL; 211 in_flight_buf_ = NULL;
219 CloseAndDelete(); 212 CloseAndDelete();
220 return; 213 return;
221 } 214 }
222 215
223 int result = static_cast<int>(bytes_read); 216 IOResult result;
mmenke 2013/02/22 16:24:59 Don't think we need this here. Can be scoped with
Sergey Ulanov 2013/02/22 21:04:06 Done.
224 if (error && error != ERROR_HANDLE_EOF) 217 if (error == ERROR_HANDLE_EOF) {
225 result = RecordAndMapError(error, error_source_); 218 result = IOResult(0, 0);
226 219 } else if (error) {
227 if (bytes_read) 220 result = IOResult::FromOSError(error);
221 RecordError(result, error_source_);
222 } else {
223 result = IOResult(bytes_read, 0);
228 IncrementOffset(&io_context_.overlapped, bytes_read); 224 IncrementOffset(&io_context_.overlapped, bytes_read);
225 }
229 226
230 CompletionCallback temp_callback = callback_; 227 CompletionCallback temp_callback = callback_;
231 callback_.Reset(); 228 callback_.Reset();
232 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_; 229 scoped_refptr<IOBuffer> temp_buf = in_flight_buf_;
233 in_flight_buf_ = NULL; 230 in_flight_buf_ = NULL;
234 temp_callback.Run(result); 231 temp_callback.Run(result.result);
235 } 232 }
236 233
237 } // namespace net 234 } // namespace net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698