mirror of
https://github.com/chromium/crashpad.git
synced 2025-03-20 18:53:47 +00:00
Remove WeakStdioFileReader and WeakStdioFileWriter
These classes were a bit of a hack, and one of the the reasons that WeakStdioFileReader was introduced, accurate detection of EOF when stdin is a terminal, will be obsolete once https://chromium-review.googlesource.com/456676/ lands. In fact, WeakStdioFileReader didn’t even work properly for this purpose on Windows. Use WeakFile{Reader,Writer} in place of these classes (there were only two use sites). Provide a StdioFileHandle() function to access the proper values to use as a FileHandle for native file I/O given each OS’ own interface. Change-Id: I35e8d49982162bb9813855f41739cc77597ea74d Reviewed-on: https://chromium-review.googlesource.com/456358 Reviewed-by: Robert Sesek <rsesek@chromium.org>
This commit is contained in:
parent
00b6442752
commit
4f90f15146
@ -560,13 +560,21 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool used_stdin = false;
|
||||||
for (const base::FilePath new_report_path : options.new_report_paths) {
|
for (const base::FilePath new_report_path : options.new_report_paths) {
|
||||||
std::unique_ptr<FileReaderInterface> file_reader;
|
std::unique_ptr<FileReaderInterface> file_reader;
|
||||||
|
|
||||||
bool is_stdin = false;
|
|
||||||
if (new_report_path.value() == FILE_PATH_LITERAL("-")) {
|
if (new_report_path.value() == FILE_PATH_LITERAL("-")) {
|
||||||
is_stdin = true;
|
if (used_stdin) {
|
||||||
file_reader.reset(new WeakStdioFileReader(stdin));
|
fprintf(stderr,
|
||||||
|
"%" PRFilePath
|
||||||
|
": Only one --new-report may be read from standard input\n",
|
||||||
|
me.value().c_str());
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
}
|
||||||
|
used_stdin = true;
|
||||||
|
file_reader.reset(new WeakFileHandleFileReader(
|
||||||
|
StdioFileHandle(StdioStream::kStandardInput)));
|
||||||
} else {
|
} else {
|
||||||
std::unique_ptr<FileReader> file_path_reader(new FileReader());
|
std::unique_ptr<FileReader> file_path_reader(new FileReader());
|
||||||
if (!file_path_reader->Open(new_report_path)) {
|
if (!file_path_reader->Open(new_report_path)) {
|
||||||
@ -607,13 +615,6 @@ int DatabaseUtilMain(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
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: " : "";
|
const char* prefix = (show_operations > 1) ? "New report ID: " : "";
|
||||||
printf("%s%s\n", prefix, uuid.ToString().c_str());
|
printf("%s%s\n", prefix, uuid.ToString().c_str());
|
||||||
}
|
}
|
||||||
|
@ -163,7 +163,8 @@ int HTTPUploadMain(int argc, char* argv[]) {
|
|||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
file_writer.reset(new WeakStdioFileWriter(stdout));
|
file_writer.reset(new WeakFileHandleFileWriter(
|
||||||
|
StdioFileHandle(StdioStream::kStandardOutput)));
|
||||||
}
|
}
|
||||||
|
|
||||||
http_multipart_builder.SetGzipEnabled(options.upload_gzip);
|
http_multipart_builder.SetGzipEnabled(options.upload_gzip);
|
||||||
|
@ -26,27 +26,6 @@
|
|||||||
#include "util/win/scoped_handle.h"
|
#include "util/win/scoped_handle.h"
|
||||||
#endif
|
#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 {
|
namespace base {
|
||||||
class FilePath;
|
class FilePath;
|
||||||
} // namespace base
|
} // namespace base
|
||||||
@ -114,6 +93,18 @@ enum class FileLocking : bool {
|
|||||||
kExclusive,
|
kExclusive,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//! \brief Determines the FileHandle that StdioFileHandle() returns.
|
||||||
|
enum class StdioStream {
|
||||||
|
//! \brief Standard input, or `stdin`.
|
||||||
|
kStandardInput,
|
||||||
|
|
||||||
|
//! \brief Standard output, or `stdout`.
|
||||||
|
kStandardOutput,
|
||||||
|
|
||||||
|
//! \brief Standard error, or `stderr`.
|
||||||
|
kStandardError,
|
||||||
|
};
|
||||||
|
|
||||||
//! \brief The name of the native read function used by ReadFile().
|
//! \brief The name of the native read function used by ReadFile().
|
||||||
//!
|
//!
|
||||||
//! This value may be useful for logging.
|
//! This value may be useful for logging.
|
||||||
@ -381,12 +372,27 @@ void CheckedCloseFile(FileHandle file);
|
|||||||
//! \brief Determines the size of a file.
|
//! \brief Determines the size of a file.
|
||||||
//!
|
//!
|
||||||
//! \param[in] file The handle to the file for which the size should be
|
//! \param[in] file The handle to the file for which the size should be
|
||||||
//! retrived.
|
//! retrieved.
|
||||||
//!
|
//!
|
||||||
//! \return The size of the file. If an error occurs when attempting to
|
//! \return The size of the file. If an error occurs when attempting to
|
||||||
//! determine its size, returns `-1` with an error logged.
|
//! determine its size, returns `-1` with an error logged.
|
||||||
FileOffset LoggingFileSizeByHandle(FileHandle file);
|
FileOffset LoggingFileSizeByHandle(FileHandle file);
|
||||||
|
|
||||||
|
//! \brief Returns a FileHandle corresponding to the requested standard I/O
|
||||||
|
//! stream.
|
||||||
|
//!
|
||||||
|
//! The returned FileHandle should not be closed on POSIX, where it is
|
||||||
|
//! important to maintain valid file descriptors occupying the slots reserved
|
||||||
|
//! for these streams. If a need to close such a stream arises on POSIX,
|
||||||
|
//! `dup2()` should instead be used to replace the existing file descriptor with
|
||||||
|
//! one opened to `/dev/null`. See CloseStdinAndStdout().
|
||||||
|
//!
|
||||||
|
//! \param[in] stdio_stream The requested standard I/O stream.
|
||||||
|
//!
|
||||||
|
//! \return A corresponding FileHandle on success. kInvalidFileHandle on error,
|
||||||
|
//! with a message logged.
|
||||||
|
FileHandle StdioFileHandle(StdioStream stdio_stream);
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
|
||||||
#endif // CRASHPAD_UTIL_FILE_FILE_IO_H_
|
#endif // CRASHPAD_UTIL_FILE_FILE_IO_H_
|
||||||
|
@ -181,4 +181,15 @@ FileOffset LoggingFileSizeByHandle(FileHandle file) {
|
|||||||
return st.st_size;
|
return st.st_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle StdioFileHandle(StdioStream stdio_stream) {
|
||||||
|
switch (stdio_stream) {
|
||||||
|
case StdioStream::kStandardInput:
|
||||||
|
return STDIN_FILENO;
|
||||||
|
case StdioStream::kStandardOutput:
|
||||||
|
return STDOUT_FILENO;
|
||||||
|
case StdioStream::kStandardError:
|
||||||
|
return STDERR_FILENO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
|
|
||||||
#include "util/file/file_io.h"
|
#include "util/file/file_io.h"
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "base/atomicops.h"
|
#include "base/atomicops.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/macros.h"
|
#include "base/macros.h"
|
||||||
@ -324,6 +326,26 @@ TEST(FileIO, FileSizeByHandle) {
|
|||||||
EXPECT_EQ(9, LoggingFileSizeByHandle(file_handle.get()));
|
EXPECT_EQ(9, LoggingFileSizeByHandle(file_handle.get()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle FileHandleForFILE(FILE* file) {
|
||||||
|
int fd = fileno(file);
|
||||||
|
#if defined(OS_POSIX)
|
||||||
|
return fd;
|
||||||
|
#elif defined(OS_WIN)
|
||||||
|
return reinterpret_cast<HANDLE>(_get_osfhandle(fd));
|
||||||
|
#else
|
||||||
|
#error Port
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(FileIO, StdioFileHandle) {
|
||||||
|
EXPECT_EQ(FileHandleForFILE(stdin),
|
||||||
|
StdioFileHandle(StdioStream::kStandardInput));
|
||||||
|
EXPECT_EQ(FileHandleForFILE(stdout),
|
||||||
|
StdioFileHandle(StdioStream::kStandardOutput));
|
||||||
|
EXPECT_EQ(FileHandleForFILE(stderr),
|
||||||
|
StdioFileHandle(StdioStream::kStandardError));
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
} // namespace test
|
} // namespace test
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -246,4 +246,26 @@ FileOffset LoggingFileSizeByHandle(FileHandle file) {
|
|||||||
return file_size.QuadPart;
|
return file_size.QuadPart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileHandle StdioFileHandle(StdioStream stdio_stream) {
|
||||||
|
DWORD standard_handle;
|
||||||
|
switch (stdio_stream) {
|
||||||
|
case StdioStream::kStandardInput:
|
||||||
|
standard_handle = STD_INPUT_HANDLE;
|
||||||
|
break;
|
||||||
|
case StdioStream::kStandardOutput:
|
||||||
|
standard_handle = STD_OUTPUT_HANDLE;
|
||||||
|
break;
|
||||||
|
case StdioStream::kStandardError:
|
||||||
|
standard_handle = STD_ERROR_HANDLE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
NOTREACHED();
|
||||||
|
return INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
HANDLE handle = GetStdHandle(standard_handle);
|
||||||
|
PLOG_IF(ERROR, handle == INVALID_HANDLE_VALUE) << "GetStdHandle";
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -113,43 +113,4 @@ FileOffset FileReader::Seek(FileOffset offset, int whence) {
|
|||||||
return weak_file_handle_file_reader_.Seek(offset, whence);
|
return weak_file_handle_file_reader_.Seek(offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakStdioFileReader::WeakStdioFileReader(FILE* file)
|
|
||||||
: file_(file) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakStdioFileReader::~WeakStdioFileReader() {
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOperationResult 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;
|
|
||||||
}
|
|
||||||
if (rv > size) {
|
|
||||||
LOG(ERROR) << "fread: expected " << size << ", observed " << rv;
|
|
||||||
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
|
} // namespace crashpad
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#ifndef CRASHPAD_UTIL_FILE_FILE_READER_H_
|
#ifndef CRASHPAD_UTIL_FILE_FILE_READER_H_
|
||||||
#define CRASHPAD_UTIL_FILE_FILE_READER_H_
|
#define CRASHPAD_UTIL_FILE_FILE_READER_H_
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
@ -142,40 +141,6 @@ class FileReader : public FileReaderInterface {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(FileReader);
|
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:
|
|
||||||
FileOperationResult 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
|
} // namespace crashpad
|
||||||
|
|
||||||
#endif // CRASHPAD_UTIL_FILE_FILE_READER_H_
|
#endif // CRASHPAD_UTIL_FILE_FILE_READER_H_
|
||||||
|
@ -192,66 +192,4 @@ FileOffset FileWriter::Seek(FileOffset offset, int whence) {
|
|||||||
return weak_file_handle_file_writer_.Seek(offset, whence);
|
return weak_file_handle_file_writer_.Seek(offset, whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
WeakStdioFileWriter::WeakStdioFileWriter(FILE* file)
|
|
||||||
: file_(file) {
|
|
||||||
}
|
|
||||||
|
|
||||||
WeakStdioFileWriter::~WeakStdioFileWriter() {
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WeakStdioFileWriter::Write(const void* data, size_t size) {
|
|
||||||
DCHECK(file_);
|
|
||||||
|
|
||||||
size_t rv = fwrite(data, 1, size, file_);
|
|
||||||
if (rv != size) {
|
|
||||||
if (ferror(file_)) {
|
|
||||||
STDIO_PLOG(ERROR) << "fwrite";
|
|
||||||
} else {
|
|
||||||
LOG(ERROR) << "fwrite: expected " << size << ", observed " << rv;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool WeakStdioFileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|
||||||
DCHECK(file_);
|
|
||||||
|
|
||||||
if (iovecs->empty()) {
|
|
||||||
LOG(ERROR) << "WriteIoVec(): no iovecs";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const WritableIoVec& iov : *iovecs) {
|
|
||||||
if (!Write(iov.iov_base, iov.iov_len)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
|
||||||
// The interface says that |iovecs| is not sacred, so scramble it to make sure
|
|
||||||
// that nobody depends on it.
|
|
||||||
memset(&(*iovecs)[0], 0xa5, sizeof((*iovecs)[0]) * iovecs->size());
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
FileOffset WeakStdioFileWriter::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
|
} // namespace crashpad
|
||||||
|
@ -167,41 +167,6 @@ class FileWriter : public FileWriterInterface {
|
|||||||
DISALLOW_COPY_AND_ASSIGN(FileWriter);
|
DISALLOW_COPY_AND_ASSIGN(FileWriter);
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief A file writer 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 write to `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 WeakStdioFileWriter for `stdout`.
|
|
||||||
class WeakStdioFileWriter : public FileWriterInterface {
|
|
||||||
public:
|
|
||||||
explicit WeakStdioFileWriter(FILE* file);
|
|
||||||
~WeakStdioFileWriter() override;
|
|
||||||
|
|
||||||
// FileWriterInterface:
|
|
||||||
bool Write(const void* data, size_t size) override;
|
|
||||||
bool WriteIoVec(std::vector<WritableIoVec>* iovecs) override;
|
|
||||||
|
|
||||||
// FileSeekerInterface:
|
|
||||||
|
|
||||||
//! \copydoc FileWriterInterface::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(WeakStdioFileWriter);
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
|
||||||
#endif // CRASHPAD_UTIL_FILE_FILE_WRITER_H_
|
#endif // CRASHPAD_UTIL_FILE_FILE_WRITER_H_
|
||||||
|
Loading…
x
Reference in New Issue
Block a user