123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- // Copyright 2014 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 "components/feedback/feedback_util.h"
- #include <string>
- #include "base/bind.h"
- #include "base/files/file_util.h"
- #include "base/files/scoped_temp_dir.h"
- #include "base/logging.h"
- #include "base/strings/string_util.h"
- #include "build/build_config.h"
- #include "components/feedback/feedback_report.h"
- #include "third_party/zlib/google/zip.h"
- namespace {
- constexpr char kMultilineIndicatorString[] = "<multiline>\n";
- constexpr char kMultilineStartString[] = "---------- START ----------\n";
- constexpr char kMultilineEndString[] = "---------- END ----------\n\n";
- } // namespace
- namespace feedback_util {
- bool ZipString(const base::FilePath& filename,
- const std::string& data,
- std::string* compressed_logs) {
- base::ScopedTempDir temp_dir;
- base::FilePath zip_file;
- // Create a temporary directory, put the logs into a file in it. Create
- // another temporary file to receive the zip file in.
- if (!temp_dir.CreateUniqueTempDir())
- return false;
- if (base::WriteFile(temp_dir.GetPath().Append(filename), data.c_str(),
- data.size()) == -1) {
- return false;
- }
- bool succeed = base::CreateTemporaryFile(&zip_file) &&
- zip::Zip(temp_dir.GetPath(), zip_file, false) &&
- base::ReadFileToString(zip_file, compressed_logs);
- base::DeleteFile(zip_file);
- return succeed;
- }
- std::string LogsToString(const FeedbackCommon::SystemLogsMap& sys_info) {
- std::string syslogs_string;
- for (const auto& iter : sys_info) {
- std::string key = iter.first;
- base::TrimString(key, "\n ", &key);
- if (key == feedback::FeedbackReport::kCrashReportIdsKey ||
- key == feedback::FeedbackReport::kAllCrashReportIdsKey) {
- // Avoid adding the crash IDs to the system_logs.txt file for privacy
- // reasons. They should just be part of the product specific data.
- continue;
- }
- std::string value = iter.second;
- base::TrimString(value, "\n ", &value);
- if (value.find("\n") != std::string::npos) {
- syslogs_string.append(key + "=" + kMultilineIndicatorString +
- kMultilineStartString + value + "\n" +
- kMultilineEndString);
- } else {
- syslogs_string.append(key + "=" + value + "\n");
- }
- }
- return syslogs_string;
- }
- // Note: This function is excluded from win build because its unit tests do
- // not pass on OS_WIN.
- // This function is only called on ChromeOS and Lacros build.
- // See https://crbug.com/1119560.
- #if !BUILDFLAG(IS_WIN)
- bool ReadEndOfFile(const base::FilePath& path,
- size_t max_size,
- std::string* contents) {
- if (!contents) {
- LOG(ERROR) << "contents buffer is null.";
- return false;
- }
- if (path.ReferencesParent()) {
- LOG(ERROR) << "ReadEndOfFile can't be called on file paths with parent "
- "references.";
- return false;
- }
- base::ScopedFILE fp(base::OpenFile(path, "r"));
- if (!fp) {
- PLOG(ERROR) << "Failed to open file " << path.value();
- return false;
- }
- std::unique_ptr<char[]> chunk(new char[max_size]);
- std::unique_ptr<char[]> last_chunk(new char[max_size]);
- chunk[0] = '\0';
- last_chunk[0] = '\0';
- size_t total_bytes_read = 0;
- size_t bytes_read = 0;
- // Since most logs are not seekable, read until the end keeping tracking of
- // last two chunks.
- while ((bytes_read = fread(chunk.get(), 1, max_size, fp.get())) == max_size) {
- total_bytes_read += bytes_read;
- last_chunk.swap(chunk);
- chunk[0] = '\0';
- }
- total_bytes_read += bytes_read;
- if (total_bytes_read < max_size) {
- // File is smaller than max_size
- contents->assign(chunk.get(), bytes_read);
- } else if (bytes_read == 0) {
- // File is exactly max_size or a multiple of max_size
- contents->assign(last_chunk.get(), max_size);
- } else {
- // Number of bytes to keep from last_chunk
- size_t bytes_from_last = max_size - bytes_read;
- // Shift left last_chunk by size of chunk and fit it in the back of
- // last_chunk.
- memmove(last_chunk.get(), last_chunk.get() + bytes_read, bytes_from_last);
- memcpy(last_chunk.get() + bytes_from_last, chunk.get(), bytes_read);
- contents->assign(last_chunk.get(), max_size);
- }
- return true;
- }
- #endif // !BUILDFLAG(IS_WIN)
- } // namespace feedback_util
|