OLD | NEW |
1 // Copyright 2015 The Crashpad Authors. All rights reserved. | 1 // Copyright 2015 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, |
(...skipping 20 matching lines...) Expand all Loading... |
31 #include "base/macros.h" | 31 #include "base/macros.h" |
32 #include "base/numerics/safe_conversions.h" | 32 #include "base/numerics/safe_conversions.h" |
33 #include "base/strings/utf_string_conversions.h" | 33 #include "base/strings/utf_string_conversions.h" |
34 #include "build/build_config.h" | 34 #include "build/build_config.h" |
35 #include "client/crash_report_database.h" | 35 #include "client/crash_report_database.h" |
36 #include "client/settings.h" | 36 #include "client/settings.h" |
37 #include "tools/tool_support.h" | 37 #include "tools/tool_support.h" |
38 #include "util/file/file_io.h" | 38 #include "util/file/file_io.h" |
39 #include "util/file/file_reader.h" | 39 #include "util/file/file_reader.h" |
40 #include "util/misc/uuid.h" | 40 #include "util/misc/uuid.h" |
| 41 #include "util/stdlib/string_number_conversion.h" |
41 | 42 |
42 namespace crashpad { | 43 namespace crashpad { |
43 namespace { | 44 namespace { |
44 | 45 |
45 void Usage(const base::FilePath& me) { | 46 void Usage(const base::FilePath& me) { |
46 fprintf(stderr, | 47 fprintf(stderr, |
47 "Usage: %" PRFilePath " [OPTION]... PID\n" | 48 "Usage: %" PRFilePath " [OPTION]... PID\n" |
48 "Operate on Crashpad crash report databases.\n" | 49 "Operate on Crashpad crash report databases.\n" |
49 "\n" | 50 "\n" |
50 " --create allow database at PATH to be created\n" | 51 " --create allow database at PATH to be created\n" |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 } | 124 } |
124 | 125 |
125 return false; | 126 return false; |
126 } | 127 } |
127 | 128 |
128 // Converts |boolean| to a string, either "true" or "false". | 129 // Converts |boolean| to a string, either "true" or "false". |
129 std::string BoolToString(bool boolean) { | 130 std::string BoolToString(bool boolean) { |
130 return std::string(boolean ? "true" : "false"); | 131 return std::string(boolean ? "true" : "false"); |
131 } | 132 } |
132 | 133 |
133 // Converts |string| to |time|, returning true if a conversion could be | 134 // Converts |string| to |out_time|, returning true if a conversion could be |
134 // performed, and false without setting |boolean| if no conversion could be | 135 // performed, and false without setting |boolean| if no conversion could be |
135 // performed. Various time formats are recognized, including several string | 136 // performed. Various time formats are recognized, including several string |
136 // representations and a numeric time_t representation. The special string | 137 // representations and a numeric time_t representation. The special |string| |
137 // "never" is recognized as |string| and converts to a |time| value of 0. |utc|, | 138 // "never" is recognized as converted to a |out_time| value of 0; "now" is |
138 // when true, causes |string| to be interpreted as a UTC time rather than a | 139 // converted to the current time. |utc|, when true, causes |string| to be |
139 // local time when the time zone is ambiguous. | 140 // interpreted as a UTC time rather than a local time when the time zone is |
140 bool StringToTime(const char* string, time_t* time, bool utc) { | 141 // ambiguous. |
| 142 bool StringToTime(const char* string, time_t* out_time, bool utc) { |
141 if (strcasecmp(string, "never") == 0) { | 143 if (strcasecmp(string, "never") == 0) { |
142 *time = 0; | 144 *out_time = 0; |
143 return true; | 145 return true; |
144 } | 146 } |
145 | 147 |
| 148 if (strcasecmp(string, "now") == 0) { |
| 149 errno = 0; |
| 150 PCHECK(time(out_time) != -1 || errno == 0); |
| 151 return true; |
| 152 } |
| 153 |
146 const char* end = string + strlen(string); | 154 const char* end = string + strlen(string); |
147 | 155 |
148 const char* const kFormats[] = { | 156 const char* const kFormats[] = { |
149 "%Y-%m-%d %H:%M:%S %Z", | 157 "%Y-%m-%d %H:%M:%S %Z", |
150 "%Y-%m-%d %H:%M:%S", | 158 "%Y-%m-%d %H:%M:%S", |
151 "%+", | 159 "%+", |
152 }; | 160 }; |
153 | 161 |
154 for (size_t index = 0; index < arraysize(kFormats); ++index) { | 162 for (size_t index = 0; index < arraysize(kFormats); ++index) { |
155 tm time_tm; | 163 tm time_tm; |
156 const char* strptime_result = strptime(string, kFormats[index], &time_tm); | 164 const char* strptime_result = strptime(string, kFormats[index], &time_tm); |
157 if (strptime_result == end) { | 165 if (strptime_result == end) { |
| 166 time_t test_out_time; |
158 if (utc) { | 167 if (utc) { |
159 *time = timegm(&time_tm); | 168 test_out_time = timegm(&time_tm); |
160 } else { | 169 } else { |
161 *time = mktime(&time_tm); | 170 test_out_time = mktime(&time_tm); |
162 } | 171 } |
163 | 172 |
164 return true; | 173 // mktime() is supposed to set errno in the event of an error, but support |
| 174 // for this is spotty, so there’s no way to distinguish between a true |
| 175 // time_t of -1 (1969-12-31 23:59:59 UTC) and an error. Assume error. |
| 176 // |
| 177 // See 10.11.5 Libc-1082.50.1/stdtime/FreeBSD/localtime.c and |
| 178 // glibc-2.24/time/mktime.c, which don’t set errno or save and restore |
| 179 // errno. Post-Android 7.1.0 Bionic is even more hopeless, setting errno |
| 180 // whenever the time conversion returns -1, even for valid input. See |
| 181 // libc/tzcode/localtime.c mktime(). Windows seems to get it right: see |
| 182 // 10.0.14393 SDK Source/ucrt/time/mktime.cpp. |
| 183 if (test_out_time != -1) { |
| 184 *out_time = test_out_time; |
| 185 return true; |
| 186 } |
165 } | 187 } |
166 } | 188 } |
167 | 189 |
168 char* end_result; | 190 int64_t int64_result; |
169 errno = 0; | 191 if (StringToNumber(string, &int64_result) && |
170 long long strtoll_result = strtoll(string, &end_result, 0); | 192 base::IsValueInRangeForNumericType<time_t>(int64_result)) { |
171 if (end_result == end && errno == 0 && | 193 *out_time = int64_result; |
172 base::IsValueInRangeForNumericType<time_t>(strtoll_result)) { | |
173 *time = strtoll_result; | |
174 return true; | 194 return true; |
175 } | 195 } |
176 | 196 |
177 return false; | 197 return false; |
178 } | 198 } |
179 | 199 |
180 // Converts |time_tt| to a string, and returns it. |utc| determines whether the | 200 // Converts |out_time| to a string, and returns it. |utc| determines whether the |
181 // converted time will reference local time or UTC. If |time_tt| is 0, the | 201 // converted time will reference local time or UTC. If |out_time| is 0, the |
182 // string "never" will be returned as a special case. | 202 // string "never" will be returned as a special case. |
183 std::string TimeToString(time_t time_tt, bool utc) { | 203 std::string TimeToString(time_t out_time, bool utc) { |
184 if (time_tt == 0) { | 204 if (out_time == 0) { |
185 return std::string("never"); | 205 return std::string("never"); |
186 } | 206 } |
187 | 207 |
188 tm time_tm; | 208 tm time_tm; |
189 if (utc) { | 209 if (utc) { |
190 gmtime_r(&time_tt, &time_tm); | 210 PCHECK(gmtime_r(&out_time, &time_tm)); |
191 } else { | 211 } else { |
192 localtime_r(&time_tt, &time_tm); | 212 PCHECK(localtime_r(&out_time, &time_tm)); |
193 } | 213 } |
194 | 214 |
195 char string[64]; | 215 char string[64]; |
196 CHECK_NE( | 216 CHECK_NE( |
197 strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), | 217 strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), |
198 0u); | 218 0u); |
199 | 219 |
200 return std::string(string); | 220 return std::string(string); |
201 } | 221 } |
202 | 222 |
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
606 | 626 |
607 #if defined(OS_POSIX) | 627 #if defined(OS_POSIX) |
608 int main(int argc, char* argv[]) { | 628 int main(int argc, char* argv[]) { |
609 return crashpad::DatabaseUtilMain(argc, argv); | 629 return crashpad::DatabaseUtilMain(argc, argv); |
610 } | 630 } |
611 #elif defined(OS_WIN) | 631 #elif defined(OS_WIN) |
612 int wmain(int argc, wchar_t* argv[]) { | 632 int wmain(int argc, wchar_t* argv[]) { |
613 return crashpad::ToolSupport::Wmain(argc, argv, crashpad::DatabaseUtilMain); | 633 return crashpad::ToolSupport::Wmain(argc, argv, crashpad::DatabaseUtilMain); |
614 } | 634 } |
615 #endif // OS_POSIX | 635 #endif // OS_POSIX |
OLD | NEW |