crashpad_database_util: Accept --new-report=- to read a new report from

standard input.

R=rsesek@chromium.org

Review URL: https://codereview.chromium.org/1023943003 .
This commit is contained in:
Mark Mentovai 2015-08-07 13:57:05 -04:00
parent 29eeec3d56
commit 124ace19bd
7 changed files with 133 additions and 23 deletions

View File

@ -105,8 +105,9 @@ numeric +time_t+ value, or the special string +"never"+.
See also *--show-last-upload-attempt-time*.
*--new-report*='PATH'::
Submit a new report located at 'PATH' to the database. The new report will be in
the “pending” state. The UUID assigned to the new report will be printed. This
Submit a new report located at 'PATH' to the database. If 'PATH' is +"-"+, the
new report will be read from standard input. The new report will be in the
“pending” state. The UUID assigned to the new report will be printed. This
option may appear multiple times.
*--utc*::

View File

@ -58,7 +58,7 @@ void Usage(const base::FilePath& me) {
" --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"
" --new-report=PATH submit a new report at PATH\n"
" --new-report=PATH submit a new report at PATH, or - for stdin\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",
@ -527,9 +527,19 @@ int DatabaseUtilMain(int argc, char* argv[]) {
}
for (const base::FilePath new_report_path : options.new_report_paths) {
FileReader file_reader;
if (!file_reader.Open(new_report_path)) {
return EXIT_FAILURE;
scoped_ptr<FileReaderInterface> file_reader;
bool is_stdin = false;
if (new_report_path.value() == FILE_PATH_LITERAL("-")) {
is_stdin = true;
file_reader.reset(new WeakStdioFileReader(stdin));
} else {
scoped_ptr<FileReader> file_path_reader(new FileReader());
if (!file_path_reader->Open(new_report_path)) {
return EXIT_FAILURE;
}
file_reader = file_path_reader.Pass();
}
CrashReportDatabase::NewReport* new_report;
@ -544,14 +554,16 @@ int DatabaseUtilMain(int argc, char* argv[]) {
char buf[4096];
ssize_t read_result;
while ((read_result = file_reader.Read(buf, sizeof(buf))) > 0) {
if (!LoggingWriteFile(new_report->handle, buf, read_result)) {
do {
read_result = file_reader->Read(buf, sizeof(buf));
if (read_result < 0) {
return EXIT_FAILURE;
}
}
if (read_result < 0) {
return EXIT_FAILURE;
}
if (read_result > 0 &&
!LoggingWriteFile(new_report->handle, buf, read_result)) {
return EXIT_FAILURE;
}
} while (read_result == sizeof(buf));
call_error_writing_crash_report.Disarm();
@ -561,6 +573,13 @@ int DatabaseUtilMain(int argc, char* argv[]) {
return EXIT_FAILURE;
}
file_reader.reset();
if (is_stdin) {
if (fclose(stdin) == EOF) {
STDIO_PLOG(ERROR) << "fclose";
}
}
const char* prefix = (show_operations > 1) ? "New report ID: " : "";
printf("%s%s\n", prefix, uuid.ToString().c_str());
}

View File

@ -26,6 +26,27 @@
#include "util/win/scoped_handle.h"
#endif
//! \file
#if defined(OS_POSIX) || DOXYGEN
//! \brief A `PLOG()` macro usable for standard input/output error conditions.
//!
//! The `PLOG()` macro uses `errno` on POSIX and is appropriate to report
//! errors from standard input/output functions. On Windows, `PLOG()` uses
//! `GetLastError()`, and cannot be used to report errors from standard
//! input/output functions. This macro uses `PLOG()` when appropriate for
//! standard I/O functions, and `LOG()` otherwise.
#define STDIO_PLOG(x) PLOG(x)
#else
#define STDIO_PLOG(x) LOG(x)
#define fseeko(file, offset, whence) _fseeki64(file, offset, whence)
#define ftello(file) _ftelli64(file)
#endif
namespace base {
class FilePath;
} // namespace base

View File

@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/numerics/safe_conversions.h"
#include "build/build_config.h"
namespace crashpad {
@ -97,4 +98,39 @@ FileOffset FileReader::Seek(FileOffset offset, int whence) {
return weak_file_handle_file_reader_.Seek(offset, whence);
}
WeakStdioFileReader::WeakStdioFileReader(FILE* file)
: file_(file) {
}
WeakStdioFileReader::~WeakStdioFileReader() {
}
ssize_t WeakStdioFileReader::Read(void* data, size_t size) {
DCHECK(file_);
size_t rv = fread(data, 1, size, file_);
if (rv < size && ferror(file_)) {
STDIO_PLOG(ERROR) << "fread";
return -1;
}
return rv;
}
FileOffset WeakStdioFileReader::Seek(FileOffset offset, int whence) {
DCHECK(file_);
if (fseeko(file_, offset, whence) == -1) {
STDIO_PLOG(ERROR) << "fseeko";
return -1;
}
FileOffset new_offset = ftello(file_);
if (new_offset == -1) {
STDIO_PLOG(ERROR) << "ftello";
return -1;
}
return new_offset;
}
} // namespace crashpad

View File

@ -15,6 +15,7 @@
#ifndef CRASHPAD_UTIL_FILE_FILE_READER_H_
#define CRASHPAD_UTIL_FILE_FILE_READER_H_
#include <stdio.h>
#include <sys/types.h>
#include "base/basictypes.h"
@ -28,6 +29,8 @@ namespace crashpad {
//! semantics matching the underlying platform (POSIX or Windows).
class FileReaderInterface : public virtual FileSeekerInterface {
public:
virtual ~FileReaderInterface() {}
//! \brief Wraps ReadFile(), or provides an implementation with identical
//! semantics.
//!
@ -44,9 +47,6 @@ class FileReaderInterface : public virtual FileSeekerInterface {
//! \return `true` if the operation succeeded, `false` if it failed, with an
//! error message logged. Short reads are treated as failures.
bool ReadExactly(void* data, size_t size);
protected:
~FileReaderInterface() {}
};
//! \brief A file reader backed by a FileHandle.
@ -66,7 +66,7 @@ class FileReaderInterface : public virtual FileSeekerInterface {
class WeakFileHandleFileReader : public FileReaderInterface {
public:
explicit WeakFileHandleFileReader(FileHandle file_handle);
~WeakFileHandleFileReader();
~WeakFileHandleFileReader() override;
// FileReaderInterface:
ssize_t Read(void* data, size_t size) override;
@ -99,7 +99,7 @@ class WeakFileHandleFileReader : public FileReaderInterface {
class FileReader : public FileReaderInterface {
public:
FileReader();
~FileReader();
~FileReader() override;
// FileReaderInterface:
@ -142,6 +142,40 @@ class FileReader : public FileReaderInterface {
DISALLOW_COPY_AND_ASSIGN(FileReader);
};
//! \brief A file reader backed by a standard input/output `FILE*`.
//!
//! This class accepts an already-open `FILE*`. It is not responsible for
//! opening or closing this `FILE*`. Users of this class must ensure that the
//! `FILE*` is closed appropriately elsewhere. Objects of this class may be used
//! to read from `FILE*` objects not associated with filesystem-based files,
//! although special attention should be paid to the Seek() method, which may
//! not function on `FILE*` objects that do not refer to disk-based files.
//!
//! This class is expected to be used when other code is responsible for
//! opening `FILE*` objects and already provides `FILE*` objects. A good use
//! would be a WeakStdioFileReader for `stdin`.
class WeakStdioFileReader : public FileReaderInterface {
public:
explicit WeakStdioFileReader(FILE* file);
~WeakStdioFileReader() override;
// FileReaderInterface:
ssize_t Read(void* data, size_t size) override;
// FileSeekerInterface:
//! \copydoc FileReaderInterface::Seek()
//!
//! \note This method is only guaranteed to function on `FILE*` objects
//! referring to disk-based files.
FileOffset Seek(FileOffset offset, int whence) override;
private:
FILE* file_; // weak
DISALLOW_COPY_AND_ASSIGN(WeakStdioFileReader);
};
} // namespace crashpad
#endif // CRASHPAD_UTIL_FILE_FILE_READER_H_

View File

@ -44,6 +44,8 @@ struct WritableIoVec {
//! semantics matching the underlying platform (POSIX or Windows).
class FileWriterInterface : public virtual FileSeekerInterface {
public:
virtual ~FileWriterInterface() {}
//! \brief Wraps LoggingWriteFile(), or provides an implementation with
//! identical semantics.
//!
@ -61,9 +63,6 @@ class FileWriterInterface : public virtual FileSeekerInterface {
//!
//! \note The contents of \a iovecs are undefined when this method returns.
virtual bool WriteIoVec(std::vector<WritableIoVec>* iovecs) = 0;
protected:
~FileWriterInterface() {}
};
//! \brief A file writer backed by a FileHandle.
@ -83,7 +82,7 @@ class FileWriterInterface : public virtual FileSeekerInterface {
class WeakFileHandleFileWriter : public FileWriterInterface {
public:
explicit WeakFileHandleFileWriter(FileHandle file_handle);
~WeakFileHandleFileWriter();
~WeakFileHandleFileWriter() override;
// FileWriterInterface:
bool Write(const void* data, size_t size) override;
@ -117,7 +116,7 @@ class WeakFileHandleFileWriter : public FileWriterInterface {
class FileWriter : public FileWriterInterface {
public:
FileWriter();
~FileWriter();
~FileWriter() override;
// FileWriterInterface:

View File

@ -36,7 +36,7 @@ namespace crashpad {
class StringFile : public FileReaderInterface, public FileWriterInterface {
public:
StringFile();
~StringFile();
~StringFile() override;
//! \brief Returns a string containing the virtual files contents.
const std::string& string() const { return string_; }