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

Side by Side Diff: tools/crashpad_database_util.cc

Issue 1119783005: win: get tools/crashpad_database_util mostly working (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: roll Created 5 years, 7 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 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
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698