mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-26 23:01:05 +08:00
Add crashpad_database_util and its man page.
R=rsesek@chromium.org Review URL: https://codereview.chromium.org/1022663002
This commit is contained in:
parent
4bd97bb6db
commit
6f4e6aacc8
@ -573,15 +573,15 @@ CrashReportDatabase::OperationStatus CrashReportDatabaseMac::ReportsInDirectory(
|
||||
|
||||
reports->reserve([paths count]);
|
||||
for (NSString* entry in paths) {
|
||||
base::FilePath report_path = path.Append([entry fileSystemRepresentation]);
|
||||
base::ScopedFD lock(ObtainReportLock(report_path));
|
||||
Report report;
|
||||
report.file_path = path.Append([entry fileSystemRepresentation]);
|
||||
base::ScopedFD lock(ObtainReportLock(report.file_path));
|
||||
if (!lock.is_valid())
|
||||
continue;
|
||||
|
||||
Report report;
|
||||
if (!ReadReportMetadataLocked(report_path, &report)) {
|
||||
if (!ReadReportMetadataLocked(report.file_path, &report)) {
|
||||
LOG(WARNING) << "Failed to read report metadata for "
|
||||
<< report_path.value();
|
||||
<< report.file_path.value();
|
||||
continue;
|
||||
}
|
||||
reports->push_back(report);
|
||||
|
@ -372,8 +372,10 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
EXPECT_EQ(4u, pending.size());
|
||||
ASSERT_EQ(1u, completed.size());
|
||||
|
||||
for (const auto& report : pending)
|
||||
for (const auto& report : pending) {
|
||||
EXPECT_NE(report_1_uuid, report.uuid);
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
}
|
||||
EXPECT_EQ(report_1_uuid, completed[0].uuid);
|
||||
EXPECT_EQ("report1", completed[0].id);
|
||||
EXPECT_EQ(true, completed[0].uploaded);
|
||||
@ -400,6 +402,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
EXPECT_FALSE(report.uploaded);
|
||||
EXPECT_TRUE(report.id.empty());
|
||||
}
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
}
|
||||
|
||||
// Upload a second report.
|
||||
@ -431,6 +434,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
for (const auto& report : pending) {
|
||||
EXPECT_TRUE(report.uuid == report_0_uuid ||
|
||||
report.uuid == report_3_uuid);
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
}
|
||||
|
||||
// Skip upload for one report.
|
||||
@ -459,6 +463,7 @@ TEST_F(CrashReportDatabaseTest, GetCompletedAndNotUploadedReports) {
|
||||
EXPECT_GT(report.upload_attempts, 0);
|
||||
EXPECT_GT(report.last_upload_attempt_time, 0);
|
||||
}
|
||||
EXPECT_FALSE(report.file_path.empty());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,6 +101,7 @@ Failure, with a message printed to the standard error stream.
|
||||
== See Also
|
||||
|
||||
man_link:catch_exception_tool[1],
|
||||
man_link:crashpad_database_util[1],
|
||||
man_link:generate_dump[1],
|
||||
man_link:run_with_crashpad[1]
|
||||
|
||||
|
@ -77,7 +77,7 @@ int HandlerMain(int argc, char* argv[]) {
|
||||
} options = {};
|
||||
options.handshake_fd = -1;
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"annotation", required_argument, nullptr, kOptionAnnotation},
|
||||
{"database", required_argument, nullptr, kOptionDatabase},
|
||||
{"handshake-fd", required_argument, nullptr, kOptionHandshakeFD},
|
||||
|
151
tools/crashpad_database_util.ad
Normal file
151
tools/crashpad_database_util.ad
Normal file
@ -0,0 +1,151 @@
|
||||
// Copyright 2015 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
:doctype: manpage
|
||||
|
||||
= crashpad_database_util(1)
|
||||
|
||||
== Name
|
||||
|
||||
crashpad_database_util - Operate on Crashpad crash report databases
|
||||
|
||||
== Synopsis
|
||||
|
||||
[verse]
|
||||
*crashpad_database_util* ['OPTION…']
|
||||
|
||||
== Description
|
||||
|
||||
Operates on Crashpad crash report databases. The database’s settings can be
|
||||
queried and modified, and information about crash reports stored in the
|
||||
database can be displayed.
|
||||
|
||||
When this program is requested to both show and set information in a single
|
||||
invocation, all “show” operations will be completed prior to beginning any “set”
|
||||
operation.
|
||||
|
||||
Programs that use the Crashpad client library directly will not normally use
|
||||
this tool, but may use the database through the programmatic interfaces in the
|
||||
client library. This tool exists to allow developers to manipulate a Crashpad
|
||||
database.
|
||||
|
||||
== Options
|
||||
*-d*, *--database*='PATH'::
|
||||
Use 'PATH' as the path to the Crashpad crash report database. This option is
|
||||
required. If the database does not exist, it will be created, provided that the
|
||||
parent directory of 'PATH' exists.
|
||||
|
||||
*--show-client-id*::
|
||||
Show the client ID stored in the database’s settings. The client ID is formatted
|
||||
as a UUID. The client ID is set when the database is created.
|
||||
|
||||
*--show-uploads-enabled*::
|
||||
Show the status of the uploads-enabled bit stored in the database’s settings.
|
||||
man_link:crashpad_handler[8] does not upload reports when this bit is false.
|
||||
This bit is false when a database is created, and is under an application’s
|
||||
control via the Crashpad client library interface.
|
||||
+
|
||||
See also *--set-uploads-enabled*.
|
||||
|
||||
*--show-last-upload-attempt-time*::
|
||||
Show the last-upload-attempt time stored in the database’s settings. This value
|
||||
is +0+, meaning “never,” when the database is created.
|
||||
man_link:crashpad_handler[8] consults this value before attempting an upload to
|
||||
implement its rate-limiting behavior. The database updates this value whenever
|
||||
an upload is attempted.
|
||||
+
|
||||
See also *--set-last-upload-attempt-time*.
|
||||
|
||||
*--show-pending-reports*::
|
||||
Show reports eligible for upload.
|
||||
|
||||
*--show-completed-reports*::
|
||||
Show reports not eligible for upload. A report is moved from the “pending” state
|
||||
to the “completed” state by man_link:crashpad_handler[8]. This may happen when a
|
||||
report is successfully uploaded, when a report is not uploaded because uploads
|
||||
are disabled, or when a report upload attempt fails and will not be retried.
|
||||
|
||||
*--show-all-report-info*::
|
||||
With *--show-pending-reports* or *--show-completed-reports*, show all metadata
|
||||
for each report displayed. Without this option, only report IDs will be shown.
|
||||
|
||||
*--show-report*='UUID'::
|
||||
Show a report from the database looked up by its identifier, 'UUID', which must
|
||||
be formatted in string representation per RFC 4122 §3. All metadata for each
|
||||
report found via a *--show-report* option will be shown. If 'UUID' is not found,
|
||||
the string +"not found"+ will be printed. If this program is only requested to
|
||||
show a single report and it is not found, it will treat this as a failure for
|
||||
the purposes of determining its exit status.
|
||||
|
||||
*--set-report-uploads-enabled*='BOOL'::
|
||||
Enable or disable report upload in the database’s settings. 'BOOL' is a string
|
||||
representation of a boolean value, such as +"0"+ or +"true"+.
|
||||
+
|
||||
See also *--show-uploads-enabled*.
|
||||
|
||||
*--set-last-upload-attempt-time*='TIME'::
|
||||
Set the last-upload-attempt time in the database’s settings. 'TIME' is a string
|
||||
representation of a time, which may be in 'yyyy-mm-dd hh:mm:ss' format, a
|
||||
numeric +time_t+ value, or the special string +"never"+.
|
||||
+
|
||||
See also *--show-last-upload-attempt-time*.
|
||||
|
||||
*--utc*::
|
||||
When showing times, do so in UTC as opposed to the local time zone. When setting
|
||||
times, interpret ambiguous time strings in UTC as opposed to the local time
|
||||
zone.
|
||||
|
||||
*--help*::
|
||||
Display help and exit.
|
||||
|
||||
*--version*::
|
||||
Output version information and exit.
|
||||
|
||||
== Examples
|
||||
|
||||
Shows all crash reports in a crash report database that are in the “completed”
|
||||
state.
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ *crashpad_database_util --database /tmp/crashpad_database \
|
||||
--show-completed-reports*
|
||||
23f9512b-63e1-4ead-9dcd-e2e21fbccc68
|
||||
4bfca440-039f-4bc6-bbd4-6933cef5efd4
|
||||
56caeff8-b61a-43b2-832d-9e796e6e4a50
|
||||
----
|
||||
|
||||
Disables report upload in a crash report database’s settings, and then verifies
|
||||
that the change was made.
|
||||
[subs="quotes"]
|
||||
----
|
||||
$ *crashpad_database_util --database /tmp/crashpad_database \
|
||||
--set-uploads-enabled false*
|
||||
$ *crashpad_database_util --database /tmp/crashpad_database \
|
||||
--show-uploads-enabled*
|
||||
false
|
||||
----
|
||||
|
||||
== Exit Status
|
||||
|
||||
*0*::
|
||||
Success.
|
||||
|
||||
*1*::
|
||||
Failure, with a message printed to the standard error stream.
|
||||
|
||||
== See Also
|
||||
|
||||
man_link:crashpad_handler[8]
|
||||
|
||||
include::../../doc/man_footer.ad[]
|
516
tools/crashpad_database_util.cc
Normal file
516
tools/crashpad_database_util.cc
Normal file
@ -0,0 +1,516 @@
|
||||
// Copyright 2015 The Crashpad Authors. All rights reserved.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <errno.h>
|
||||
#include <getopt.h>
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h>
|
||||
#include <time.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/basictypes.h"
|
||||
#include "base/logging.h"
|
||||
#include "base/files/file_path.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/numerics/safe_conversions.h"
|
||||
#include "client/crash_report_database.h"
|
||||
#include "client/settings.h"
|
||||
#include "tools/tool_support.h"
|
||||
#include "util/misc/uuid.h"
|
||||
|
||||
namespace crashpad {
|
||||
namespace {
|
||||
|
||||
void Usage(const std::string& me) {
|
||||
fprintf(stderr,
|
||||
"Usage: %s [OPTION]... PID\n"
|
||||
"Operate on Crashpad crash report databases.\n"
|
||||
"\n"
|
||||
" -d, --database=PATH operate on the crash report database at PATH\n"
|
||||
" --show-client-id show the client ID\n"
|
||||
" --show-uploads-enabled show whether uploads are enabled\n"
|
||||
" --show-last-upload-attempt-time\n"
|
||||
" show the last-upload-attempt time\n"
|
||||
" --show-pending-reports show reports eligible for upload\n"
|
||||
" --show-completed-reports show reports not eligible for upload\n"
|
||||
" --show-all-report-info with --show-*-reports, show more information\n"
|
||||
" --show-report=UUID show report stored under UUID\n"
|
||||
" --set-uploads-enabled=BOOL enable or disable uploads\n"
|
||||
" --set-last-upload-attempt-time=TIME\n"
|
||||
" set the last-upload-attempt time to TIME\n"
|
||||
" --utc show and set UTC times instead of local\n"
|
||||
" --help display this help and exit\n"
|
||||
" --version output version information and exit\n",
|
||||
me.c_str());
|
||||
ToolSupport::UsageTail(me);
|
||||
}
|
||||
|
||||
struct Options {
|
||||
std::vector<UUID> show_reports;
|
||||
const char* database;
|
||||
const char* set_last_upload_attempt_time_string;
|
||||
time_t set_last_upload_attempt_time;
|
||||
bool show_client_id;
|
||||
bool show_uploads_enabled;
|
||||
bool show_last_upload_attempt_time;
|
||||
bool show_pending_reports;
|
||||
bool show_completed_reports;
|
||||
bool show_all_report_info;
|
||||
bool set_uploads_enabled;
|
||||
bool has_set_uploads_enabled;
|
||||
bool utc;
|
||||
};
|
||||
|
||||
// Converts |string| to |boolean|, returning true if a conversion could be
|
||||
// performed, and false without setting |boolean| if no conversion could be
|
||||
// performed. Various string representations of a boolean are recognized
|
||||
// case-insensitively.
|
||||
bool StringToBool(const char* string, bool* boolean) {
|
||||
const char* const kFalseWords[] = {
|
||||
"0",
|
||||
"false",
|
||||
"no",
|
||||
"off",
|
||||
"disabled",
|
||||
"clear",
|
||||
};
|
||||
const char* const kTrueWords[] = {
|
||||
"1",
|
||||
"true",
|
||||
"yes",
|
||||
"on",
|
||||
"enabled",
|
||||
"set",
|
||||
};
|
||||
|
||||
for (size_t index = 0; index < arraysize(kFalseWords); ++index) {
|
||||
if (strcasecmp(string, kFalseWords[index]) == 0) {
|
||||
*boolean = false;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t index = 0; index < arraysize(kTrueWords); ++index) {
|
||||
if (strcasecmp(string, kTrueWords[index]) == 0) {
|
||||
*boolean = true;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Converts |boolean| to a string, either "true" or "false".
|
||||
std::string BoolToString(bool boolean) {
|
||||
return std::string(boolean ? "true" : "false");
|
||||
}
|
||||
|
||||
// Converts |string| to |time|, returning true if a conversion could be
|
||||
// performed, and false without setting |boolean| if no conversion could be
|
||||
// performed. Various time formats are recognized, including several string
|
||||
// representations and a numeric time_t representation. The special string
|
||||
// "never" is recognized as |string| and converts to a |time| value of 0. |utc|,
|
||||
// when true, causes |string| to be interpreted as a UTC time rather than a
|
||||
// local time when the time zone is ambiguous.
|
||||
bool StringToTime(const char* string, time_t* time, bool utc) {
|
||||
if (strcasecmp(string, "never") == 0) {
|
||||
*time = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
const char* end = string + strlen(string);
|
||||
|
||||
const char* const kFormats[] = {
|
||||
"%Y-%m-%d %H:%M:%S %Z",
|
||||
"%Y-%m-%d %H:%M:%S",
|
||||
"%+",
|
||||
};
|
||||
|
||||
for (size_t index = 0; index < arraysize(kFormats); ++index) {
|
||||
tm time_tm;
|
||||
const char* strptime_result = strptime(string, kFormats[index], &time_tm);
|
||||
if (strptime_result == end) {
|
||||
if (utc) {
|
||||
*time = timegm(&time_tm);
|
||||
} else {
|
||||
*time = timelocal(&time_tm);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
char* end_result;
|
||||
errno = 0;
|
||||
long long strtoll_result = strtoll(string, &end_result, 0);
|
||||
if (end_result == end && errno == 0 &&
|
||||
base::IsValueInRangeForNumericType<time_t>(strtoll_result)) {
|
||||
*time = strtoll_result;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Converst |time_tt| to a string, and returns it. |utc| determines whether the
|
||||
// converted time will reference local time or UTC. If |time_tt| is 0, the
|
||||
// string "never" will be returned as a special case.
|
||||
std::string TimeToString(time_t time_tt, bool utc) {
|
||||
if (time_tt == 0) {
|
||||
return std::string("never");
|
||||
}
|
||||
|
||||
tm time_tm;
|
||||
if (utc) {
|
||||
gmtime_r(&time_tt, &time_tm);
|
||||
} else {
|
||||
localtime_r(&time_tt, &time_tm);
|
||||
}
|
||||
|
||||
char string[64];
|
||||
CHECK_NE(
|
||||
strftime(string, arraysize(string), "%Y-%m-%d %H:%M:%S %Z", &time_tm),
|
||||
0u);
|
||||
|
||||
return std::string(string);
|
||||
}
|
||||
|
||||
// Shows information about a single |report|. |space_count| is the number of
|
||||
// spaces to print before each line that is printed. |utc| determines whether
|
||||
// times should be shown in UTC or the local time zone.
|
||||
void ShowReport(const CrashReportDatabase::Report& report,
|
||||
size_t space_count,
|
||||
bool utc) {
|
||||
std::string spaces(space_count, ' ');
|
||||
|
||||
printf("%sPath: %s\n", spaces.c_str(), report.file_path.value().c_str());
|
||||
if (!report.id.empty()) {
|
||||
printf("%sRemote ID: %s\n", spaces.c_str(), report.id.c_str());
|
||||
}
|
||||
printf("%sCreation time: %s\n",
|
||||
spaces.c_str(),
|
||||
TimeToString(report.creation_time, utc).c_str());
|
||||
printf("%sUploaded: %s\n",
|
||||
spaces.c_str(),
|
||||
BoolToString(report.uploaded).c_str());
|
||||
printf("%sLast upload attempt time: %s\n",
|
||||
spaces.c_str(),
|
||||
TimeToString(report.last_upload_attempt_time, utc).c_str());
|
||||
printf("%sUpload attempts: %d\n", spaces.c_str(), report.upload_attempts);
|
||||
}
|
||||
|
||||
// Shows information about a vector of |reports|. |space_count| is the number of
|
||||
// spaces to print before each line that is printed. |options| will be consulted
|
||||
// to determine whether to show expanded information
|
||||
// (options.show_all_report_info) and what time zone to use when showing
|
||||
// expanded information (options.utc).
|
||||
void ShowReports(const std::vector<CrashReportDatabase::Report>& reports,
|
||||
size_t space_count,
|
||||
const Options& options) {
|
||||
std::string spaces(space_count, ' ');
|
||||
const char* colon = options.show_all_report_info ? ":" : "";
|
||||
|
||||
for (const CrashReportDatabase::Report& report : reports) {
|
||||
printf("%s%s%s\n", spaces.c_str(), report.uuid.ToString().c_str(), colon);
|
||||
if (options.show_all_report_info) {
|
||||
ShowReport(report, space_count + 2, options.utc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int DatabaseUtilMain(int argc, char* argv[]) {
|
||||
const std::string me(basename(argv[0]));
|
||||
|
||||
enum OptionFlags {
|
||||
// “Short” (single-character) options.
|
||||
kOptionDatabase = 'd',
|
||||
|
||||
// Long options without short equivalents.
|
||||
kOptionLastChar = 255,
|
||||
kOptionShowClientID,
|
||||
kOptionShowUploadsEnabled,
|
||||
kOptionShowLastUploadAttemptTime,
|
||||
kOptionShowPendingReports,
|
||||
kOptionShowCompletedReports,
|
||||
kOptionShowAllReportInfo,
|
||||
kOptionShowReport,
|
||||
kOptionSetUploadsEnabled,
|
||||
kOptionSetLastUploadAttemptTime,
|
||||
kOptionUTC,
|
||||
|
||||
// Standard options.
|
||||
kOptionHelp = -2,
|
||||
kOptionVersion = -3,
|
||||
};
|
||||
|
||||
const option long_options[] = {
|
||||
{"database", required_argument, nullptr, kOptionDatabase},
|
||||
{"show-client-id", no_argument, nullptr, kOptionShowClientID},
|
||||
{"show-uploads-enabled", no_argument, nullptr, kOptionShowUploadsEnabled},
|
||||
{"show-last-upload-attempt-time",
|
||||
no_argument,
|
||||
nullptr,
|
||||
kOptionShowLastUploadAttemptTime},
|
||||
{"show-pending-reports", no_argument, nullptr, kOptionShowPendingReports},
|
||||
{"show-completed-reports",
|
||||
no_argument,
|
||||
nullptr,
|
||||
kOptionShowCompletedReports},
|
||||
{"show-all-report-info", no_argument, nullptr, kOptionShowAllReportInfo},
|
||||
{"show-report", required_argument, nullptr, kOptionShowReport},
|
||||
{"set-uploads-enabled",
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionSetUploadsEnabled},
|
||||
{"set-last-upload-attempt-time",
|
||||
required_argument,
|
||||
nullptr,
|
||||
kOptionSetLastUploadAttemptTime},
|
||||
{"utc", no_argument, nullptr, kOptionUTC},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
{"version", no_argument, nullptr, kOptionVersion},
|
||||
{nullptr, 0, nullptr, 0},
|
||||
};
|
||||
|
||||
Options options = {};
|
||||
|
||||
int opt;
|
||||
while ((opt = getopt_long(argc, argv, "d:", long_options, nullptr)) != -1) {
|
||||
switch (opt) {
|
||||
case kOptionDatabase: {
|
||||
options.database = optarg;
|
||||
break;
|
||||
}
|
||||
case kOptionShowClientID: {
|
||||
options.show_client_id = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowUploadsEnabled: {
|
||||
options.show_uploads_enabled = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowLastUploadAttemptTime: {
|
||||
options.show_last_upload_attempt_time = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowPendingReports: {
|
||||
options.show_pending_reports = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowCompletedReports: {
|
||||
options.show_completed_reports = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowAllReportInfo: {
|
||||
options.show_all_report_info = true;
|
||||
break;
|
||||
}
|
||||
case kOptionShowReport: {
|
||||
UUID uuid;
|
||||
if (!uuid.InitializeFromString(optarg)) {
|
||||
ToolSupport::UsageHint(me, "--show-report requires a UUID");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
options.show_reports.push_back(uuid);
|
||||
break;
|
||||
}
|
||||
case kOptionSetUploadsEnabled: {
|
||||
if (!StringToBool(optarg, &options.set_uploads_enabled)) {
|
||||
ToolSupport::UsageHint(me, "--set-uploads-enabled requires a BOOL");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
options.has_set_uploads_enabled = true;
|
||||
break;
|
||||
}
|
||||
case kOptionSetLastUploadAttemptTime: {
|
||||
options.set_last_upload_attempt_time_string = optarg;
|
||||
break;
|
||||
}
|
||||
case kOptionUTC: {
|
||||
options.utc = true;
|
||||
break;
|
||||
}
|
||||
case kOptionHelp: {
|
||||
Usage(me);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
case kOptionVersion: {
|
||||
ToolSupport::Version(me);
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
default: {
|
||||
ToolSupport::UsageHint(me, nullptr);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
if (!options.database) {
|
||||
ToolSupport::UsageHint(me, "--database is required");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
// This conversion couldn’t happen in the option-processing loop above because
|
||||
// it depends on options.utc, which may have been set after
|
||||
// options.set_last_upload_attempt_time_string.
|
||||
if (options.set_last_upload_attempt_time_string) {
|
||||
if (!StringToTime(options.set_last_upload_attempt_time_string,
|
||||
&options.set_last_upload_attempt_time,
|
||||
options.utc)) {
|
||||
ToolSupport::UsageHint(me,
|
||||
"--set-last-upload-attempt-time requires a TIME");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
const size_t show_operations = options.show_client_id +
|
||||
options.show_uploads_enabled +
|
||||
options.show_last_upload_attempt_time +
|
||||
options.show_pending_reports +
|
||||
options.show_completed_reports +
|
||||
options.show_reports.size();
|
||||
const size_t set_operations =
|
||||
options.has_set_uploads_enabled +
|
||||
(options.set_last_upload_attempt_time_string != nullptr);
|
||||
|
||||
if (show_operations + set_operations == 0) {
|
||||
ToolSupport::UsageHint(me, "nothing to do");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
scoped_ptr<CrashReportDatabase> database(
|
||||
CrashReportDatabase::Initialize(base::FilePath(options.database)));
|
||||
if (!database) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
Settings* settings = database->GetSettings();
|
||||
|
||||
// Handle the “show” options before the “set” options so that when they’re
|
||||
// specified together, the “show” option reflects the initial state.
|
||||
|
||||
if (options.show_client_id) {
|
||||
UUID client_id;
|
||||
if (!settings->GetClientID(&client_id)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char* prefix = (show_operations > 1) ? "Client ID: " : "";
|
||||
|
||||
printf("%s%s\n", prefix, client_id.ToString().c_str());
|
||||
}
|
||||
|
||||
if (options.show_uploads_enabled) {
|
||||
bool uploads_enabled;
|
||||
if (!settings->GetUploadsEnabled(&uploads_enabled)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char* prefix = (show_operations > 1) ? "Uploads enabled: " : "";
|
||||
|
||||
printf("%s%s\n", prefix, BoolToString(uploads_enabled).c_str());
|
||||
}
|
||||
|
||||
if (options.show_last_upload_attempt_time) {
|
||||
time_t last_upload_attempt_time;
|
||||
if (!settings->GetLastUploadAttemptTime(&last_upload_attempt_time)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
const char* prefix =
|
||||
(show_operations > 1) ? "Last upload attempt time: " : "";
|
||||
|
||||
printf("%s%s (%ld)\n",
|
||||
prefix,
|
||||
TimeToString(last_upload_attempt_time, options.utc).c_str(),
|
||||
implicit_cast<long>(last_upload_attempt_time));
|
||||
}
|
||||
|
||||
if (options.show_pending_reports) {
|
||||
std::vector<CrashReportDatabase::Report> pending_reports;
|
||||
if (database->GetPendingReports(&pending_reports) !=
|
||||
CrashReportDatabase::kNoError) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (show_operations > 1) {
|
||||
printf("Pending reports:\n");
|
||||
}
|
||||
|
||||
ShowReports(pending_reports, show_operations > 1 ? 2 : 0, options);
|
||||
}
|
||||
|
||||
if (options.show_completed_reports) {
|
||||
std::vector<CrashReportDatabase::Report> completed_reports;
|
||||
if (database->GetCompletedReports(&completed_reports) !=
|
||||
CrashReportDatabase::kNoError) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (show_operations > 1) {
|
||||
printf("Completed reports:\n");
|
||||
}
|
||||
|
||||
ShowReports(completed_reports, show_operations > 1 ? 2 : 0, options);
|
||||
}
|
||||
|
||||
for (const UUID& uuid : options.show_reports) {
|
||||
CrashReportDatabase::Report report;
|
||||
CrashReportDatabase::OperationStatus status =
|
||||
database->LookUpCrashReport(uuid, &report);
|
||||
if (status == CrashReportDatabase::kNoError) {
|
||||
if (show_operations > 1) {
|
||||
printf("Report %s:\n", uuid.ToString().c_str());
|
||||
}
|
||||
ShowReport(report, show_operations > 1 ? 2 : 0, options.utc);
|
||||
} else if (status == CrashReportDatabase::kReportNotFound) {
|
||||
// If only asked to do one thing, a failure to find the single requested
|
||||
// report should result in a failure exit status.
|
||||
if (show_operations + set_operations == 1) {
|
||||
fprintf(stderr, "%s: Report not found\n", me.c_str());
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
printf("Report %s not found\n", uuid.ToString().c_str());
|
||||
} else {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
if (options.has_set_uploads_enabled &&
|
||||
!settings->SetUploadsEnabled(options.set_uploads_enabled)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
if (options.set_last_upload_attempt_time_string &&
|
||||
!settings->SetLastUploadAttemptTime(
|
||||
options.set_last_upload_attempt_time)) {
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace crashpad
|
||||
|
||||
int main(int argc, char* argv[]) {
|
||||
return crashpad::DatabaseUtilMain(argc, argv);
|
||||
}
|
@ -76,7 +76,7 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
||||
Options options = {};
|
||||
options.suspend = true;
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"no-suspend", no_argument, nullptr, kOptionNoSuspend},
|
||||
{"output", required_argument, nullptr, kOptionOutput},
|
||||
{"help", no_argument, nullptr, kOptionHelp},
|
||||
|
@ -200,7 +200,7 @@ int CatchExceptionToolMain(int argc, char* argv[]) {
|
||||
|
||||
Options options = {};
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"file", required_argument, nullptr, kOptionFile},
|
||||
{"mach-service", required_argument, nullptr, kOptionMachService},
|
||||
{"persistent", no_argument, nullptr, kOptionPersistent},
|
||||
|
@ -401,7 +401,7 @@ int ExceptionPortToolMain(int argc, char* argv[]) {
|
||||
bool numeric;
|
||||
} options = {};
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"set-handler", required_argument, nullptr, kOptionSetPort},
|
||||
{"show-bootstrap", required_argument, nullptr, kOptionShowBootstrap},
|
||||
{"pid", required_argument, nullptr, kOptionPid},
|
||||
|
@ -81,7 +81,7 @@ int OnDemandServiceToolMain(int argc, char* argv[]) {
|
||||
std::vector<std::string> mach_services;
|
||||
} options = {};
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"load", no_argument, nullptr, kOptionLoadJob},
|
||||
{"unload", no_argument, nullptr, kOptionUnloadJob},
|
||||
{"label", required_argument, nullptr, kOptionJobLabel},
|
||||
|
@ -83,7 +83,7 @@ int RunWithCrashpadMain(int argc, char* argv[]) {
|
||||
kOptionVersion = -3,
|
||||
};
|
||||
|
||||
const struct option long_options[] = {
|
||||
const option long_options[] = {
|
||||
{"handler", required_argument, nullptr, kOptionHandler},
|
||||
{"annotation", required_argument, nullptr, kOptionAnnotation},
|
||||
{"database", required_argument, nullptr, kOptionDatabase},
|
||||
|
@ -59,6 +59,23 @@
|
||||
'tool_support.h',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'crashpad_database_util',
|
||||
'type': 'executable',
|
||||
'dependencies': [
|
||||
'crashpad_tool_support',
|
||||
'../client/client.gyp:crashpad_client',
|
||||
'../compat/compat.gyp:crashpad_compat',
|
||||
'../third_party/mini_chromium/mini_chromium.gyp:base',
|
||||
'../util/util.gyp:crashpad_util',
|
||||
],
|
||||
'include_dirs': [
|
||||
'..',
|
||||
],
|
||||
'sources': [
|
||||
'crashpad_database_util.cc',
|
||||
],
|
||||
},
|
||||
{
|
||||
'target_name': 'catch_exception_tool',
|
||||
'type': 'executable',
|
||||
|
Loading…
x
Reference in New Issue
Block a user