OLD | NEW |
1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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 // For 64-bit file access (off_t = off64_t, lseek64, etc). | 5 // For 64-bit file access (off_t = off64_t, lseek64, etc). |
6 #define _FILE_OFFSET_BITS 64 | 6 #define _FILE_OFFSET_BITS 64 |
7 | 7 |
8 #include "net/base/file_stream.h" | 8 #include "net/base/file_stream.h" |
9 | 9 |
10 #include <sys/types.h> | 10 #include <sys/types.h> |
11 #include <sys/stat.h> | 11 #include <sys/stat.h> |
12 #include <fcntl.h> | 12 #include <fcntl.h> |
13 #include <unistd.h> | 13 #include <unistd.h> |
14 #include <errno.h> | 14 #include <errno.h> |
15 | 15 |
16 #include "base/basictypes.h" | 16 #include "base/basictypes.h" |
17 #include "base/callback.h" | 17 #include "base/callback.h" |
18 #include "base/eintr_wrapper.h" | 18 #include "base/eintr_wrapper.h" |
19 #include "base/file_path.h" | 19 #include "base/file_path.h" |
20 #include "base/logging.h" | 20 #include "base/logging.h" |
21 #include "base/message_loop.h" | 21 #include "base/message_loop.h" |
22 #include "base/metrics/histogram.h" | 22 #include "base/metrics/histogram.h" |
23 #include "base/string_util.h" | 23 #include "base/string_util.h" |
| 24 #include "base/threading/thread_restrictions.h" |
24 #include "base/threading/worker_pool.h" | 25 #include "base/threading/worker_pool.h" |
25 #include "base/synchronization/waitable_event.h" | 26 #include "base/synchronization/waitable_event.h" |
26 #include "net/base/net_errors.h" | 27 #include "net/base/net_errors.h" |
27 | 28 |
28 // We cast back and forth, so make sure it's the size we're expecting. | 29 // We cast back and forth, so make sure it's the size we're expecting. |
29 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); | 30 COMPILE_ASSERT(sizeof(int64) == sizeof(off_t), off_t_64_bit); |
30 | 31 |
31 // Make sure our Whence mappings match the system headers. | 32 // Make sure our Whence mappings match the system headers. |
32 COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && | 33 COMPILE_ASSERT(net::FROM_BEGIN == SEEK_SET && |
33 net::FROM_CURRENT == SEEK_CUR && | 34 net::FROM_CURRENT == SEEK_CUR && |
(...skipping 11 matching lines...) Expand all Loading... |
45 return ERR_ACCESS_DENIED; | 46 return ERR_ACCESS_DENIED; |
46 default: | 47 default: |
47 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; | 48 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; |
48 return ERR_FAILED; | 49 return ERR_FAILED; |
49 } | 50 } |
50 } | 51 } |
51 | 52 |
52 // ReadFile() is a simple wrapper around read() that handles EINTR signals and | 53 // ReadFile() is a simple wrapper around read() that handles EINTR signals and |
53 // calls MapErrorCode() to map errno to net error codes. | 54 // calls MapErrorCode() to map errno to net error codes. |
54 int ReadFile(base::PlatformFile file, char* buf, int buf_len) { | 55 int ReadFile(base::PlatformFile file, char* buf, int buf_len) { |
| 56 base::ThreadRestrictions::AssertIOAllowed(); |
55 // read(..., 0) returns 0 to indicate end-of-file. | 57 // read(..., 0) returns 0 to indicate end-of-file. |
56 | 58 |
57 // Loop in the case of getting interrupted by a signal. | 59 // Loop in the case of getting interrupted by a signal. |
58 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len))); | 60 ssize_t res = HANDLE_EINTR(read(file, buf, static_cast<size_t>(buf_len))); |
59 if (res == static_cast<ssize_t>(-1)) | 61 if (res == static_cast<ssize_t>(-1)) |
60 return MapErrorCode(errno); | 62 return MapErrorCode(errno); |
61 return static_cast<int>(res); | 63 return static_cast<int>(res); |
62 } | 64 } |
63 | 65 |
64 // WriteFile() is a simple wrapper around write() that handles EINTR signals and | 66 // WriteFile() is a simple wrapper around write() that handles EINTR signals and |
65 // calls MapErrorCode() to map errno to net error codes. It tries to write to | 67 // calls MapErrorCode() to map errno to net error codes. It tries to write to |
66 // completion. | 68 // completion. |
67 int WriteFile(base::PlatformFile file, const char* buf, int buf_len) { | 69 int WriteFile(base::PlatformFile file, const char* buf, int buf_len) { |
| 70 base::ThreadRestrictions::AssertIOAllowed(); |
68 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len)); | 71 ssize_t res = HANDLE_EINTR(write(file, buf, buf_len)); |
69 if (res == -1) | 72 if (res == -1) |
70 return MapErrorCode(errno); | 73 return MapErrorCode(errno); |
71 return res; | 74 return res; |
72 } | 75 } |
73 | 76 |
74 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and | 77 // FlushFile() is a simple wrapper around fsync() that handles EINTR signals and |
75 // calls MapErrorCode() to map errno to net error codes. It tries to flush to | 78 // calls MapErrorCode() to map errno to net error codes. It tries to flush to |
76 // completion. | 79 // completion. |
77 int FlushFile(base::PlatformFile file) { | 80 int FlushFile(base::PlatformFile file) { |
| 81 base::ThreadRestrictions::AssertIOAllowed(); |
78 ssize_t res = HANDLE_EINTR(fsync(file)); | 82 ssize_t res = HANDLE_EINTR(fsync(file)); |
79 if (res == -1) | 83 if (res == -1) |
80 return MapErrorCode(errno); | 84 return MapErrorCode(errno); |
81 return res; | 85 return res; |
82 } | 86 } |
83 | 87 |
84 // BackgroundReadTask is a simple task that reads a file and then runs | 88 // BackgroundReadTask is a simple task that reads a file and then runs |
85 // |callback|. AsyncContext will post this task to the WorkerPool. | 89 // |callback|. AsyncContext will post this task to the WorkerPool. |
86 class BackgroundReadTask : public Task { | 90 class BackgroundReadTask : public Task { |
87 public: | 91 public: |
(...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 } | 359 } |
356 | 360 |
357 return OK; | 361 return OK; |
358 } | 362 } |
359 | 363 |
360 bool FileStream::IsOpen() const { | 364 bool FileStream::IsOpen() const { |
361 return file_ != base::kInvalidPlatformFileValue; | 365 return file_ != base::kInvalidPlatformFileValue; |
362 } | 366 } |
363 | 367 |
364 int64 FileStream::Seek(Whence whence, int64 offset) { | 368 int64 FileStream::Seek(Whence whence, int64 offset) { |
| 369 base::ThreadRestrictions::AssertIOAllowed(); |
| 370 |
365 if (!IsOpen()) | 371 if (!IsOpen()) |
366 return ERR_UNEXPECTED; | 372 return ERR_UNEXPECTED; |
367 | 373 |
368 // If we're in async, make sure we don't have a request in flight. | 374 // If we're in async, make sure we don't have a request in flight. |
369 DCHECK(!async_context_.get() || !async_context_->callback()); | 375 DCHECK(!async_context_.get() || !async_context_->callback()); |
370 | 376 |
371 off_t res = lseek(file_, static_cast<off_t>(offset), | 377 off_t res = lseek(file_, static_cast<off_t>(offset), |
372 static_cast<int>(whence)); | 378 static_cast<int>(whence)); |
373 if (res == static_cast<off_t>(-1)) | 379 if (res == static_cast<off_t>(-1)) |
374 return MapErrorCode(errno); | 380 return MapErrorCode(errno); |
375 | 381 |
376 return res; | 382 return res; |
377 } | 383 } |
378 | 384 |
379 int64 FileStream::Available() { | 385 int64 FileStream::Available() { |
| 386 base::ThreadRestrictions::AssertIOAllowed(); |
| 387 |
380 if (!IsOpen()) | 388 if (!IsOpen()) |
381 return ERR_UNEXPECTED; | 389 return ERR_UNEXPECTED; |
382 | 390 |
383 int64 cur_pos = Seek(FROM_CURRENT, 0); | 391 int64 cur_pos = Seek(FROM_CURRENT, 0); |
384 if (cur_pos < 0) | 392 if (cur_pos < 0) |
385 return cur_pos; | 393 return cur_pos; |
386 | 394 |
387 struct stat info; | 395 struct stat info; |
388 if (fstat(file_, &info) != 0) | 396 if (fstat(file_, &info) != 0) |
389 return MapErrorCode(errno); | 397 return MapErrorCode(errno); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
431 buf += bytes_read; | 439 buf += bytes_read; |
432 to_read -= bytes_read; | 440 to_read -= bytes_read; |
433 } while (bytes_total < buf_len); | 441 } while (bytes_total < buf_len); |
434 | 442 |
435 return bytes_total; | 443 return bytes_total; |
436 } | 444 } |
437 | 445 |
438 int FileStream::Write( | 446 int FileStream::Write( |
439 const char* buf, int buf_len, CompletionCallback* callback) { | 447 const char* buf, int buf_len, CompletionCallback* callback) { |
440 // write(..., 0) will return 0, which indicates end-of-file. | 448 // write(..., 0) will return 0, which indicates end-of-file. |
441 DCHECK(buf_len > 0); | 449 DCHECK_GT(buf_len, 0); |
442 | 450 |
443 if (!IsOpen()) | 451 if (!IsOpen()) |
444 return ERR_UNEXPECTED; | 452 return ERR_UNEXPECTED; |
445 | 453 |
446 if (async_context_.get()) { | 454 if (async_context_.get()) { |
447 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); | 455 DCHECK(open_flags_ & base::PLATFORM_FILE_ASYNC); |
448 // If we're in async, make sure we don't have a request in flight. | 456 // If we're in async, make sure we don't have a request in flight. |
449 DCHECK(!async_context_->callback()); | 457 DCHECK(!async_context_->callback()); |
450 async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback); | 458 async_context_->InitiateAsyncWrite(file_, buf, buf_len, callback); |
451 return ERR_IO_PENDING; | 459 return ERR_IO_PENDING; |
452 } else { | 460 } else { |
453 return WriteFile(file_, buf, buf_len); | 461 return WriteFile(file_, buf, buf_len); |
454 } | 462 } |
455 } | 463 } |
456 | 464 |
457 int64 FileStream::Truncate(int64 bytes) { | 465 int64 FileStream::Truncate(int64 bytes) { |
| 466 base::ThreadRestrictions::AssertIOAllowed(); |
| 467 |
458 if (!IsOpen()) | 468 if (!IsOpen()) |
459 return ERR_UNEXPECTED; | 469 return ERR_UNEXPECTED; |
460 | 470 |
461 // We better be open for reading. | 471 // We better be open for reading. |
462 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); | 472 DCHECK(open_flags_ & base::PLATFORM_FILE_WRITE); |
463 | 473 |
464 // Seek to the position to truncate from. | 474 // Seek to the position to truncate from. |
465 int64 seek_position = Seek(FROM_BEGIN, bytes); | 475 int64 seek_position = Seek(FROM_BEGIN, bytes); |
466 if (seek_position != bytes) | 476 if (seek_position != bytes) |
467 return ERR_UNEXPECTED; | 477 return ERR_UNEXPECTED; |
468 | 478 |
469 // And truncate the file. | 479 // And truncate the file. |
470 int result = ftruncate(file_, bytes); | 480 int result = ftruncate(file_, bytes); |
471 return result == 0 ? seek_position : MapErrorCode(errno); | 481 return result == 0 ? seek_position : MapErrorCode(errno); |
472 } | 482 } |
473 | 483 |
474 int FileStream::Flush() { | 484 int FileStream::Flush() { |
475 if (!IsOpen()) | 485 if (!IsOpen()) |
476 return ERR_UNEXPECTED; | 486 return ERR_UNEXPECTED; |
477 | 487 |
478 return FlushFile(file_); | 488 return FlushFile(file_); |
479 } | 489 } |
480 | 490 |
481 } // namespace net | 491 } // namespace net |
OLD | NEW |