| OLD | NEW | 
|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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.h" | 5 #include "net/base/file_stream.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" | 
| 11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" | 
| 12 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" | 
| 13 #include "base/threading/thread_restrictions.h" | 13 #include "base/threading/thread_restrictions.h" | 
|  | 14 #include "net/base/file_stream_metrics.h" | 
| 14 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" | 
| 15 | 16 | 
| 16 namespace net { | 17 namespace net { | 
| 17 | 18 | 
| 18 // Ensure that we can just use our Whence values directly. | 19 // Ensure that we can just use our Whence values directly. | 
| 19 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); | 20 COMPILE_ASSERT(FROM_BEGIN == FILE_BEGIN, bad_whence_begin); | 
| 20 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); | 21 COMPILE_ASSERT(FROM_CURRENT == FILE_CURRENT, bad_whence_current); | 
| 21 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); | 22 COMPILE_ASSERT(FROM_END == FILE_END, bad_whence_end); | 
| 22 | 23 | 
| 23 static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { | 24 static void SetOffset(OVERLAPPED* overlapped, const LARGE_INTEGER& offset) { | 
| (...skipping 17 matching lines...) Expand all  Loading... | 
| 41     case ERROR_ACCESS_DENIED: | 42     case ERROR_ACCESS_DENIED: | 
| 42       return ERR_ACCESS_DENIED; | 43       return ERR_ACCESS_DENIED; | 
| 43     case ERROR_SUCCESS: | 44     case ERROR_SUCCESS: | 
| 44       return OK; | 45       return OK; | 
| 45     default: | 46     default: | 
| 46       LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; | 47       LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; | 
| 47       return ERR_FAILED; | 48       return ERR_FAILED; | 
| 48   } | 49   } | 
| 49 } | 50 } | 
| 50 | 51 | 
|  | 52 namespace { | 
|  | 53 | 
|  | 54 int RecordAndMapError(int error, FileErrorSource source, bool record_uma) { | 
|  | 55   RecordFileError(error, source, record_uma); | 
|  | 56   return MapErrorCode(error); | 
|  | 57 } | 
|  | 58 | 
|  | 59 }  // namespace | 
|  | 60 | 
| 51 // FileStream::AsyncContext ---------------------------------------------- | 61 // FileStream::AsyncContext ---------------------------------------------- | 
| 52 | 62 | 
| 53 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { | 63 class FileStream::AsyncContext : public MessageLoopForIO::IOHandler { | 
| 54  public: | 64  public: | 
| 55   AsyncContext(FileStream* owner) | 65   AsyncContext(FileStream* owner) | 
| 56       : owner_(owner), context_(), callback_(NULL), is_closing_(false) { | 66       : owner_(owner), context_(), callback_(NULL), is_closing_(false), | 
|  | 67         record_uma_(false), error_source_(FILE_ERROR_SOURCE_COUNT) { | 
| 57     context_.handler = this; | 68     context_.handler = this; | 
| 58   } | 69   } | 
| 59   ~AsyncContext(); | 70   ~AsyncContext(); | 
| 60 | 71 | 
| 61   void IOCompletionIsPending(CompletionCallback* callback); | 72   void IOCompletionIsPending(CompletionCallback* callback); | 
| 62 | 73 | 
| 63   OVERLAPPED* overlapped() { return &context_.overlapped; } | 74   OVERLAPPED* overlapped() { return &context_.overlapped; } | 
| 64   CompletionCallback* callback() const { return callback_; } | 75   CompletionCallback* callback() const { return callback_; } | 
| 65 | 76 | 
|  | 77   void set_error_source(FileErrorSource source) { error_source_ = source; } | 
|  | 78 | 
|  | 79   void EnableErrorStatistics() { | 
|  | 80     record_uma_ = true; | 
|  | 81   } | 
|  | 82 | 
| 66  private: | 83  private: | 
| 67   virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 84   virtual void OnIOCompleted(MessageLoopForIO::IOContext* context, | 
| 68                              DWORD bytes_read, DWORD error); | 85                              DWORD bytes_read, DWORD error); | 
| 69 | 86 | 
| 70   FileStream* owner_; | 87   FileStream* owner_; | 
| 71   MessageLoopForIO::IOContext context_; | 88   MessageLoopForIO::IOContext context_; | 
| 72   CompletionCallback* callback_; | 89   CompletionCallback* callback_; | 
| 73   bool is_closing_; | 90   bool is_closing_; | 
|  | 91   bool record_uma_; | 
|  | 92   FileErrorSource error_source_; | 
| 74 }; | 93 }; | 
| 75 | 94 | 
| 76 FileStream::AsyncContext::~AsyncContext() { | 95 FileStream::AsyncContext::~AsyncContext() { | 
| 77   is_closing_ = true; | 96   is_closing_ = true; | 
| 78   bool waited = false; | 97   bool waited = false; | 
| 79   base::TimeTicks start = base::TimeTicks::Now(); | 98   base::TimeTicks start = base::TimeTicks::Now(); | 
| 80   while (callback_) { | 99   while (callback_) { | 
| 81     waited = true; | 100     waited = true; | 
| 82     MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); | 101     MessageLoopForIO::current()->WaitForIOCompletion(INFINITE, this); | 
| 83   } | 102   } | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 99   DCHECK_EQ(&context_, context); | 118   DCHECK_EQ(&context_, context); | 
| 100   DCHECK(callback_); | 119   DCHECK(callback_); | 
| 101 | 120 | 
| 102   if (is_closing_) { | 121   if (is_closing_) { | 
| 103     callback_ = NULL; | 122     callback_ = NULL; | 
| 104     return; | 123     return; | 
| 105   } | 124   } | 
| 106 | 125 | 
| 107   int result = static_cast<int>(bytes_read); | 126   int result = static_cast<int>(bytes_read); | 
| 108   if (error && error != ERROR_HANDLE_EOF) | 127   if (error && error != ERROR_HANDLE_EOF) | 
| 109     result = MapErrorCode(error); | 128     result = RecordAndMapError(error, error_source_, record_uma_); | 
| 110 | 129 | 
| 111   if (bytes_read) | 130   if (bytes_read) | 
| 112     IncrementOffset(&context->overlapped, bytes_read); | 131     IncrementOffset(&context->overlapped, bytes_read); | 
| 113 | 132 | 
| 114   CompletionCallback* temp = NULL; | 133   CompletionCallback* temp = NULL; | 
| 115   std::swap(temp, callback_); | 134   std::swap(temp, callback_); | 
| 116   temp->Run(result); | 135   temp->Run(result); | 
| 117 } | 136 } | 
| 118 | 137 | 
| 119 // FileStream ------------------------------------------------------------ | 138 // FileStream ------------------------------------------------------------ | 
| 120 | 139 | 
| 121 FileStream::FileStream() | 140 FileStream::FileStream() | 
| 122     : file_(INVALID_HANDLE_VALUE), | 141     : file_(INVALID_HANDLE_VALUE), | 
| 123       open_flags_(0), | 142       open_flags_(0), | 
| 124       auto_closed_(true) { | 143       auto_closed_(true), | 
|  | 144       record_uma_(false) { | 
| 125 } | 145 } | 
| 126 | 146 | 
| 127 FileStream::FileStream(base::PlatformFile file, int flags) | 147 FileStream::FileStream(base::PlatformFile file, int flags) | 
| 128     : file_(file), | 148     : file_(file), | 
| 129       open_flags_(flags), | 149       open_flags_(flags), | 
| 130       auto_closed_(false) { | 150       auto_closed_(false), | 
|  | 151       record_uma_(false) { | 
| 131   // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to | 152   // If the file handle is opened with base::PLATFORM_FILE_ASYNC, we need to | 
| 132   // make sure we will perform asynchronous File IO to it. | 153   // make sure we will perform asynchronous File IO to it. | 
| 133   if (flags & base::PLATFORM_FILE_ASYNC) { | 154   if (flags & base::PLATFORM_FILE_ASYNC) { | 
| 134     async_context_.reset(new AsyncContext(this)); | 155     async_context_.reset(new AsyncContext(this)); | 
| 135     MessageLoopForIO::current()->RegisterIOHandler(file_, | 156     MessageLoopForIO::current()->RegisterIOHandler(file_, | 
| 136                                                    async_context_.get()); | 157                                                    async_context_.get()); | 
| 137   } | 158   } | 
| 138 } | 159 } | 
| 139 | 160 | 
| 140 FileStream::~FileStream() { | 161 FileStream::~FileStream() { | 
| (...skipping 16 matching lines...) Expand all  Loading... | 
| 157   if (IsOpen()) { | 178   if (IsOpen()) { | 
| 158     DLOG(FATAL) << "File is already open!"; | 179     DLOG(FATAL) << "File is already open!"; | 
| 159     return ERR_UNEXPECTED; | 180     return ERR_UNEXPECTED; | 
| 160   } | 181   } | 
| 161 | 182 | 
| 162   open_flags_ = open_flags; | 183   open_flags_ = open_flags; | 
| 163   file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); | 184   file_ = base::CreatePlatformFile(path, open_flags_, NULL, NULL); | 
| 164   if (file_ == INVALID_HANDLE_VALUE) { | 185   if (file_ == INVALID_HANDLE_VALUE) { | 
| 165     DWORD error = GetLastError(); | 186     DWORD error = GetLastError(); | 
| 166     LOG(WARNING) << "Failed to open file: " << error; | 187     LOG(WARNING) << "Failed to open file: " << error; | 
| 167     return MapErrorCode(error); | 188     return RecordAndMapError(error, FILE_ERROR_SOURCE_OPEN, record_uma_); | 
| 168   } | 189   } | 
| 169 | 190 | 
| 170   if (open_flags_ & base::PLATFORM_FILE_ASYNC) { | 191   if (open_flags_ & base::PLATFORM_FILE_ASYNC) { | 
| 171     async_context_.reset(new AsyncContext(this)); | 192     async_context_.reset(new AsyncContext(this)); | 
|  | 193     if (record_uma_) | 
|  | 194       async_context_->EnableErrorStatistics(); | 
| 172     MessageLoopForIO::current()->RegisterIOHandler(file_, | 195     MessageLoopForIO::current()->RegisterIOHandler(file_, | 
| 173                                                    async_context_.get()); | 196                                                    async_context_.get()); | 
| 174   } | 197   } | 
| 175 | 198 | 
| 176   return OK; | 199   return OK; | 
| 177 } | 200 } | 
| 178 | 201 | 
| 179 bool FileStream::IsOpen() const { | 202 bool FileStream::IsOpen() const { | 
| 180   return file_ != INVALID_HANDLE_VALUE; | 203   return file_ != INVALID_HANDLE_VALUE; | 
| 181 } | 204 } | 
| 182 | 205 | 
| 183 int64 FileStream::Seek(Whence whence, int64 offset) { | 206 int64 FileStream::Seek(Whence whence, int64 offset) { | 
| 184   if (!IsOpen()) | 207   if (!IsOpen()) | 
| 185     return ERR_UNEXPECTED; | 208     return ERR_UNEXPECTED; | 
|  | 209 | 
| 186   DCHECK(!async_context_.get() || !async_context_->callback()); | 210   DCHECK(!async_context_.get() || !async_context_->callback()); | 
| 187 | 211 | 
| 188   LARGE_INTEGER distance, result; | 212   LARGE_INTEGER distance, result; | 
| 189   distance.QuadPart = offset; | 213   distance.QuadPart = offset; | 
| 190   DWORD move_method = static_cast<DWORD>(whence); | 214   DWORD move_method = static_cast<DWORD>(whence); | 
| 191   if (!SetFilePointerEx(file_, distance, &result, move_method)) { | 215   if (!SetFilePointerEx(file_, distance, &result, move_method)) { | 
| 192     DWORD error = GetLastError(); | 216     DWORD error = GetLastError(); | 
| 193     LOG(WARNING) << "SetFilePointerEx failed: " << error; | 217     LOG(WARNING) << "SetFilePointerEx failed: " << error; | 
| 194     return MapErrorCode(error); | 218     return RecordAndMapError(error, FILE_ERROR_SOURCE_SEEK, record_uma_); | 
| 195   } | 219   } | 
| 196   if (async_context_.get()) | 220   if (async_context_.get()) { | 
|  | 221     async_context_->set_error_source(FILE_ERROR_SOURCE_SEEK); | 
| 197     SetOffset(async_context_->overlapped(), result); | 222     SetOffset(async_context_->overlapped(), result); | 
|  | 223   } | 
| 198   return result.QuadPart; | 224   return result.QuadPart; | 
| 199 } | 225 } | 
| 200 | 226 | 
| 201 int64 FileStream::Available() { | 227 int64 FileStream::Available() { | 
| 202   base::ThreadRestrictions::AssertIOAllowed(); | 228   base::ThreadRestrictions::AssertIOAllowed(); | 
| 203 | 229 | 
| 204   if (!IsOpen()) | 230   if (!IsOpen()) | 
| 205     return ERR_UNEXPECTED; | 231     return ERR_UNEXPECTED; | 
| 206 | 232 | 
| 207   int64 cur_pos = Seek(FROM_CURRENT, 0); | 233   int64 cur_pos = Seek(FROM_CURRENT, 0); | 
| 208   if (cur_pos < 0) | 234   if (cur_pos < 0) | 
| 209     return cur_pos; | 235     return cur_pos; | 
| 210 | 236 | 
| 211   LARGE_INTEGER file_size; | 237   LARGE_INTEGER file_size; | 
| 212   if (!GetFileSizeEx(file_, &file_size)) { | 238   if (!GetFileSizeEx(file_, &file_size)) { | 
| 213     DWORD error = GetLastError(); | 239     DWORD error = GetLastError(); | 
| 214     LOG(WARNING) << "GetFileSizeEx failed: " << error; | 240     LOG(WARNING) << "GetFileSizeEx failed: " << error; | 
| 215     return MapErrorCode(error); | 241     return RecordAndMapError(error, FILE_ERROR_SOURCE_GET_SIZE, record_uma_); | 
| 216   } | 242   } | 
| 217 | 243 | 
| 218   return file_size.QuadPart - cur_pos; | 244   return file_size.QuadPart - cur_pos; | 
| 219 } | 245 } | 
| 220 | 246 | 
| 221 int FileStream::Read( | 247 int FileStream::Read( | 
| 222     char* buf, int buf_len, CompletionCallback* callback) { | 248     char* buf, int buf_len, CompletionCallback* callback) { | 
| 223   if (!IsOpen()) | 249   if (!IsOpen()) | 
| 224     return ERR_UNEXPECTED; | 250     return ERR_UNEXPECTED; | 
|  | 251 | 
| 225   DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | 252   DCHECK(open_flags_ & base::PLATFORM_FILE_READ); | 
| 226 | 253 | 
| 227   OVERLAPPED* overlapped = NULL; | 254   OVERLAPPED* overlapped = NULL; | 
| 228   if (async_context_.get()) { | 255   if (async_context_.get()) { | 
| 229     DCHECK(callback); | 256     DCHECK(callback); | 
| 230     DCHECK(!async_context_->callback()); | 257     DCHECK(!async_context_->callback()); | 
| 231     overlapped = async_context_->overlapped(); | 258     overlapped = async_context_->overlapped(); | 
|  | 259     async_context_->set_error_source(FILE_ERROR_SOURCE_READ); | 
| 232   } else { | 260   } else { | 
| 233     DCHECK(!callback); | 261     DCHECK(!callback); | 
| 234     base::ThreadRestrictions::AssertIOAllowed(); | 262     base::ThreadRestrictions::AssertIOAllowed(); | 
| 235   } | 263   } | 
| 236 | 264 | 
| 237   int rv; | 265   int rv; | 
| 238 | 266 | 
| 239   DWORD bytes_read; | 267   DWORD bytes_read; | 
| 240   if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { | 268   if (!ReadFile(file_, buf, buf_len, &bytes_read, overlapped)) { | 
| 241     DWORD error = GetLastError(); | 269     DWORD error = GetLastError(); | 
| 242     if (async_context_.get() && error == ERROR_IO_PENDING) { | 270     if (async_context_.get() && error == ERROR_IO_PENDING) { | 
| 243       async_context_->IOCompletionIsPending(callback); | 271       async_context_->IOCompletionIsPending(callback); | 
| 244       rv = ERR_IO_PENDING; | 272       rv = ERR_IO_PENDING; | 
| 245     } else if (error == ERROR_HANDLE_EOF) { | 273     } else if (error == ERROR_HANDLE_EOF) { | 
| 246       rv = 0;  // Report EOF by returning 0 bytes read. | 274       rv = 0;  // Report EOF by returning 0 bytes read. | 
| 247     } else { | 275     } else { | 
| 248       LOG(WARNING) << "ReadFile failed: " << error; | 276       LOG(WARNING) << "ReadFile failed: " << error; | 
| 249       rv = MapErrorCode(error); | 277       rv = RecordAndMapError(error, FILE_ERROR_SOURCE_READ, record_uma_); | 
| 250     } | 278     } | 
| 251   } else if (overlapped) { | 279   } else if (overlapped) { | 
| 252     async_context_->IOCompletionIsPending(callback); | 280     async_context_->IOCompletionIsPending(callback); | 
| 253     rv = ERR_IO_PENDING; | 281     rv = ERR_IO_PENDING; | 
| 254   } else { | 282   } else { | 
| 255     rv = static_cast<int>(bytes_read); | 283     rv = static_cast<int>(bytes_read); | 
| 256   } | 284   } | 
| 257   return rv; | 285   return rv; | 
| 258 } | 286 } | 
| 259 | 287 | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
| 275     to_read -= bytes_read; | 303     to_read -= bytes_read; | 
| 276   } while (bytes_total < buf_len); | 304   } while (bytes_total < buf_len); | 
| 277 | 305 | 
| 278   return bytes_total; | 306   return bytes_total; | 
| 279 } | 307 } | 
| 280 | 308 | 
| 281 int FileStream::Write( | 309 int FileStream::Write( | 
| 282     const char* buf, int buf_len, CompletionCallback* callback) { | 310     const char* buf, int buf_len, CompletionCallback* callback) { | 
| 283   if (!IsOpen()) | 311   if (!IsOpen()) | 
| 284     return ERR_UNEXPECTED; | 312     return ERR_UNEXPECTED; | 
|  | 313 | 
| 285   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 314   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 
| 286 | 315 | 
| 287   OVERLAPPED* overlapped = NULL; | 316   OVERLAPPED* overlapped = NULL; | 
| 288   if (async_context_.get()) { | 317   if (async_context_.get()) { | 
| 289     DCHECK(callback); | 318     DCHECK(callback); | 
| 290     DCHECK(!async_context_->callback()); | 319     DCHECK(!async_context_->callback()); | 
| 291     overlapped = async_context_->overlapped(); | 320     overlapped = async_context_->overlapped(); | 
|  | 321     async_context_->set_error_source(FILE_ERROR_SOURCE_WRITE); | 
| 292   } else { | 322   } else { | 
| 293     DCHECK(!callback); | 323     DCHECK(!callback); | 
| 294     base::ThreadRestrictions::AssertIOAllowed(); | 324     base::ThreadRestrictions::AssertIOAllowed(); | 
| 295   } | 325   } | 
| 296 | 326 | 
| 297   int rv; | 327   int rv; | 
| 298   DWORD bytes_written; | 328   DWORD bytes_written; | 
| 299   if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { | 329   if (!WriteFile(file_, buf, buf_len, &bytes_written, overlapped)) { | 
| 300     DWORD error = GetLastError(); | 330     DWORD error = GetLastError(); | 
| 301     if (async_context_.get() && error == ERROR_IO_PENDING) { | 331     if (async_context_.get() && error == ERROR_IO_PENDING) { | 
| 302       async_context_->IOCompletionIsPending(callback); | 332       async_context_->IOCompletionIsPending(callback); | 
| 303       rv = ERR_IO_PENDING; | 333       rv = ERR_IO_PENDING; | 
| 304     } else { | 334     } else { | 
| 305       LOG(WARNING) << "WriteFile failed: " << error; | 335       LOG(WARNING) << "WriteFile failed: " << error; | 
| 306       rv = MapErrorCode(error); | 336       rv = RecordAndMapError(error, FILE_ERROR_SOURCE_WRITE, record_uma_); | 
| 307     } | 337     } | 
| 308   } else if (overlapped) { | 338   } else if (overlapped) { | 
| 309     async_context_->IOCompletionIsPending(callback); | 339     async_context_->IOCompletionIsPending(callback); | 
| 310     rv = ERR_IO_PENDING; | 340     rv = ERR_IO_PENDING; | 
| 311   } else { | 341   } else { | 
| 312     rv = static_cast<int>(bytes_written); | 342     rv = static_cast<int>(bytes_written); | 
| 313   } | 343   } | 
| 314   return rv; | 344   return rv; | 
| 315 } | 345 } | 
| 316 | 346 | 
| 317 int FileStream::Flush() { | 347 int FileStream::Flush() { | 
| 318   base::ThreadRestrictions::AssertIOAllowed(); | 348   base::ThreadRestrictions::AssertIOAllowed(); | 
| 319 | 349 | 
| 320   if (!IsOpen()) | 350   if (!IsOpen()) | 
| 321     return ERR_UNEXPECTED; | 351     return ERR_UNEXPECTED; | 
| 322 | 352 | 
| 323   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 353   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 
| 324   if (FlushFileBuffers(file_)) { | 354   if (FlushFileBuffers(file_)) { | 
| 325     return OK; | 355     return OK; | 
| 326   } | 356   } | 
| 327 | 357 | 
| 328   int rv; | 358   return RecordAndMapError(GetLastError(), | 
| 329   DWORD error = GetLastError(); | 359                            FILE_ERROR_SOURCE_FLUSH, | 
| 330   rv = MapErrorCode(error); | 360                            record_uma_); | 
| 331   return rv; |  | 
| 332 } | 361 } | 
| 333 | 362 | 
| 334 int64 FileStream::Truncate(int64 bytes) { | 363 int64 FileStream::Truncate(int64 bytes) { | 
| 335   base::ThreadRestrictions::AssertIOAllowed(); | 364   base::ThreadRestrictions::AssertIOAllowed(); | 
| 336 | 365 | 
| 337   if (!IsOpen()) | 366   if (!IsOpen()) | 
| 338     return ERR_UNEXPECTED; | 367     return ERR_UNEXPECTED; | 
| 339 | 368 | 
| 340   // We better be open for reading. | 369   // We better be open for reading. | 
| 341   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 370   DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 
| 342 | 371 | 
| 343   // Seek to the position to truncate from. | 372   // Seek to the position to truncate from. | 
| 344   int64 seek_position = Seek(FROM_BEGIN, bytes); | 373   int64 seek_position = Seek(FROM_BEGIN, bytes); | 
| 345   if (seek_position != bytes) | 374   if (seek_position != bytes) | 
| 346     return ERR_UNEXPECTED; | 375     return ERR_UNEXPECTED; | 
| 347 | 376 | 
| 348   // And truncate the file. | 377   // And truncate the file. | 
| 349   BOOL result = SetEndOfFile(file_); | 378   BOOL result = SetEndOfFile(file_); | 
| 350   if (!result) { | 379   if (!result) { | 
| 351     DWORD error = GetLastError(); | 380     DWORD error = GetLastError(); | 
| 352     LOG(WARNING) << "SetEndOfFile failed: " << error; | 381     LOG(WARNING) << "SetEndOfFile failed: " << error; | 
| 353     return MapErrorCode(error); | 382     return RecordAndMapError(error, FILE_ERROR_SOURCE_SET_EOF, record_uma_); | 
| 354   } | 383   } | 
| 355 | 384 | 
| 356   // Success. | 385   // Success. | 
| 357   return seek_position; | 386   return seek_position; | 
| 358 } | 387 } | 
| 359 | 388 | 
|  | 389 void FileStream::EnableErrorStatistics() { | 
|  | 390   record_uma_ = true; | 
|  | 391 | 
|  | 392   if (async_context_.get()) | 
|  | 393     async_context_->EnableErrorStatistics(); | 
|  | 394 } | 
|  | 395 | 
| 360 }  // namespace net | 396 }  // namespace net | 
| OLD | NEW | 
|---|