/third_party/ijar/mapped_file_windows.cc

https://github.com/google/bazel · C++ · 211 lines · 159 code · 36 blank · 16 comment · 27 complexity · e803105480a59c91a17bd8052684dcf9 MD5 · raw file

  1. // Copyright 2015 The Bazel Authors. All rights reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. #include <stdio.h>
  15. #include <windows.h>
  16. #include <string>
  17. #include "src/main/cpp/util/errors.h"
  18. #include "src/main/cpp/util/logging.h"
  19. #include "src/main/cpp/util/path_platform.h"
  20. #include "src/main/cpp/util/strings.h"
  21. #include "third_party/ijar/mapped_file.h"
  22. #define MAX_ERROR 2048
  23. namespace devtools_ijar {
  24. using std::string;
  25. using std::wstring;
  26. static char errmsg[MAX_ERROR] = "";
  27. struct MappedInputFileImpl {
  28. HANDLE file_;
  29. HANDLE mapping_;
  30. MappedInputFileImpl(HANDLE file, HANDLE mapping) {
  31. file_ = file;
  32. mapping_ = mapping;
  33. }
  34. };
  35. MappedInputFile::MappedInputFile(const char* name) {
  36. impl_ = NULL;
  37. opened_ = false;
  38. errmsg_ = errmsg;
  39. wstring wname;
  40. string error;
  41. if (!blaze_util::AsAbsoluteWindowsPath(name, &wname, &error)) {
  42. BAZEL_DIE(255) << "MappedInputFile(" << name
  43. << "): AsAbsoluteWindowsPath failed: " << error;
  44. }
  45. HANDLE file = CreateFileW(wname.c_str(), GENERIC_READ, FILE_SHARE_READ, NULL,
  46. OPEN_EXISTING, 0, NULL);
  47. if (file == INVALID_HANDLE_VALUE) {
  48. string errormsg = blaze_util::GetLastErrorString();
  49. BAZEL_DIE(255) << "MappedInputFile(" << name << "): CreateFileW("
  50. << blaze_util::WstringToCstring(wname)
  51. << ") failed: " << errormsg;
  52. }
  53. LARGE_INTEGER size;
  54. if (!GetFileSizeEx(file, &size)) {
  55. string errormsg = blaze_util::GetLastErrorString();
  56. BAZEL_DIE(255) << "MappedInputFile(" << name
  57. << "): GetFileSizeEx failed: " << errormsg;
  58. }
  59. HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READONLY,
  60. size.HighPart, size.LowPart, NULL);
  61. if (mapping == NULL || mapping == INVALID_HANDLE_VALUE) {
  62. string errormsg = blaze_util::GetLastErrorString();
  63. BAZEL_DIE(255) << "MappedInputFile(" << name
  64. << "): CreateFileMapping failed: " << errormsg;
  65. }
  66. void *view = MapViewOfFileEx(mapping, FILE_MAP_READ, 0, 0, 0, NULL);
  67. if (view == NULL) {
  68. string errormsg = blaze_util::GetLastErrorString();
  69. BAZEL_DIE(255) << "MappedInputFile(" << name
  70. << "): MapViewOfFileEx failed: " << errormsg;
  71. }
  72. impl_ = new MappedInputFileImpl(file, mapping);
  73. length_ = size.QuadPart;
  74. buffer_ = reinterpret_cast<u1*>(view);
  75. opened_ = true;
  76. }
  77. MappedInputFile::~MappedInputFile() {
  78. delete impl_;
  79. }
  80. void MappedInputFile::Discard(size_t bytes) {
  81. // This is not supported on Windows for now. I'm not sure if we can unmap
  82. // parts of an existing view and that this is necessary for Windows at all.
  83. // At any rate, this only matters for >2GB (or maybe >4GB?) input files.
  84. }
  85. int MappedInputFile::Close() {
  86. if (!UnmapViewOfFile(buffer_)) {
  87. string errormsg = blaze_util::GetLastErrorString();
  88. BAZEL_DIE(255) << "MappedInputFile::Close: UnmapViewOfFile failed: "
  89. << errormsg;
  90. }
  91. if (!CloseHandle(impl_->mapping_)) {
  92. string errormsg = blaze_util::GetLastErrorString();
  93. BAZEL_DIE(255) << "MappedInputFile::Close: CloseHandle for mapping failed: "
  94. << errormsg;
  95. }
  96. if (!CloseHandle(impl_->file_)) {
  97. string errormsg = blaze_util::GetLastErrorString();
  98. BAZEL_DIE(255) << "MappedInputFile::Close: CloseHandle for file failed: "
  99. << errormsg;
  100. }
  101. return 0;
  102. }
  103. struct MappedOutputFileImpl {
  104. HANDLE file_;
  105. HANDLE mapping_;
  106. MappedOutputFileImpl(HANDLE file, HANDLE mapping) {
  107. file_ = file;
  108. mapping_ = mapping;
  109. }
  110. };
  111. MappedOutputFile::MappedOutputFile(const char* name, size_t estimated_size) {
  112. impl_ = NULL;
  113. opened_ = false;
  114. errmsg_ = errmsg;
  115. wstring wname;
  116. string error;
  117. if (!blaze_util::AsAbsoluteWindowsPath(name, &wname, &error)) {
  118. BAZEL_DIE(255) << "MappedOutputFile(" << name
  119. << "): AsAbsoluteWindowsPath failed: " << error;
  120. }
  121. HANDLE file = CreateFileW(wname.c_str(), GENERIC_READ | GENERIC_WRITE, 0,
  122. NULL, CREATE_ALWAYS, 0, NULL);
  123. if (file == INVALID_HANDLE_VALUE) {
  124. string errormsg = blaze_util::GetLastErrorString();
  125. BAZEL_DIE(255) << "MappedOutputFile(" << name << "): CreateFileW("
  126. << blaze_util::WstringToCstring(wname)
  127. << ") failed: " << errormsg;
  128. }
  129. HANDLE mapping = CreateFileMapping(file, NULL, PAGE_READWRITE,
  130. estimated_size >> 32, estimated_size & 0xffffffffUL, NULL);
  131. if (mapping == NULL || mapping == INVALID_HANDLE_VALUE) {
  132. BAZEL_DIE(255) << "MappedOutputFile(" << name
  133. << "): CreateFileMapping failed";
  134. }
  135. void *view = MapViewOfFileEx(mapping, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
  136. if (view == NULL) {
  137. string errormsg = blaze_util::GetLastErrorString();
  138. BAZEL_DIE(255) << "MappedOutputFile(" << name
  139. << "): MapViewOfFileEx failed: " << errormsg;
  140. CloseHandle(mapping);
  141. CloseHandle(file);
  142. return;
  143. }
  144. impl_ = new MappedOutputFileImpl(file, mapping);
  145. buffer_ = reinterpret_cast<u1*>(view);
  146. opened_ = true;
  147. }
  148. MappedOutputFile::~MappedOutputFile() {
  149. delete impl_;
  150. }
  151. int MappedOutputFile::Close(size_t size) {
  152. if (!UnmapViewOfFile(buffer_)) {
  153. BAZEL_DIE(255) << "MappedOutputFile::Close: UnmapViewOfFile failed: "
  154. << blaze_util::GetLastErrorString();
  155. }
  156. if (!CloseHandle(impl_->mapping_)) {
  157. BAZEL_DIE(255)
  158. << "MappedOutputFile::Close: CloseHandle for mapping failed: "
  159. << blaze_util::GetLastErrorString();
  160. }
  161. if (!SetFilePointer(impl_->file_, size, NULL, FILE_BEGIN)) {
  162. BAZEL_DIE(255) << "MappedOutputFile::Close: SetFilePointer failed: "
  163. << blaze_util::GetLastErrorString();
  164. }
  165. if (!SetEndOfFile(impl_->file_)) {
  166. BAZEL_DIE(255) << "MappedOutputFile::Close: SetEndOfFile failed: "
  167. << blaze_util::GetLastErrorString();
  168. }
  169. if (!CloseHandle(impl_->file_)) {
  170. BAZEL_DIE(255) << "MappedOutputFile::Close: CloseHandle for file failed: "
  171. << blaze_util::GetLastErrorString();
  172. }
  173. return 0;
  174. }
  175. } // namespace devtools_ijar