// Copyright 2015 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "chromecast/crash/linux/dump_info.h" #include #include #include #include "base/logging.h" #include "base/values.h" namespace chromecast { namespace { const char kDumpTimeFormat[] = "%Y-%m-%d %H:%M:%S"; const unsigned kDumpTimeMaxLen = 255; const int kNumRequiredParams = 5; const char kNameKey[] = "name"; const char kDumpTimeKey[] = "dump_time"; const char kDumpKey[] = "dump"; const char kUptimeKey[] = "uptime"; const char kLogfileKey[] = "logfile"; const char kSuffixKey[] = "suffix"; const char kPrevAppNameKey[] = "prev_app_name"; const char kCurAppNameKey[] = "cur_app_name"; const char kLastAppNameKey[] = "last_app_name"; const char kReleaseVersionKey[] = "release_version"; const char kBuildNumberKey[] = "build_number"; const char kReasonKey[] = "reason"; } // namespace DumpInfo::DumpInfo(const base::Value* entry) : valid_(ParseEntry(entry)) { } DumpInfo::DumpInfo(const std::string& crashed_process_dump, const std::string& logfile, const time_t& dump_time, const MinidumpParams& params) : crashed_process_dump_(crashed_process_dump), logfile_(logfile), dump_time_(dump_time), params_(params), valid_(false) { // Validate the time passed in. struct tm* tm = gmtime(&dump_time); char buf[kDumpTimeMaxLen]; int n = strftime(buf, kDumpTimeMaxLen, kDumpTimeFormat, tm); if (n <= 0) { LOG(INFO) << "strftime failed"; return; } valid_ = true; } DumpInfo::~DumpInfo() { } scoped_ptr DumpInfo::GetAsValue() const { scoped_ptr result = make_scoped_ptr(new base::DictionaryValue()); base::DictionaryValue* entry; result->GetAsDictionary(&entry); entry->SetString(kNameKey, params_.process_name); struct tm* tm = gmtime(&dump_time_); char buf[kDumpTimeMaxLen]; int n = strftime(buf, kDumpTimeMaxLen, kDumpTimeFormat, tm); DCHECK_GT(n, 0); std::string dump_time(buf); entry->SetString(kDumpTimeKey, dump_time); entry->SetString(kDumpKey, crashed_process_dump_); std::string uptime = std::to_string(params_.process_uptime); entry->SetString(kUptimeKey, uptime); entry->SetString(kLogfileKey, logfile_); entry->SetString(kSuffixKey, params_.suffix); entry->SetString(kPrevAppNameKey, params_.previous_app_name); entry->SetString(kCurAppNameKey, params_.current_app_name); entry->SetString(kLastAppNameKey, params_.last_app_name); entry->SetString(kReleaseVersionKey, params_.cast_release_version); entry->SetString(kBuildNumberKey, params_.cast_build_number); entry->SetString(kReasonKey, params_.reason); return result; } bool DumpInfo::ParseEntry(const base::Value* entry) { valid_ = false; if (!entry) return false; const base::DictionaryValue* dict; if (!entry->GetAsDictionary(&dict)) return false; // Extract required fields. if (!dict->GetString(kNameKey, ¶ms_.process_name)) return false; std::string dump_time; if (!dict->GetString(kDumpTimeKey, &dump_time)) return false; if (!SetDumpTimeFromString(dump_time)) return false; if (!dict->GetString(kDumpKey, &crashed_process_dump_)) return false; std::string uptime; if (!dict->GetString(kUptimeKey, &uptime)) return false; errno = 0; params_.process_uptime = strtoull(uptime.c_str(), nullptr, 0); if (errno != 0) return false; if (!dict->GetString(kLogfileKey, &logfile_)) return false; size_t num_params = kNumRequiredParams; // Extract all other optional fields. if (dict->GetString(kSuffixKey, ¶ms_.suffix)) ++num_params; if (dict->GetString(kPrevAppNameKey, ¶ms_.previous_app_name)) ++num_params; if (dict->GetString(kCurAppNameKey, ¶ms_.current_app_name)) ++num_params; if (dict->GetString(kLastAppNameKey, ¶ms_.last_app_name)) ++num_params; if (dict->GetString(kReleaseVersionKey, ¶ms_.cast_release_version)) ++num_params; if (dict->GetString(kBuildNumberKey, ¶ms_.cast_build_number)) ++num_params; if (dict->GetString(kReasonKey, ¶ms_.reason)) ++num_params; // Disallow extraneous params if (dict->size() != num_params) return false; valid_ = true; return true; } bool DumpInfo::SetDumpTimeFromString(const std::string& timestr) { struct tm tm = {0}; char* text = strptime(timestr.c_str(), kDumpTimeFormat, &tm); dump_time_ = mktime(&tm); if (!text || dump_time_ < 0) { LOG(INFO) << "Failed to convert dump time invalid"; return false; } return true; } } // namespace chromecast