file.cc 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  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
  3. // found in the LICENSE file.
  4. #include "base/files/file.h"
  5. #include <utility>
  6. #include "base/check_op.h"
  7. #include "base/files/file_path.h"
  8. #include "base/files/file_tracing.h"
  9. #include "base/metrics/histogram.h"
  10. #include "base/notreached.h"
  11. #include "base/numerics/safe_conversions.h"
  12. #include "base/timer/elapsed_timer.h"
  13. #include "base/trace_event/base_tracing.h"
  14. #include "build/build_config.h"
  15. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  16. #include <errno.h>
  17. #endif
  18. namespace base {
  19. File::Info::Info() = default;
  20. File::Info::~Info() = default;
  21. File::File() = default;
  22. #if !BUILDFLAG(IS_NACL)
  23. File::File(const FilePath& path, uint32_t flags) : error_details_(FILE_OK) {
  24. Initialize(path, flags);
  25. }
  26. #endif
  27. File::File(ScopedPlatformFile platform_file)
  28. : File(std::move(platform_file), false) {}
  29. File::File(PlatformFile platform_file) : File(platform_file, false) {}
  30. File::File(ScopedPlatformFile platform_file, bool async)
  31. : file_(std::move(platform_file)), error_details_(FILE_OK), async_(async) {
  32. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  33. DCHECK_GE(file_.get(), -1);
  34. #endif
  35. }
  36. File::File(PlatformFile platform_file, bool async)
  37. : file_(platform_file),
  38. error_details_(FILE_OK),
  39. async_(async) {
  40. #if BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  41. DCHECK_GE(platform_file, -1);
  42. #endif
  43. }
  44. File::File(Error error_details) : error_details_(error_details) {}
  45. File::File(File&& other)
  46. : file_(other.TakePlatformFile()),
  47. tracing_path_(other.tracing_path_),
  48. error_details_(other.error_details()),
  49. created_(other.created()),
  50. async_(other.async_) {}
  51. File::~File() {
  52. // Go through the AssertIOAllowed logic.
  53. Close();
  54. }
  55. File& File::operator=(File&& other) {
  56. Close();
  57. SetPlatformFile(other.TakePlatformFile());
  58. tracing_path_ = other.tracing_path_;
  59. error_details_ = other.error_details();
  60. created_ = other.created();
  61. async_ = other.async_;
  62. return *this;
  63. }
  64. #if !BUILDFLAG(IS_NACL)
  65. void File::Initialize(const FilePath& path, uint32_t flags) {
  66. if (path.ReferencesParent()) {
  67. #if BUILDFLAG(IS_WIN)
  68. ::SetLastError(ERROR_ACCESS_DENIED);
  69. #elif BUILDFLAG(IS_POSIX) || BUILDFLAG(IS_FUCHSIA)
  70. errno = EACCES;
  71. #else
  72. #error Unsupported platform
  73. #endif
  74. error_details_ = FILE_ERROR_ACCESS_DENIED;
  75. return;
  76. }
  77. if (FileTracing::IsCategoryEnabled())
  78. tracing_path_ = path;
  79. SCOPED_FILE_TRACE("Initialize");
  80. DoInitialize(path, flags);
  81. }
  82. #endif
  83. bool File::ReadAndCheck(int64_t offset, span<uint8_t> data) {
  84. int size = checked_cast<int>(data.size());
  85. return Read(offset, reinterpret_cast<char*>(data.data()), size) == size;
  86. }
  87. bool File::ReadAtCurrentPosAndCheck(span<uint8_t> data) {
  88. int size = checked_cast<int>(data.size());
  89. return ReadAtCurrentPos(reinterpret_cast<char*>(data.data()), size) == size;
  90. }
  91. bool File::WriteAndCheck(int64_t offset, span<const uint8_t> data) {
  92. int size = checked_cast<int>(data.size());
  93. return Write(offset, reinterpret_cast<const char*>(data.data()), size) ==
  94. size;
  95. }
  96. bool File::WriteAtCurrentPosAndCheck(span<const uint8_t> data) {
  97. int size = checked_cast<int>(data.size());
  98. return WriteAtCurrentPos(reinterpret_cast<const char*>(data.data()), size) ==
  99. size;
  100. }
  101. // static
  102. std::string File::ErrorToString(Error error) {
  103. switch (error) {
  104. case FILE_OK:
  105. return "FILE_OK";
  106. case FILE_ERROR_FAILED:
  107. return "FILE_ERROR_FAILED";
  108. case FILE_ERROR_IN_USE:
  109. return "FILE_ERROR_IN_USE";
  110. case FILE_ERROR_EXISTS:
  111. return "FILE_ERROR_EXISTS";
  112. case FILE_ERROR_NOT_FOUND:
  113. return "FILE_ERROR_NOT_FOUND";
  114. case FILE_ERROR_ACCESS_DENIED:
  115. return "FILE_ERROR_ACCESS_DENIED";
  116. case FILE_ERROR_TOO_MANY_OPENED:
  117. return "FILE_ERROR_TOO_MANY_OPENED";
  118. case FILE_ERROR_NO_MEMORY:
  119. return "FILE_ERROR_NO_MEMORY";
  120. case FILE_ERROR_NO_SPACE:
  121. return "FILE_ERROR_NO_SPACE";
  122. case FILE_ERROR_NOT_A_DIRECTORY:
  123. return "FILE_ERROR_NOT_A_DIRECTORY";
  124. case FILE_ERROR_INVALID_OPERATION:
  125. return "FILE_ERROR_INVALID_OPERATION";
  126. case FILE_ERROR_SECURITY:
  127. return "FILE_ERROR_SECURITY";
  128. case FILE_ERROR_ABORT:
  129. return "FILE_ERROR_ABORT";
  130. case FILE_ERROR_NOT_A_FILE:
  131. return "FILE_ERROR_NOT_A_FILE";
  132. case FILE_ERROR_NOT_EMPTY:
  133. return "FILE_ERROR_NOT_EMPTY";
  134. case FILE_ERROR_INVALID_URL:
  135. return "FILE_ERROR_INVALID_URL";
  136. case FILE_ERROR_IO:
  137. return "FILE_ERROR_IO";
  138. case FILE_ERROR_MAX:
  139. break;
  140. }
  141. NOTREACHED();
  142. return "";
  143. }
  144. void File::WriteIntoTrace(perfetto::TracedValue context) const {
  145. auto dict = std::move(context).WriteDictionary();
  146. dict.Add("is_valid", IsValid());
  147. dict.Add("created", created_);
  148. dict.Add("async", async_);
  149. dict.Add("error_details", ErrorToString(error_details_));
  150. }
  151. } // namespace base