1c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch// found in the LICENSE file. 4c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 5c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/file_stream.h" 6c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 7c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include <windows.h> 8c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 9c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/file_path.h" 10c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/logging.h" 11c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "base/message_loop.h" 12731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/metrics/histogram.h" 13ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/threading/thread_restrictions.h" 14c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott#include "net/base/net_errors.h" 15c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 16c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottnamespace net { 17c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 18c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// Ensure that we can just use our Whence values directly. 19c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); 20c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); 21c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottCOMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); 22c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 23c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { 24c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott overlapped->Offset = offset.LowPart; 25c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott overlapped->OffsetHigh = offset.HighPart; 26c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 27c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 28c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic void IncrementOffset(OVERLAPPED* overlapped, DWORD count) { 29c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LARGE_INTEGER offset; 30c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset.LowPart = overlapped->Offset; 31c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset.HighPart = overlapped->OffsetHigh; 32c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott offset.QuadPart += static_cast<LONGLONG>(count); 33c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetOffset(overlapped, offset); 34c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 35c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 36c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottstatic int MapErrorCode(DWORD err) { 37c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott switch (err) { 38c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERROR_FILE_NOT_FOUND: 39c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERROR_PATH_NOT_FOUND: 40c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FILE_NOT_FOUND; 41c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERROR_ACCESS_DENIED: 42c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_ACCESS_DENIED; 43c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott case ERROR_SUCCESS: 44c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 45c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott default: 46c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; 47c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_FAILED; 48c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 49c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 50c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 51c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FileStream::AsyncContext ---------------------------------------------- 52c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 53c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottclass FileStream::AsyncContext : public MessageLoopForIO::IOHandler { 54c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott public: 55c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott AsyncContext(FileStream* owner) 56c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : owner_(owner), context_(), callback_(NULL), is_closing_(false) { 57c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott context_.handler = this; 58c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 59c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott ~AsyncContext(); 60c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 61c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott void IOCompletionIsPending(CompletionCallback* callback); 62c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 63c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OVERLAPPED* overlapped() { return &context_.overlapped; } 64c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback() const { return callback_; } 65c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 66c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott private: 67c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, 68c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD bytes_read, DWORD error); 69c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 70c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott FileStream* owner_; 71c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::IOContext context_; 72c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback_; 73c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool is_closing_; 74c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott}; 75c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 76c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFileStream::AsyncContext::~AsyncContext() { 77c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott is_closing_ = true; 78c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bool waited = false; 79c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks start = base::TimeTicks::Now(); 80c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott while (callback_) { 81c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott waited = true; 82c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); 83c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 84c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (waited) { 85c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We want to see if we block the message loop for too long. 86c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch UMA_HISTOGRAM_TIMES("AsyncIO.FileStreamClose", 87c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch base::TimeTicks::Now() - start); 88c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 89c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 90c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 91c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid FileStream::AsyncContext::IOCompletionIsPending( 92c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* callback) { 93c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!callback_); 94c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_ = callback; 95c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 96c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 97c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid FileStream::AsyncContext::OnIOCompleted( 98c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::IOContext* context, DWORD bytes_read, DWORD error) { 99c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(&context_ == context); 100c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(callback_); 101c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 102c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (is_closing_) { 103c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott callback_ = NULL; 104c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return; 105c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 106c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 107c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int result = static_cast<int>(bytes_read); 108c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (error && error != ERROR_HANDLE_EOF) 109c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott result = MapErrorCode(error); 110c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 111c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_read) 112c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott IncrementOffset(&context->overlapped, bytes_read); 113c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 114c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CompletionCallback* temp = NULL; 115c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott std::swap(temp, callback_); 116c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott temp->Run(result); 117c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 118c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 119c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott// FileStream ------------------------------------------------------------ 120c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 121c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFileStream::FileStream() 122c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : file_(INVALID_HANDLE_VALUE), 123c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch open_flags_(0), 124c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auto_closed_(true) { 125c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 126c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 127c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFileStream::FileStream(base::PlatformFile file, int flags) 128c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott : file_(file), 129c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch open_flags_(flags), 130c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch auto_closed_(false) { 131c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to 132c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // make sure we will perform asynchronous File IO to it. 133c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (flags & base::PLATFORM_FILE_ASYNC) { 134c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_.reset(new AsyncContext(this)); 135c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::current()->RegisterIOHandler(file_, 136c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_.get()); 137c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 138c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 139c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 140c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick ScottFileStream::~FileStream() { 141c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (auto_closed_) 142c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch Close(); 143c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 144c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 145c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottvoid FileStream::Close() { 146c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (file_ != INVALID_HANDLE_VALUE) 147c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CancelIo(file_); 148c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 149c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_.reset(); 150c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (file_ != INVALID_HANDLE_VALUE) { 151c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott CloseHandle(file_); 152c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott file_ = INVALID_HANDLE_VALUE; 153c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 154c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 155c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 156c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint FileStream::Open(const FilePath& path, int open_flags) { 157c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (IsOpen()) { 158c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DLOG(FATAL) << "File is already open!"; 159c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 160c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 161c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 162c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott open_flags_ = open_flags; 1633345a6884c488ff3a535c2c9acdd33d74b37e311Iain Merrick file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); 164c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (file_ == INVALID_HANDLE_VALUE) { 165c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 166c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "Failed to open file: " << error; 167c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapErrorCode(error); 168c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 169c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 170c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (open_flags_ & base::PLATFORM_FILE_ASYNC) { 171c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_.reset(new AsyncContext(this)); 172c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott MessageLoopForIO::current()->RegisterIOHandler(file_, 173c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_.get()); 174c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 175c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 176c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return OK; 177c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 178c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 179c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottbool FileStream::IsOpen() const { 180c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return file_ != INVALID_HANDLE_VALUE; 181c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 182c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 183c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 FileStream::Seek(Whence whence, int64 offset) { 184c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsOpen()) 185c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 186c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!async_context_.get() || !async_context_->callback()); 187c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 188c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LARGE_INTEGER distance, result; 189c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott distance.QuadPart = offset; 190c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD move_method = static_cast<DWORD>(whence); 191c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!SetFilePointerEx(file_, distance, &result, move_method)) { 192c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 193c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "SetFilePointerEx failed: " << error; 194c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapErrorCode(error); 195c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 196c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (async_context_.get()) 197c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott SetOffset(async_context_->overlapped(), result); 198c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return result.QuadPart; 199c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 200c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 201c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 FileStream::Available() { 202ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::AssertIOAllowed(); 203ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 204c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsOpen()) 205c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 206c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 207c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 cur_pos = Seek(FROM_CURRENT, 0); 208c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (cur_pos < 0) 209c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return cur_pos; 210c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 211c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LARGE_INTEGER file_size; 212c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!GetFileSizeEx(file_, &file_size)) { 213c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 214c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "GetFileSizeEx failed: " << error; 215c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapErrorCode(error); 216c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 217c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 218c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return file_size.QuadPart - cur_pos; 219c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 220c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 221c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint FileStream::Read( 222c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott char* buf, int buf_len, CompletionCallback* callback) { 223c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsOpen()) 224c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 225c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(open_flags_ & base::PLATFORM_FILE_READ); 226c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 227c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OVERLAPPED* overlapped = NULL; 228c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (async_context_.get()) { 229ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(callback); 230c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!async_context_->callback()); 231c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott overlapped = async_context_->overlapped(); 232ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 233ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!callback); 234ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::AssertIOAllowed(); 235c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 236c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 237c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 238c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 239c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD bytes_read; 240c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { 241c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 242c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (async_context_.get() && error == ERROR_IO_PENDING) { 243c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_->IOCompletionIsPending(callback); 244c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_IO_PENDING; 245c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (error == ERROR_HANDLE_EOF) { 246c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = 0; // Report EOF by returning 0 bytes read. 247c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 248c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "ReadFile failed: " << error; 249c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = MapErrorCode(error); 250c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 251c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (overlapped) { 252c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_->IOCompletionIsPending(callback); 253c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_IO_PENDING; 254c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 255c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = static_cast<int>(bytes_read); 256c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 257c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 258c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 259c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 260c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint FileStream::ReadUntilComplete(char *buf, int buf_len) { 261c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int to_read = buf_len; 262c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bytes_total = 0; 263c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 264c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott do { 265c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int bytes_read = Read(buf, to_read, NULL); 266c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_read <= 0) { 267c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (bytes_total == 0) 268c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return bytes_read; 269c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 270c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return bytes_total; 271c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 272c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 273c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott bytes_total += bytes_read; 274c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott buf += bytes_read; 275c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott to_read -= bytes_read; 276c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } while (bytes_total < buf_len); 277c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 278c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return bytes_total; 279c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 280c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 281c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint FileStream::Write( 282c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott const char* buf, int buf_len, CompletionCallback* callback) { 283c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsOpen()) 284c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 285c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 286c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 287c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott OVERLAPPED* overlapped = NULL; 288c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (async_context_.get()) { 289ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(callback); 290c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(!async_context_->callback()); 291c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott overlapped = async_context_->overlapped(); 292ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen } else { 293ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen DCHECK(!callback); 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::AssertIOAllowed(); 295c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 296c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 297c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int rv; 298c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD bytes_written; 299c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { 300c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 301c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (async_context_.get() && error == ERROR_IO_PENDING) { 302c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_->IOCompletionIsPending(callback); 303c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_IO_PENDING; 304c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 305c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "WriteFile failed: " << error; 306c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = MapErrorCode(error); 307c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 308c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else if (overlapped) { 309c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott async_context_->IOCompletionIsPending(callback); 310c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = ERR_IO_PENDING; 311c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } else { 312c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott rv = static_cast<int>(bytes_written); 313c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 314c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return rv; 315c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 316c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 317c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdochint FileStream::Flush() { 318ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::AssertIOAllowed(); 319ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 320c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (!IsOpen()) 321c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return ERR_UNEXPECTED; 322c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 323c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 324c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch if (FlushFileBuffers(file_)) { 325c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return OK; 326c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch } 327c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 328c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch int rv; 329c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch DWORD error = GetLastError(); 330c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch rv = MapErrorCode(error); 331c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch return rv; 332c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch} 333c407dc5cd9bdc5668497f21b26b09d988ab439deBen Murdoch 334c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scottint64 FileStream::Truncate(int64 bytes) { 335ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen base::ThreadRestrictions::AssertIOAllowed(); 336ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 337c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!IsOpen()) 338c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 339c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 340c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // We better be open for reading. 341c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); 342c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 343c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Seek to the position to truncate from. 344c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott int64 seek_position = Seek(FROM_BEGIN, bytes); 345c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (seek_position != bytes) 346c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return ERR_UNEXPECTED; 347c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 348c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // And truncate the file. 349c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott BOOL result = SetEndOfFile(file_); 350c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott if (!result) { 351c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott DWORD error = GetLastError(); 352c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott LOG(WARNING) << "SetEndOfFile failed: " << error; 353c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return MapErrorCode(error); 354c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott } 355c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 356c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott // Success. 357c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott return seek_position; 358c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} 359c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott 360c7f5f8508d98d5952d42ed7648c2a8f30a4da156Patrick Scott} // namespace net 361