| OLD | NEW |
| 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 Loading... |
| 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 |
| OLD | NEW |