file_stream.cc 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102
  1. // Copyright 2017 The Chromium OS Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. #include "puffin/file_stream.h"
  5. #include <fcntl.h>
  6. #include <algorithm>
  7. #include <cstdint>
  8. #include <utility>
  9. #include "base/files/file_path.h"
  10. #include "base/files/file_util.h"
  11. #include "base/numerics/safe_conversions.h"
  12. #include "puffin/src/include/puffin/common.h"
  13. #include "puffin/src/logging.h"
  14. using std::string;
  15. namespace puffin {
  16. UniqueStreamPtr FileStream::Open(const string& path, bool read, bool write) {
  17. TEST_AND_RETURN_VALUE(read || write, nullptr);
  18. uint32_t flags = 0;
  19. base::FilePath file_path = base::FilePath::FromUTF8Unsafe(path.c_str());
  20. if (read && write) {
  21. flags |= base::File::Flags::FLAG_READ | base::File::Flags::FLAG_WRITE |
  22. base::File::Flags::FLAG_OPEN_ALWAYS;
  23. } else if (read) {
  24. flags |= base::File::Flags::FLAG_READ | base::File::Flags::FLAG_OPEN;
  25. TEST_AND_RETURN_VALUE(PathExists(file_path), nullptr);
  26. } else {
  27. flags |=
  28. base::File::Flags::FLAG_WRITE | base::File::Flags::FLAG_OPEN_ALWAYS;
  29. }
  30. return UniqueStreamPtr(new FileStream(file_path, flags));
  31. }
  32. UniqueStreamPtr FileStream::CreateStreamFromFile(base::File file) {
  33. return UniqueStreamPtr(new FileStream(std::move(file)));
  34. }
  35. bool FileStream::GetSize(uint64_t* size) {
  36. TEST_AND_RETURN_FALSE(file_.IsValid());
  37. int64_t result = file_.GetLength();
  38. TEST_AND_RETURN_FALSE(result >= 0);
  39. *size = base::as_unsigned(result);
  40. return true;
  41. }
  42. bool FileStream::GetOffset(uint64_t* offset) {
  43. int64_t off = file_.Seek(base::File::Whence::FROM_CURRENT, 0);
  44. TEST_AND_RETURN_FALSE(off >= 0);
  45. *offset = base::as_unsigned(off);
  46. return true;
  47. }
  48. bool FileStream::Seek(uint64_t u_offset) {
  49. TEST_AND_RETURN_FALSE(base::IsValueInRangeForNumericType<int64_t>(u_offset));
  50. int64_t offset = base::as_signed(u_offset);
  51. int64_t off =
  52. base::as_signed(file_.Seek(base::File::Whence::FROM_BEGIN, offset));
  53. TEST_AND_RETURN_FALSE(off == offset);
  54. return true;
  55. }
  56. bool FileStream::Read(void* buffer, size_t length) {
  57. auto c_bytes = static_cast<char*>(buffer);
  58. size_t total_bytes_read = 0;
  59. while (total_bytes_read < length) {
  60. auto bytes_read = file_.ReadAtCurrentPos(c_bytes + total_bytes_read,
  61. length - total_bytes_read);
  62. // if bytes_read is zero then EOF is reached and we should not be here.
  63. TEST_AND_RETURN_FALSE(bytes_read > 0);
  64. total_bytes_read += bytes_read;
  65. }
  66. return true;
  67. }
  68. bool FileStream::Write(const void* buffer, size_t length) {
  69. auto c_bytes = static_cast<const char*>(buffer);
  70. size_t total_bytes_wrote = 0;
  71. while (total_bytes_wrote < length) {
  72. auto bytes_wrote = file_.WriteAtCurrentPos(c_bytes + total_bytes_wrote,
  73. length - total_bytes_wrote);
  74. TEST_AND_RETURN_FALSE(bytes_wrote >= 0);
  75. total_bytes_wrote += bytes_wrote;
  76. }
  77. return true;
  78. }
  79. bool FileStream::Close() {
  80. if (!file_.IsValid()) {
  81. return false;
  82. }
  83. file_.Close();
  84. return true;
  85. }
  86. } // namespace puffin