Chromium Code Reviews| 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, |
| 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 <errno.h> | 15 #include <errno.h> |
| 16 #include <getopt.h> | 16 #include <getopt.h> |
| 17 #include <libgen.h> | |
| 18 #include <stdio.h> | 17 #include <stdio.h> |
| 19 #include <stdlib.h> | 18 #include <stdlib.h> |
| 20 #include <string.h> | 19 #include <string.h> |
| 21 #include <sys/types.h> | 20 #include <sys/types.h> |
| 22 #include <time.h> | 21 #include <time.h> |
| 23 | 22 |
| 24 #include <string> | 23 #include <string> |
| 25 #include <vector> | 24 #include <vector> |
| 26 | 25 |
| 27 #include "base/basictypes.h" | 26 #include "base/basictypes.h" |
| 27 #include "base/files/file_path.h" | |
| 28 #include "base/logging.h" | 28 #include "base/logging.h" |
| 29 #include "base/files/file_path.h" | |
| 30 #include "base/memory/scoped_ptr.h" | 29 #include "base/memory/scoped_ptr.h" |
| 31 #include "base/numerics/safe_conversions.h" | 30 #include "base/numerics/safe_conversions.h" |
| 31 #include "base/strings/string_util.h" | |
| 32 #include "base/strings/utf_string_conversions.h" | |
| 33 #include "build/build_config.h" | |
| 32 #include "client/crash_report_database.h" | 34 #include "client/crash_report_database.h" |
| 33 #include "client/settings.h" | 35 #include "client/settings.h" |
| 34 #include "tools/tool_support.h" | 36 #include "tools/tool_support.h" |
| 35 #include "util/file/file_io.h" | 37 #include "util/file/file_io.h" |
| 36 #include "util/file/file_reader.h" | 38 #include "util/file/file_reader.h" |
| 37 #include "util/misc/uuid.h" | 39 #include "util/misc/uuid.h" |
| 38 | 40 |
| 41 #if defined(OS_MACOSX) | |
| 42 #include <libgen.h> | |
|
Mark Mentovai
2015/05/05 22:25:27
Remove this. It was only here for basename().
scottmg
2015/05/05 23:03:37
Done.
| |
| 43 #endif // OS_MACOSX | |
| 44 | |
| 45 #if defined(OS_POSIX) | |
| 46 base::FilePath::StringType UTF8ToFilePathStringType(const char* path) { | |
| 47 return path; | |
| 48 } | |
| 49 #elif defined(OS_WIN) | |
| 50 base::FilePath::StringType UTF8ToFilePathStringType(const char* path) { | |
| 51 return base::UTF8ToUTF16(path); | |
| 52 } | |
| 53 #endif | |
| 54 | |
| 39 namespace crashpad { | 55 namespace crashpad { |
| 40 namespace { | 56 namespace { |
| 41 | 57 |
| 42 void Usage(const std::string& me) { | 58 void Usage(const base::FilePath& me) { |
| 43 fprintf(stderr, | 59 fprintf(stderr, |
| 44 "Usage: %s [OPTION]... PID\n" | 60 "Usage: %" PRFilePath " [OPTION]... PID\n" |
| 45 "Operate on Crashpad crash report databases.\n" | 61 "Operate on Crashpad crash report databases.\n" |
| 46 "\n" | 62 "\n" |
| 47 " -d, --database=PATH operate on the crash report database at PATH\ n" | 63 " -d, --database=PATH operate on the crash report database at PATH\ n" |
| 48 " --show-client-id show the client ID\n" | 64 " --show-client-id show the client ID\n" |
| 49 " --show-uploads-enabled show whether uploads are enabled\n" | 65 " --show-uploads-enabled show whether uploads are enabled\n" |
| 50 " --show-last-upload-attempt-time\n" | 66 " --show-last-upload-attempt-time\n" |
| 51 " show the last-upload-attempt time\n" | 67 " show the last-upload-attempt time\n" |
| 52 " --show-pending-reports show reports eligible for upload\n" | 68 " --show-pending-reports show reports eligible for upload\n" |
| 53 " --show-completed-reports show reports not eligible for upload\n" | 69 " --show-completed-reports show reports not eligible for upload\n" |
| 54 " --show-all-report-info with --show-*-reports, show more information\ n" | 70 " --show-all-report-info with --show-*-reports, show more information\ n" |
| 55 " --show-report=UUID show report stored under UUID\n" | 71 " --show-report=UUID show report stored under UUID\n" |
| 56 " --set-uploads-enabled=BOOL enable or disable uploads\n" | 72 " --set-uploads-enabled=BOOL enable or disable uploads\n" |
| 57 " --set-last-upload-attempt-time=TIME\n" | 73 " --set-last-upload-attempt-time=TIME\n" |
| 58 " set the last-upload-attempt time to TIME\n" | 74 " set the last-upload-attempt time to TIME\n" |
| 59 " --new-report=PATH submit a new report at PATH\n" | 75 " --new-report=PATH submit a new report at PATH\n" |
| 60 " --utc show and set UTC times instead of local\n" | 76 " --utc show and set UTC times instead of local\n" |
| 61 " --help display this help and exit\n" | 77 " --help display this help and exit\n" |
| 62 " --version output version information and exit\n", | 78 " --version output version information and exit\n", |
| 63 me.c_str()); | 79 me.value().c_str()); |
| 64 ToolSupport::UsageTail(me); | 80 ToolSupport::UsageTail(me); |
| 65 } | 81 } |
| 66 | 82 |
| 67 struct Options { | 83 struct Options { |
| 68 std::vector<UUID> show_reports; | 84 std::vector<UUID> show_reports; |
| 69 std::vector<base::FilePath> new_report_paths; | 85 std::vector<base::FilePath> new_report_paths; |
| 70 const char* database; | 86 const char* database; |
| 71 const char* set_last_upload_attempt_time_string; | 87 const char* set_last_upload_attempt_time_string; |
| 72 time_t set_last_upload_attempt_time; | 88 time_t set_last_upload_attempt_time; |
| 73 bool show_client_id; | 89 bool show_client_id; |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 97 const char* const kTrueWords[] = { | 113 const char* const kTrueWords[] = { |
| 98 "1", | 114 "1", |
| 99 "true", | 115 "true", |
| 100 "yes", | 116 "yes", |
| 101 "on", | 117 "on", |
| 102 "enabled", | 118 "enabled", |
| 103 "set", | 119 "set", |
| 104 }; | 120 }; |
| 105 | 121 |
| 106 for (size_t index = 0; index < arraysize(kFalseWords); ++index) { | 122 for (size_t index = 0; index < arraysize(kFalseWords); ++index) { |
| 107 if (strcasecmp(string, kFalseWords[index]) == 0) { | 123 if (base::strcasecmp(string, kFalseWords[index]) == 0) { |
| 108 *boolean = false; | 124 *boolean = false; |
| 109 return true; | 125 return true; |
| 110 } | 126 } |
| 111 } | 127 } |
| 112 | 128 |
| 113 for (size_t index = 0; index < arraysize(kTrueWords); ++index) { | 129 for (size_t index = 0; index < arraysize(kTrueWords); ++index) { |
| 114 if (strcasecmp(string, kTrueWords[index]) == 0) { | 130 if (base::strcasecmp(string, kTrueWords[index]) == 0) { |
| 115 *boolean = true; | 131 *boolean = true; |
| 116 return true; | 132 return true; |
| 117 } | 133 } |
| 118 } | 134 } |
| 119 | 135 |
| 120 return false; | 136 return false; |
| 121 } | 137 } |
| 122 | 138 |
| 123 // Converts |boolean| to a string, either "true" or "false". | 139 // Converts |boolean| to a string, either "true" or "false". |
| 124 std::string BoolToString(bool boolean) { | 140 std::string BoolToString(bool boolean) { |
| 125 return std::string(boolean ? "true" : "false"); | 141 return std::string(boolean ? "true" : "false"); |
| 126 } | 142 } |
| 127 | 143 |
| 128 // Converts |string| to |time|, returning true if a conversion could be | 144 // Converts |string| to |time|, returning true if a conversion could be |
| 129 // performed, and false without setting |boolean| if no conversion could be | 145 // performed, and false without setting |boolean| if no conversion could be |
| 130 // performed. Various time formats are recognized, including several string | 146 // performed. Various time formats are recognized, including several string |
| 131 // representations and a numeric time_t representation. The special string | 147 // representations and a numeric time_t representation. The special string |
| 132 // "never" is recognized as |string| and converts to a |time| value of 0. |utc|, | 148 // "never" is recognized as |string| and converts to a |time| value of 0. |utc|, |
| 133 // when true, causes |string| to be interpreted as a UTC time rather than a | 149 // when true, causes |string| to be interpreted as a UTC time rather than a |
| 134 // local time when the time zone is ambiguous. | 150 // local time when the time zone is ambiguous. |
| 135 bool StringToTime(const char* string, time_t* time, bool utc) { | 151 bool StringToTime(const char* string, time_t* time, bool utc) { |
| 136 if (strcasecmp(string, "never") == 0) { | 152 if (base::strcasecmp(string, "never") == 0) { |
| 137 *time = 0; | 153 *time = 0; |
| 138 return true; | 154 return true; |
| 139 } | 155 } |
| 140 | 156 |
| 141 const char* end = string + strlen(string); | 157 const char* end = string + strlen(string); |
| 142 | 158 |
| 143 const char* const kFormats[] = { | 159 const char* const kFormats[] = { |
| 144 "%Y-%m-%d %H:%M:%S %Z", | 160 "%Y-%m-%d %H:%M:%S %Z", |
| 145 "%Y-%m-%d %H:%M:%S", | 161 "%Y-%m-%d %H:%M:%S", |
| 146 "%+", | 162 "%+", |
| 147 }; | 163 }; |
| 148 | 164 |
| 149 for (size_t index = 0; index < arraysize(kFormats); ++index) { | 165 for (size_t index = 0; index < arraysize(kFormats); ++index) { |
| 150 tm time_tm; | 166 tm time_tm; |
| 151 const char* strptime_result = strptime(string, kFormats[index], &time_tm); | 167 const char* strptime_result = strptime(string, kFormats[index], &time_tm); |
| 152 if (strptime_result == end) { | 168 if (strptime_result == end) { |
| 153 if (utc) { | 169 if (utc) { |
| 154 *time = timegm(&time_tm); | 170 *time = timegm(&time_tm); |
| 155 } else { | 171 } else { |
| 156 *time = timelocal(&time_tm); | 172 *time = mktime(&time_tm); |
| 157 } | 173 } |
| 158 | 174 |
| 159 return true; | 175 return true; |
| 160 } | 176 } |
| 161 } | 177 } |
| 162 | 178 |
| 163 char* end_result; | 179 char* end_result; |
| 164 errno = 0; | 180 errno = 0; |
| 165 long long strtoll_result = strtoll(string, &end_result, 0); | 181 long long strtoll_result = strtoll(string, &end_result, 0); |
| 166 if (end_result == end && errno == 0 && | 182 if (end_result == end && errno == 0 && |
| 167 base::IsValueInRangeForNumericType<time_t>(strtoll_result)) { | 183 base::IsValueInRangeForNumericType<time_t>(strtoll_result)) { |
| 168 *time = strtoll_result; | 184 *time = strtoll_result; |
| 169 return true; | 185 return true; |
| 170 } | 186 } |
| 171 | 187 |
| 172 return false; | 188 return false; |
| 173 } | 189 } |
| 174 | 190 |
| 175 // Converst |time_tt| to a string, and returns it. |utc| determines whether the | 191 // Converts |time_tt| to a string, and returns it. |utc| determines whether the |
| 176 // converted time will reference local time or UTC. If |time_tt| is 0, the | 192 // converted time will reference local time or UTC. If |time_tt| is 0, the |
| 177 // string "never" will be returned as a special case. | 193 // string "never" will be returned as a special case. |
| 178 std::string TimeToString(time_t time_tt, bool utc) { | 194 std::string TimeToString(time_t time_tt, bool utc) { |
| 179 if (time_tt == 0) { | 195 if (time_tt == 0) { |
| 180 return std::string("never"); | 196 return std::string("never"); |
| 181 } | 197 } |
| 182 | 198 |
| 183 tm time_tm; | 199 tm time_tm; |
| 184 if (utc) { | 200 if (utc) { |
| 201 #if defined(OS_POSIX) | |
| 185 gmtime_r(&time_tt, &time_tm); | 202 gmtime_r(&time_tt, &time_tm); |
| 203 #elif defined(OS_WIN) | |
| 204 gmtime_s(&time_tm, &time_tt); | |
|
Mark Mentovai
2015/05/05 22:19:49
gmtime_r() and localtime_r() can wrap gmtime_s() a
scottmg
2015/05/05 23:03:37
Done.
| |
| 205 #endif // OS_POSIX | |
| 186 } else { | 206 } else { |
| 207 #if defined(OS_POSIX) | |
| 187 localtime_r(&time_tt, &time_tm); | 208 localtime_r(&time_tt, &time_tm); |
| 209 #elif defined(OS_WIN) | |
| 210 localtime_s(&time_tm, &time_tt); | |
| 211 #endif // OS_POSIX | |
| 188 } | 212 } |
| 189 | 213 |
| 190 char string[64]; | 214 char string[64]; |
| 191 CHECK_NE( | 215 CHECK_NE( |
| 192 strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), | 216 strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm), |
| 193 0u); | 217 0u); |
| 194 | 218 |
| 195 return std::string(string); | 219 return std::string(string); |
| 196 } | 220 } |
| 197 | 221 |
| 198 // Shows information about a single |report|. |space_count| is the number of | 222 // Shows information about a single |report|. |space_count| is the number of |
| 199 // spaces to print before each line that is printed. |utc| determines whether | 223 // spaces to print before each line that is printed. |utc| determines whether |
| 200 // times should be shown in UTC or the local time zone. | 224 // times should be shown in UTC or the local time zone. |
| 201 void ShowReport(const CrashReportDatabase::Report& report, | 225 void ShowReport(const CrashReportDatabase::Report& report, |
| 202 size_t space_count, | 226 size_t space_count, |
| 203 bool utc) { | 227 bool utc) { |
| 204 std::string spaces(space_count, ' '); | 228 std::string spaces(space_count, ' '); |
| 205 | 229 |
| 206 printf("%sPath: %s\n", spaces.c_str(), report.file_path.value().c_str()); | 230 printf("%sPath: %" PRFilePath "\n", |
| 231 spaces.c_str(), | |
| 232 report.file_path.value().c_str()); | |
| 207 if (!report.id.empty()) { | 233 if (!report.id.empty()) { |
| 208 printf("%sRemote ID: %s\n", spaces.c_str(), report.id.c_str()); | 234 printf("%sRemote ID: %s\n", spaces.c_str(), report.id.c_str()); |
| 209 } | 235 } |
| 210 printf("%sCreation time: %s\n", | 236 printf("%sCreation time: %s\n", |
| 211 spaces.c_str(), | 237 spaces.c_str(), |
| 212 TimeToString(report.creation_time, utc).c_str()); | 238 TimeToString(report.creation_time, utc).c_str()); |
| 213 printf("%sUploaded: %s\n", | 239 printf("%sUploaded: %s\n", |
| 214 spaces.c_str(), | 240 spaces.c_str(), |
| 215 BoolToString(report.uploaded).c_str()); | 241 BoolToString(report.uploaded).c_str()); |
| 216 printf("%sLast upload attempt time: %s\n", | 242 printf("%sLast upload attempt time: %s\n", |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 232 | 258 |
| 233 for (const CrashReportDatabase::Report& report : reports) { | 259 for (const CrashReportDatabase::Report& report : reports) { |
| 234 printf("%s%s%s\n", spaces.c_str(), report.uuid.ToString().c_str(), colon); | 260 printf("%s%s%s\n", spaces.c_str(), report.uuid.ToString().c_str(), colon); |
| 235 if (options.show_all_report_info) { | 261 if (options.show_all_report_info) { |
| 236 ShowReport(report, space_count + 2, options.utc); | 262 ShowReport(report, space_count + 2, options.utc); |
| 237 } | 263 } |
| 238 } | 264 } |
| 239 } | 265 } |
| 240 | 266 |
| 241 int DatabaseUtilMain(int argc, char* argv[]) { | 267 int DatabaseUtilMain(int argc, char* argv[]) { |
| 242 const std::string me(basename(argv[0])); | 268 const base::FilePath me( |
| 269 base::FilePath(UTF8ToFilePathStringType(argv[0])).BaseName()); | |
| 243 | 270 |
| 244 enum OptionFlags { | 271 enum OptionFlags { |
| 245 // “Short” (single-character) options. | 272 // “Short” (single-character) options. |
| 246 kOptionDatabase = 'd', | 273 kOptionDatabase = 'd', |
| 247 | 274 |
| 248 // Long options without short equivalents. | 275 // Long options without short equivalents. |
| 249 kOptionLastChar = 255, | 276 kOptionLastChar = 255, |
| 250 kOptionShowClientID, | 277 kOptionShowClientID, |
| 251 kOptionShowUploadsEnabled, | 278 kOptionShowUploadsEnabled, |
| 252 kOptionShowLastUploadAttemptTime, | 279 kOptionShowLastUploadAttemptTime, |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 290 {"new-report", required_argument, nullptr, kOptionNewReport}, | 317 {"new-report", required_argument, nullptr, kOptionNewReport}, |
| 291 {"utc", no_argument, nullptr, kOptionUTC}, | 318 {"utc", no_argument, nullptr, kOptionUTC}, |
| 292 {"help", no_argument, nullptr, kOptionHelp}, | 319 {"help", no_argument, nullptr, kOptionHelp}, |
| 293 {"version", no_argument, nullptr, kOptionVersion}, | 320 {"version", no_argument, nullptr, kOptionVersion}, |
| 294 {nullptr, 0, nullptr, 0}, | 321 {nullptr, 0, nullptr, 0}, |
| 295 }; | 322 }; |
| 296 | 323 |
| 297 Options options = {}; | 324 Options options = {}; |
| 298 | 325 |
| 299 int opt; | 326 int opt; |
| 300 while ((opt = getopt_long(argc, argv, "d:", long_options, nullptr)) != -1) { | 327 while ((opt = getopt_long( |
|
Mark Mentovai
2015/05/05 22:19:49
This fit on one line before and you haven’t change
scottmg
2015/05/05 23:03:37
Oops, missed that in my conversions back and forth
| |
| 328 argc, argv, "d:", long_options, nullptr)) != -1) { | |
| 301 switch (opt) { | 329 switch (opt) { |
| 302 case kOptionDatabase: { | 330 case kOptionDatabase: { |
| 303 options.database = optarg; | 331 options.database = optarg; |
| 304 break; | 332 break; |
| 305 } | 333 } |
| 306 case kOptionShowClientID: { | 334 case kOptionShowClientID: { |
| 307 options.show_client_id = true; | 335 options.show_client_id = true; |
| 308 break; | 336 break; |
| 309 } | 337 } |
| 310 case kOptionShowUploadsEnabled: { | 338 case kOptionShowUploadsEnabled: { |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 342 return EXIT_FAILURE; | 370 return EXIT_FAILURE; |
| 343 } | 371 } |
| 344 options.has_set_uploads_enabled = true; | 372 options.has_set_uploads_enabled = true; |
| 345 break; | 373 break; |
| 346 } | 374 } |
| 347 case kOptionSetLastUploadAttemptTime: { | 375 case kOptionSetLastUploadAttemptTime: { |
| 348 options.set_last_upload_attempt_time_string = optarg; | 376 options.set_last_upload_attempt_time_string = optarg; |
| 349 break; | 377 break; |
| 350 } | 378 } |
| 351 case kOptionNewReport: { | 379 case kOptionNewReport: { |
| 352 options.new_report_paths.push_back(base::FilePath(optarg)); | 380 options.new_report_paths.push_back( |
| 381 base::FilePath(UTF8ToFilePathStringType(optarg))); | |
| 353 break; | 382 break; |
| 354 } | 383 } |
| 355 case kOptionUTC: { | 384 case kOptionUTC: { |
| 356 options.utc = true; | 385 options.utc = true; |
| 357 break; | 386 break; |
| 358 } | 387 } |
| 359 case kOptionHelp: { | 388 case kOptionHelp: { |
| 360 Usage(me); | 389 Usage(me); |
| 361 return EXIT_SUCCESS; | 390 return EXIT_SUCCESS; |
| 362 } | 391 } |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 401 options.new_report_paths.size(); | 430 options.new_report_paths.size(); |
| 402 const size_t set_operations = | 431 const size_t set_operations = |
| 403 options.has_set_uploads_enabled + | 432 options.has_set_uploads_enabled + |
| 404 (options.set_last_upload_attempt_time_string != nullptr); | 433 (options.set_last_upload_attempt_time_string != nullptr); |
| 405 | 434 |
| 406 if (show_operations + set_operations == 0) { | 435 if (show_operations + set_operations == 0) { |
| 407 ToolSupport::UsageHint(me, "nothing to do"); | 436 ToolSupport::UsageHint(me, "nothing to do"); |
| 408 return EXIT_FAILURE; | 437 return EXIT_FAILURE; |
| 409 } | 438 } |
| 410 | 439 |
| 411 scoped_ptr<CrashReportDatabase> database( | 440 scoped_ptr<CrashReportDatabase> database(CrashReportDatabase::Initialize( |
| 412 CrashReportDatabase::Initialize(base::FilePath(options.database))); | 441 base::FilePath(UTF8ToFilePathStringType(options.database)))); |
| 413 if (!database) { | 442 if (!database) { |
| 414 return EXIT_FAILURE; | 443 return EXIT_FAILURE; |
| 415 } | 444 } |
| 416 | 445 |
| 417 Settings* settings = database->GetSettings(); | 446 Settings* settings = database->GetSettings(); |
| 418 | 447 |
| 419 // Handle the “show” options before the “set” options so that when they’re | 448 // Handle the “show” options before the “set” options so that when they’re |
| 420 // specified together, the “show” option reflects the initial state. | 449 // specified together, the “show” option reflects the initial state. |
| 421 | 450 |
| 422 if (options.show_client_id) { | 451 if (options.show_client_id) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 446 if (!settings->GetLastUploadAttemptTime(&last_upload_attempt_time)) { | 475 if (!settings->GetLastUploadAttemptTime(&last_upload_attempt_time)) { |
| 447 return EXIT_FAILURE; | 476 return EXIT_FAILURE; |
| 448 } | 477 } |
| 449 | 478 |
| 450 const char* prefix = | 479 const char* prefix = |
| 451 (show_operations > 1) ? "Last upload attempt time: " : ""; | 480 (show_operations > 1) ? "Last upload attempt time: " : ""; |
| 452 | 481 |
| 453 printf("%s%s (%ld)\n", | 482 printf("%s%s (%ld)\n", |
| 454 prefix, | 483 prefix, |
| 455 TimeToString(last_upload_attempt_time, options.utc).c_str(), | 484 TimeToString(last_upload_attempt_time, options.utc).c_str(), |
| 456 implicit_cast<long>(last_upload_attempt_time)); | 485 static_cast<long>(last_upload_attempt_time)); |
| 457 } | 486 } |
| 458 | 487 |
| 459 if (options.show_pending_reports) { | 488 if (options.show_pending_reports) { |
| 460 std::vector<CrashReportDatabase::Report> pending_reports; | 489 std::vector<CrashReportDatabase::Report> pending_reports; |
| 461 if (database->GetPendingReports(&pending_reports) != | 490 if (database->GetPendingReports(&pending_reports) != |
| 462 CrashReportDatabase::kNoError) { | 491 CrashReportDatabase::kNoError) { |
| 463 return EXIT_FAILURE; | 492 return EXIT_FAILURE; |
| 464 } | 493 } |
| 465 | 494 |
| 466 if (show_operations > 1) { | 495 if (show_operations > 1) { |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 490 database->LookUpCrashReport(uuid, &report); | 519 database->LookUpCrashReport(uuid, &report); |
| 491 if (status == CrashReportDatabase::kNoError) { | 520 if (status == CrashReportDatabase::kNoError) { |
| 492 if (show_operations > 1) { | 521 if (show_operations > 1) { |
| 493 printf("Report %s:\n", uuid.ToString().c_str()); | 522 printf("Report %s:\n", uuid.ToString().c_str()); |
| 494 } | 523 } |
| 495 ShowReport(report, show_operations > 1 ? 2 : 0, options.utc); | 524 ShowReport(report, show_operations > 1 ? 2 : 0, options.utc); |
| 496 } else if (status == CrashReportDatabase::kReportNotFound) { | 525 } else if (status == CrashReportDatabase::kReportNotFound) { |
| 497 // If only asked to do one thing, a failure to find the single requested | 526 // If only asked to do one thing, a failure to find the single requested |
| 498 // report should result in a failure exit status. | 527 // report should result in a failure exit status. |
| 499 if (show_operations + set_operations == 1) { | 528 if (show_operations + set_operations == 1) { |
| 500 fprintf(stderr, "%s: Report not found\n", me.c_str()); | 529 fprintf( |
| 530 stderr, "%" PRFilePath ": Report not found\n", me.value().c_str()); | |
| 501 return EXIT_FAILURE; | 531 return EXIT_FAILURE; |
| 502 } | 532 } |
| 503 printf("Report %s not found\n", uuid.ToString().c_str()); | 533 printf("Report %s not found\n", uuid.ToString().c_str()); |
| 504 } else { | 534 } else { |
| 505 return EXIT_FAILURE; | 535 return EXIT_FAILURE; |
| 506 } | 536 } |
| 507 } | 537 } |
| 508 | 538 |
| 509 if (options.has_set_uploads_enabled && | 539 if (options.has_set_uploads_enabled && |
| 510 !settings->SetUploadsEnabled(options.set_uploads_enabled)) { | 540 !settings->SetUploadsEnabled(options.set_uploads_enabled)) { |
| (...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 555 const char* prefix = (show_operations > 1) ? "New report ID: " : ""; | 585 const char* prefix = (show_operations > 1) ? "New report ID: " : ""; |
| 556 printf("%s%s\n", prefix, uuid.ToString().c_str()); | 586 printf("%s%s\n", prefix, uuid.ToString().c_str()); |
| 557 } | 587 } |
| 558 | 588 |
| 559 return EXIT_SUCCESS; | 589 return EXIT_SUCCESS; |
| 560 } | 590 } |
| 561 | 591 |
| 562 } // namespace | 592 } // namespace |
| 563 } // namespace crashpad | 593 } // namespace crashpad |
| 564 | 594 |
| 595 #if defined(OS_POSIX) | |
| 565 int main(int argc, char* argv[]) { | 596 int main(int argc, char* argv[]) { |
| 566 return crashpad::DatabaseUtilMain(argc, argv); | 597 return crashpad::DatabaseUtilMain(argc, argv); |
| 567 } | 598 } |
| 599 #elif defined(OS_WIN) | |
| 600 int wmain(int argc, wchar_t* argv[]) { | |
| 601 scoped_ptr<char*[]> argv_as_utf8(new char*[argc]); | |
|
Mark Mentovai
2015/05/05 22:19:49
I imagine that we’ll want this to be in tool_suppo
scottmg
2015/05/05 23:03:37
Yeah, I did that in the generate_dump CL as it's t
| |
| 602 std::vector<std::string> storage; | |
| 603 storage.reserve(argc); | |
| 604 for (int i = 0; i < argc; ++i) { | |
| 605 storage.push_back(base::UTF16ToUTF8(argv[i])); | |
| 606 argv_as_utf8[i] = &storage[i][0]; | |
| 607 } | |
| 608 return crashpad::DatabaseUtilMain(argc, argv_as_utf8.get()); | |
| 609 } | |
| 610 #endif // OS_POSIX | |
| OLD | NEW |