Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(600)

Side by Side Diff: third_party/crashpad/crashpad/util/file/file_io_win.cc

Issue 2773813002: Update Crashpad to 8e37886d418dd042c3c7bfadac99214739ee4d98 (Closed)
Patch Set: Update Crashpad to 8e37886d418dd042c3c7bfadac99214739ee4d98 Created 3 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2014 The Crashpad Authors. All rights reserved. 1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 // 2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); 3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with 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 5 // You may obtain a copy of the License at
6 // 6 //
7 // http://www.apache.org/licenses/LICENSE-2.0 7 // http://www.apache.org/licenses/LICENSE-2.0
8 // 8 //
9 // Unless required by applicable law or agreed to in writing, software 9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, 10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and 12 // See the License for the specific language governing permissions and
13 // limitations under the License. 13 // limitations under the License.
14 14
15 #include "util/file/file_io.h" 15 #include "util/file/file_io.h"
16 16
17 #include <algorithm>
18 #include <limits>
19
17 #include "base/files/file_path.h" 20 #include "base/files/file_path.h"
18 #include "base/logging.h" 21 #include "base/logging.h"
19 #include "base/numerics/safe_conversions.h"
20 #include "base/strings/utf_string_conversions.h" 22 #include "base/strings/utf_string_conversions.h"
21 23
22 namespace { 24 namespace {
23 25
24 bool IsSocketHandle(HANDLE file) { 26 bool IsSocketHandle(HANDLE file) {
25 if (GetFileType(file) == FILE_TYPE_PIPE) { 27 if (GetFileType(file) == FILE_TYPE_PIPE) {
26 // FILE_TYPE_PIPE means that it's a socket, a named pipe, or an anonymous 28 // FILE_TYPE_PIPE means that it's a socket, a named pipe, or an anonymous
27 // pipe. If we are unable to retrieve the pipe information, we know it's a 29 // pipe. If we are unable to retrieve the pipe information, we know it's a
28 // socket. 30 // socket.
29 return !GetNamedPipeInfo(file, NULL, NULL, NULL, NULL); 31 return !GetNamedPipeInfo(file, NULL, NULL, NULL, NULL);
30 } 32 }
31 return false; 33 return false;
32 } 34 }
33 35
34 } // namespace 36 } // namespace
35 37
36 namespace crashpad { 38 namespace crashpad {
37 39
38 namespace { 40 namespace {
39 41
42 // kMaxReadWriteSize needs to be limited to the range of DWORD for the calls to
43 // ::ReadFile() and ::WriteFile(), and also limited to the range of
44 // FileOperationResult to be able to adequately express the number of bytes read
45 // and written in the return values from ReadFile() and NativeWriteFile(). In a
46 // 64-bit build, the former will control, and the limit will be (2^32)-1. In a
47 // 32-bit build, the latter will control, and the limit will be (2^31)-1.
48 constexpr size_t kMaxReadWriteSize = std::min(
49 static_cast<size_t>(std::numeric_limits<DWORD>::max()),
50 static_cast<size_t>(std::numeric_limits<FileOperationResult>::max()));
51
40 FileHandle OpenFileForOutput(DWORD access, 52 FileHandle OpenFileForOutput(DWORD access,
41 const base::FilePath& path, 53 const base::FilePath& path,
42 FileWriteMode mode, 54 FileWriteMode mode,
43 FilePermissions permissions) { 55 FilePermissions permissions) {
44 DCHECK(access & GENERIC_WRITE); 56 DCHECK(access & GENERIC_WRITE);
45 DCHECK_EQ(access & ~(GENERIC_READ | GENERIC_WRITE), 0u); 57 DCHECK_EQ(access & ~(GENERIC_READ | GENERIC_WRITE), 0u);
46 58
47 DWORD disposition = 0; 59 DWORD disposition = 0;
48 switch (mode) { 60 switch (mode) {
49 case FileWriteMode::kReuseOrFail: 61 case FileWriteMode::kReuseOrFail:
(...skipping 13 matching lines...) Expand all
63 access, 75 access,
64 FILE_SHARE_READ | FILE_SHARE_WRITE, 76 FILE_SHARE_READ | FILE_SHARE_WRITE,
65 nullptr, 77 nullptr,
66 disposition, 78 disposition,
67 FILE_ATTRIBUTE_NORMAL, 79 FILE_ATTRIBUTE_NORMAL,
68 nullptr); 80 nullptr);
69 } 81 }
70 82
71 } // namespace 83 } // namespace
72 84
73 // TODO(scottmg): Handle > DWORD sized writes if necessary. 85 namespace internal {
86
87 const char kNativeReadFunctionName[] = "ReadFile";
88 const char kNativeWriteFunctionName[] = "WriteFile";
89
90 FileOperationResult NativeWriteFile(FileHandle file,
91 const void* buffer,
92 size_t size) {
93 // TODO(scottmg): This might need to handle the limit for pipes across a
94 // network in the future.
95
96 const DWORD write_size =
97 static_cast<DWORD>(std::min(size, kMaxReadWriteSize));
98
99 DWORD bytes_written;
100 if (!::WriteFile(file, buffer, write_size, &bytes_written, nullptr))
101 return -1;
102
103 CHECK_NE(bytes_written, static_cast<DWORD>(-1));
104 DCHECK_LE(static_cast<size_t>(bytes_written), write_size);
105 return bytes_written;
106 }
107
108 } // namespace internal
74 109
75 FileOperationResult ReadFile(FileHandle file, void* buffer, size_t size) { 110 FileOperationResult ReadFile(FileHandle file, void* buffer, size_t size) {
76 DCHECK(!IsSocketHandle(file)); 111 DCHECK(!IsSocketHandle(file));
77 DWORD size_dword = base::checked_cast<DWORD>(size); 112
78 DWORD total_read = 0; 113 const DWORD read_size = static_cast<DWORD>(std::min(size, kMaxReadWriteSize));
79 char* buffer_c = reinterpret_cast<char*>(buffer); 114
80 while (size_dword > 0) { 115 while (true) {
81 DWORD bytes_read; 116 DWORD bytes_read;
82 BOOL success = ::ReadFile(file, buffer_c, size_dword, &bytes_read, nullptr); 117 BOOL success = ::ReadFile(file, buffer, read_size, &bytes_read, nullptr);
83 if (!success) { 118 if (!success) {
84 if (GetLastError() == ERROR_BROKEN_PIPE) { 119 if (GetLastError() == ERROR_BROKEN_PIPE) {
85 // When reading a pipe and the write handle has been closed, ReadFile 120 // When reading a pipe and the write handle has been closed, ReadFile
86 // fails with ERROR_BROKEN_PIPE, but only once all pending data has been 121 // fails with ERROR_BROKEN_PIPE, but only once all pending data has been
87 // read. 122 // read. Treat this as EOF.
88 break; 123 return 0;
89 } else if (GetLastError() != ERROR_MORE_DATA) {
90 return -1;
91 } 124 }
92 } else if (bytes_read == 0 && GetFileType(file) != FILE_TYPE_PIPE) { 125 return -1;
126 }
127
128 CHECK_NE(bytes_read, static_cast<DWORD>(-1));
129 DCHECK_LE(bytes_read, read_size);
130 if (bytes_read != 0 || GetFileType(file) != FILE_TYPE_PIPE) {
93 // Zero bytes read for a file indicates reaching EOF. Zero bytes read from 131 // Zero bytes read for a file indicates reaching EOF. Zero bytes read from
94 // a pipe indicates only that there was a zero byte WriteFile issued on 132 // a pipe indicates only that there was a zero byte WriteFile issued on
95 // the other end, so continue reading. 133 // the other end, so continue reading.
96 break; 134 return bytes_read;
97 } 135 }
98
99 buffer_c += bytes_read;
100 size_dword -= bytes_read;
101 total_read += bytes_read;
102 } 136 }
103 return total_read;
104 }
105
106 FileOperationResult WriteFile(FileHandle file,
107 const void* buffer,
108 size_t size) {
109 // TODO(scottmg): This might need to handle the limit for pipes across a
110 // network in the future.
111 DWORD size_dword = base::checked_cast<DWORD>(size);
112 DWORD bytes_written;
113 BOOL rv = ::WriteFile(file, buffer, size_dword, &bytes_written, nullptr);
114 if (!rv)
115 return -1;
116 CHECK_EQ(bytes_written, size_dword);
117 return bytes_written;
118 } 137 }
119 138
120 FileHandle OpenFileForRead(const base::FilePath& path) { 139 FileHandle OpenFileForRead(const base::FilePath& path) {
121 return CreateFile(path.value().c_str(), 140 return CreateFile(path.value().c_str(),
122 GENERIC_READ, 141 GENERIC_READ,
123 FILE_SHARE_READ | FILE_SHARE_WRITE, 142 FILE_SHARE_READ | FILE_SHARE_WRITE,
124 nullptr, 143 nullptr,
125 OPEN_EXISTING, 144 OPEN_EXISTING,
126 0, 145 0,
127 nullptr); 146 nullptr);
(...skipping 110 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 257
239 FileOffset LoggingFileSizeByHandle(FileHandle file) { 258 FileOffset LoggingFileSizeByHandle(FileHandle file) {
240 LARGE_INTEGER file_size; 259 LARGE_INTEGER file_size;
241 if (!GetFileSizeEx(file, &file_size)) { 260 if (!GetFileSizeEx(file, &file_size)) {
242 PLOG(ERROR) << "GetFileSizeEx"; 261 PLOG(ERROR) << "GetFileSizeEx";
243 return -1; 262 return -1;
244 } 263 }
245 return file_size.QuadPart; 264 return file_size.QuadPart;
246 } 265 }
247 266
267 FileHandle StdioFileHandle(StdioStream stdio_stream) {
268 DWORD standard_handle;
269 switch (stdio_stream) {
270 case StdioStream::kStandardInput:
271 standard_handle = STD_INPUT_HANDLE;
272 break;
273 case StdioStream::kStandardOutput:
274 standard_handle = STD_OUTPUT_HANDLE;
275 break;
276 case StdioStream::kStandardError:
277 standard_handle = STD_ERROR_HANDLE;
278 break;
279 default:
280 NOTREACHED();
281 return INVALID_HANDLE_VALUE;
282 }
283
284 HANDLE handle = GetStdHandle(standard_handle);
285 PLOG_IF(ERROR, handle == INVALID_HANDLE_VALUE) << "GetStdHandle";
286 return handle;
287 }
288
248 } // namespace crashpad 289 } // namespace crashpad
OLDNEW
« no previous file with comments | « third_party/crashpad/crashpad/util/file/file_io_test.cc ('k') | third_party/crashpad/crashpad/util/file/file_reader.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698