mirror of
https://github.com/chromium/crashpad.git
synced 2024-12-27 07:14:10 +08:00
Switch [String]FileWriter to use new file_io.h functions/types
Also add ScopedFileHandle as cross-platform version of ScopedFD/ScopedFileHANDLE. R=mark@chromium.org BUG=crashpad:1 Review URL: https://codereview.chromium.org/815053004
This commit is contained in:
parent
25c3afaac5
commit
5f5e342584
@ -152,8 +152,8 @@ int GenerateDumpMain(int argc, char* argv[]) {
|
|||||||
|
|
||||||
FileWriter file_writer;
|
FileWriter file_writer;
|
||||||
if (!file_writer.Open(base::FilePath(options.dump_path),
|
if (!file_writer.Open(base::FilePath(options.dump_path),
|
||||||
O_WRONLY | O_CREAT | O_TRUNC,
|
FileWriteMode::kTruncateOrCreate,
|
||||||
0644)) {
|
true)) {
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,8 +19,11 @@
|
|||||||
|
|
||||||
#include "build/build_config.h"
|
#include "build/build_config.h"
|
||||||
|
|
||||||
#if defined(OS_WIN)
|
#if defined(OS_POSIX)
|
||||||
|
#include "base/files/scoped_file.h"
|
||||||
|
#elif defined(OS_WIN)
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include "util/win/scoped_handle.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace base {
|
namespace base {
|
||||||
@ -37,10 +40,14 @@ using FileHandle = int;
|
|||||||
//! \brief Platform-specific alias for a position in an open file.
|
//! \brief Platform-specific alias for a position in an open file.
|
||||||
using FileOffset = off_t;
|
using FileOffset = off_t;
|
||||||
|
|
||||||
|
//! \brief Scoped wrapper of a FileHandle.
|
||||||
|
using ScopedFileHandle = base::ScopedFD;
|
||||||
|
|
||||||
#elif defined(OS_WIN)
|
#elif defined(OS_WIN)
|
||||||
|
|
||||||
using FileHandle = HANDLE;
|
using FileHandle = HANDLE;
|
||||||
using FileOffset = LONGLONG;
|
using FileOffset = LONGLONG;
|
||||||
|
using ScopedFileHandle = ScopedFileHANDLE;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -152,8 +159,7 @@ void CheckedReadFileAtEOF(FileHandle file);
|
|||||||
//!
|
//!
|
||||||
//! \return The newly opened FileHandle, or an invalid FileHandle on failure.
|
//! \return The newly opened FileHandle, or an invalid FileHandle on failure.
|
||||||
//!
|
//!
|
||||||
//! \sa ScopedFD
|
//! \sa ScopedFileHandle
|
||||||
//! \sa ScopedFileHANDLE
|
|
||||||
FileHandle LoggingOpenFileForRead(const base::FilePath& path);
|
FileHandle LoggingOpenFileForRead(const base::FilePath& path);
|
||||||
|
|
||||||
//! \brief Wraps `open()` or `CreateFile()`, creating a file for output. Logs
|
//! \brief Wraps `open()` or `CreateFile()`, creating a file for output. Logs
|
||||||
@ -168,8 +174,7 @@ FileHandle LoggingOpenFileForRead(const base::FilePath& path);
|
|||||||
//! \return The newly opened FileHandle, or an invalid FileHandle on failure.
|
//! \return The newly opened FileHandle, or an invalid FileHandle on failure.
|
||||||
//!
|
//!
|
||||||
//! \sa FileWriteMode
|
//! \sa FileWriteMode
|
||||||
//! \sa ScopedFD
|
//! \sa ScopedFileHandle
|
||||||
//! \sa ScopedFileHANDLE
|
|
||||||
FileHandle LoggingOpenFileForWrite(const base::FilePath& path,
|
FileHandle LoggingOpenFileForWrite(const base::FilePath& path,
|
||||||
FileWriteMode write_mode,
|
FileWriteMode write_mode,
|
||||||
bool world_readable);
|
bool world_readable);
|
||||||
|
@ -19,49 +19,49 @@
|
|||||||
#include <limits.h>
|
#include <limits.h>
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
|
||||||
|
#if defined(OS_POSIX)
|
||||||
|
#include <sys/uio.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include "base/posix/eintr_wrapper.h"
|
#include "base/posix/eintr_wrapper.h"
|
||||||
#include "util/file/file_io.h"
|
#endif // OS_POSIX
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
|
#if defined(OS_POSIX)
|
||||||
// Ensure type compatibility between WritableIoVec and iovec.
|
// Ensure type compatibility between WritableIoVec and iovec.
|
||||||
static_assert(sizeof(WritableIoVec) == sizeof(iovec), "WritableIoVec size");
|
static_assert(sizeof(WritableIoVec) == sizeof(iovec), "WritableIoVec size");
|
||||||
static_assert(offsetof(WritableIoVec, iov_base) == offsetof(iovec, iov_base),
|
static_assert(offsetof(WritableIoVec, iov_base) == offsetof(iovec, iov_base),
|
||||||
"WritableIoVec base offset");
|
"WritableIoVec base offset");
|
||||||
static_assert(offsetof(WritableIoVec, iov_len) == offsetof(iovec, iov_len),
|
static_assert(offsetof(WritableIoVec, iov_len) == offsetof(iovec, iov_len),
|
||||||
"WritableIoVec len offset");
|
"WritableIoVec len offset");
|
||||||
|
#endif // OS_POSIX
|
||||||
|
|
||||||
FileWriter::FileWriter() : fd_() {
|
FileWriter::FileWriter() : file_() {
|
||||||
}
|
}
|
||||||
|
|
||||||
FileWriter::~FileWriter() {
|
FileWriter::~FileWriter() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileWriter::Open(const base::FilePath& path, int oflag, mode_t mode) {
|
bool FileWriter::Open(const base::FilePath& path,
|
||||||
CHECK(!fd_.is_valid());
|
FileWriteMode write_mode,
|
||||||
|
bool world_readable) {
|
||||||
DCHECK((oflag & O_WRONLY) || (oflag & O_RDWR));
|
CHECK(!file_.is_valid());
|
||||||
|
file_.reset(LoggingOpenFileForWrite(path, write_mode, world_readable));
|
||||||
fd_.reset(HANDLE_EINTR(open(path.value().c_str(), oflag, mode)));
|
return file_.is_valid();
|
||||||
if (!fd_.is_valid()) {
|
|
||||||
PLOG(ERROR) << "open " << path.value();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void FileWriter::Close() {
|
void FileWriter::Close() {
|
||||||
CHECK(fd_.is_valid());
|
CHECK(file_.is_valid());
|
||||||
|
|
||||||
fd_.reset();
|
file_.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FileWriter::Write(const void* data, size_t size) {
|
bool FileWriter::Write(const void* data, size_t size) {
|
||||||
DCHECK(fd_.is_valid());
|
DCHECK(file_.is_valid());
|
||||||
|
|
||||||
// TODO(mark): Write no more than SSIZE_MAX bytes in a single call.
|
// TODO(mark): Write no more than SSIZE_MAX bytes in a single call.
|
||||||
ssize_t written = WriteFile(fd_.get(), data, size);
|
ssize_t written = WriteFile(file_.get(), data, size);
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
PLOG(ERROR) << "write";
|
PLOG(ERROR) << "write";
|
||||||
return false;
|
return false;
|
||||||
@ -74,7 +74,9 @@ bool FileWriter::Write(const void* data, size_t size) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool FileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
bool FileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
||||||
DCHECK(fd_.is_valid());
|
DCHECK(file_.is_valid());
|
||||||
|
|
||||||
|
#if defined(OS_POSIX)
|
||||||
|
|
||||||
ssize_t size = 0;
|
ssize_t size = 0;
|
||||||
for (const WritableIoVec& iov : *iovecs) {
|
for (const WritableIoVec& iov : *iovecs) {
|
||||||
@ -94,7 +96,8 @@ bool FileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|||||||
while (size > 0) {
|
while (size > 0) {
|
||||||
size_t writev_iovec_count =
|
size_t writev_iovec_count =
|
||||||
std::min(remaining_iovecs, implicit_cast<size_t>(IOV_MAX));
|
std::min(remaining_iovecs, implicit_cast<size_t>(IOV_MAX));
|
||||||
ssize_t written = HANDLE_EINTR(writev(fd_.get(), iov, writev_iovec_count));
|
ssize_t written =
|
||||||
|
HANDLE_EINTR(writev(file_.get(), iov, writev_iovec_count));
|
||||||
if (written < 0) {
|
if (written < 0) {
|
||||||
PLOG(ERROR) << "writev";
|
PLOG(ERROR) << "writev";
|
||||||
return false;
|
return false;
|
||||||
@ -128,6 +131,15 @@ bool FileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|||||||
|
|
||||||
DCHECK_EQ(remaining_iovecs, 0u);
|
DCHECK_EQ(remaining_iovecs, 0u);
|
||||||
|
|
||||||
|
#else // !OS_POSIX
|
||||||
|
|
||||||
|
for (const WritableIoVec& iov : *iovecs) {
|
||||||
|
if (!Write(iov.iov_base, iov.iov_len))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // OS_POSIX
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// The interface says that |iovecs| is not sacred, so scramble it to make sure
|
// The interface says that |iovecs| is not sacred, so scramble it to make sure
|
||||||
// that nobody depends on it.
|
// that nobody depends on it.
|
||||||
@ -137,15 +149,9 @@ bool FileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t FileWriter::Seek(off_t offset, int whence) {
|
FileOffset FileWriter::Seek(FileOffset offset, int whence) {
|
||||||
DCHECK(fd_.is_valid());
|
DCHECK(file_.is_valid());
|
||||||
|
return LoggingSeekFile(file_.get(), offset, whence);
|
||||||
off_t rv = lseek(fd_.get(), offset, whence);
|
|
||||||
if (rv < 0) {
|
|
||||||
PLOG(ERROR) << "lseek";
|
|
||||||
}
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace crashpad
|
} // namespace crashpad
|
||||||
|
@ -17,15 +17,14 @@
|
|||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/uio.h>
|
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "base/basictypes.h"
|
#include "base/basictypes.h"
|
||||||
#include "base/files/file_path.h"
|
#include "base/files/file_path.h"
|
||||||
#include "base/files/scoped_file.h"
|
#include "build/build_config.h"
|
||||||
|
#include "util/file/file_io.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
|
|
||||||
@ -43,21 +42,21 @@ struct WritableIoVec {
|
|||||||
size_t iov_len;
|
size_t iov_len;
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief An interface to write to files and other file-like objects with POSIX
|
//! \brief An interface to write to files and other file-like objects with
|
||||||
//! semantics.
|
//! semantics matching the underlying platform (POSIX or Windows).
|
||||||
class FileWriterInterface {
|
class FileWriterInterface {
|
||||||
public:
|
public:
|
||||||
//! \brief Wraps `write()` or provides an alternate implementation with
|
//! \brief Wraps WriteFile(), or provides an implementation with identical
|
||||||
//! identical semantics. This method will write the entire buffer,
|
//! semantics.
|
||||||
//! continuing after a short write or after being interrupted.
|
|
||||||
//!
|
//!
|
||||||
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
||||||
//! error message logged.
|
//! error message logged.
|
||||||
virtual bool Write(const void* data, size_t size) = 0;
|
virtual bool Write(const void* data, size_t size) = 0;
|
||||||
|
|
||||||
//! \brief Wraps `writev()` or provides an alternate implementation with
|
//! \brief Wraps `writev()` on POSIX or provides an alternate implementation
|
||||||
//! identical semantics. This method will write the entire buffer,
|
//! with identical semantics. This method will write entire buffers,
|
||||||
//! continuing after a short write or after being interrupted.
|
//! continuing after a short write or after being interrupted. On
|
||||||
|
//! non-POSIX this is a simple wrapper around Write().
|
||||||
//!
|
//!
|
||||||
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
||||||
//! error message logged.
|
//! error message logged.
|
||||||
@ -65,34 +64,36 @@ class FileWriterInterface {
|
|||||||
//! \note The contents of \a iovecs are undefined when this method returns.
|
//! \note The contents of \a iovecs are undefined when this method returns.
|
||||||
virtual bool WriteIoVec(std::vector<WritableIoVec>* iovecs) = 0;
|
virtual bool WriteIoVec(std::vector<WritableIoVec>* iovecs) = 0;
|
||||||
|
|
||||||
//! \brief Wraps `lseek()` or provides an alternate implementation with
|
//! \brief Wraps LoggingFileSeek() or provides an alternate implementation
|
||||||
//! identical semantics.
|
//! with identical semantics.
|
||||||
//!
|
//!
|
||||||
//! \return The return value of `lseek()`. `-1` on failure, with an error
|
//! \return The return value of LoggingFileSeek(). `-1` on failure,
|
||||||
//! message logged.
|
//! with an error message logged.
|
||||||
virtual off_t Seek(off_t offset, int whence) = 0;
|
virtual FileOffset Seek(FileOffset offset, int whence) = 0;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
~FileWriterInterface() {}
|
~FileWriterInterface() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
//! \brief A file writer implementation that wraps traditional POSIX file
|
//! \brief A file writer implementation that wraps traditional system file
|
||||||
//! operations on files accessed through the filesystem.
|
//! operations on files accessed through the filesystem.
|
||||||
class FileWriter : public FileWriterInterface {
|
class FileWriter : public FileWriterInterface {
|
||||||
public:
|
public:
|
||||||
FileWriter();
|
FileWriter();
|
||||||
~FileWriter();
|
~FileWriter();
|
||||||
|
|
||||||
//! \brief Wraps `open()`.
|
//! \brief Wraps LoggingOpenFileForWrite().
|
||||||
//!
|
//!
|
||||||
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
//! \return `true` if the operation succeeded, `false` if it failed, with an
|
||||||
//! error message logged.
|
//! error message logged.
|
||||||
//!
|
//!
|
||||||
//! \note After a successful call, this method cannot be called again until
|
//! \note After a successful call, this method cannot be called again until
|
||||||
//! after Close().
|
//! after Close().
|
||||||
bool Open(const base::FilePath& path, int oflag, mode_t mode);
|
bool Open(const base::FilePath& path,
|
||||||
|
FileWriteMode write_mode,
|
||||||
|
bool world_readable);
|
||||||
|
|
||||||
//! \brief Wraps `close().`
|
//! \brief Wraps CheckedCloseHandle().
|
||||||
//!
|
//!
|
||||||
//! \note It is only valid to call this method on an object that has had a
|
//! \note It is only valid to call this method on an object that has had a
|
||||||
//! successful Open() that has not yet been matched by a subsequent call
|
//! successful Open() that has not yet been matched by a subsequent call
|
||||||
@ -117,10 +118,10 @@ class FileWriter : public FileWriterInterface {
|
|||||||
//!
|
//!
|
||||||
//! \note It is only valid to call this method between a successful Open() and
|
//! \note It is only valid to call this method between a successful Open() and
|
||||||
//! a Close().
|
//! a Close().
|
||||||
off_t Seek(off_t offset, int whence) override;
|
FileOffset Seek(FileOffset offset, int whence) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
base::ScopedFD fd_;
|
ScopedFileHandle file_;
|
||||||
|
|
||||||
DISALLOW_COPY_AND_ASSIGN(FileWriter);
|
DISALLOW_COPY_AND_ASSIGN(FileWriter);
|
||||||
};
|
};
|
||||||
|
@ -87,7 +87,7 @@ bool StringFileWriter::WriteIoVec(std::vector<WritableIoVec>* iovecs) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t StringFileWriter::Seek(off_t offset, int whence) {
|
FileOffset StringFileWriter::Seek(FileOffset offset, int whence) {
|
||||||
DCHECK(offset_.IsValid());
|
DCHECK(offset_.IsValid());
|
||||||
|
|
||||||
size_t base_offset;
|
size_t base_offset;
|
||||||
@ -110,21 +110,22 @@ off_t StringFileWriter::Seek(off_t offset, int whence) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
off_t base_offset_offt;
|
FileOffset base_offset_fileoffset;
|
||||||
if (!AssignIfInRange(&base_offset_offt, base_offset)) {
|
if (!AssignIfInRange(&base_offset_fileoffset, base_offset)) {
|
||||||
LOG(ERROR) << "Seek(): base_offset " << base_offset << " invalid for off_t";
|
LOG(ERROR) << "Seek(): base_offset " << base_offset
|
||||||
|
<< " invalid for FileOffset";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
base::CheckedNumeric<off_t> new_offset(base_offset_offt);
|
base::CheckedNumeric<FileOffset> new_offset(base_offset_fileoffset);
|
||||||
new_offset += offset;
|
new_offset += offset;
|
||||||
if (!new_offset.IsValid()) {
|
if (!new_offset.IsValid()) {
|
||||||
LOG(ERROR) << "Seek(): new_offset invalid";
|
LOG(ERROR) << "Seek(): new_offset invalid";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
off_t new_offset_offt = new_offset.ValueOrDie();
|
FileOffset new_offset_fileoffset = new_offset.ValueOrDie();
|
||||||
size_t new_offset_sizet;
|
size_t new_offset_sizet;
|
||||||
if (!AssignIfInRange(&new_offset_sizet, new_offset_offt)) {
|
if (!AssignIfInRange(&new_offset_sizet, new_offset_fileoffset)) {
|
||||||
LOG(ERROR) << "Seek(): new_offset " << new_offset_offt
|
LOG(ERROR) << "Seek(): new_offset " << new_offset_fileoffset
|
||||||
<< " invalid for size_t";
|
<< " invalid for size_t";
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -47,7 +47,7 @@ class StringFileWriter : public FileWriterInterface {
|
|||||||
// FileWriterInterface:
|
// FileWriterInterface:
|
||||||
bool Write(const void* data, size_t size) override;
|
bool Write(const void* data, size_t size) override;
|
||||||
bool WriteIoVec(std::vector<WritableIoVec>* iovecs) override;
|
bool WriteIoVec(std::vector<WritableIoVec>* iovecs) override;
|
||||||
off_t Seek(off_t offset, int whence) override;
|
FileOffset Seek(FileOffset offset, int whence) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
//! \brief The virtual file’s contents.
|
//! \brief The virtual file’s contents.
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
#include "util/win/scoped_handle.h"
|
#include "util/win/scoped_handle.h"
|
||||||
|
|
||||||
#include "base/logging.h"
|
#include "base/logging.h"
|
||||||
|
#include "util/file/file_io.h"
|
||||||
|
|
||||||
namespace crashpad {
|
namespace crashpad {
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
void ScopedFileHANDLECloseTraits::Free(HANDLE handle) {
|
void ScopedFileHANDLECloseTraits::Free(HANDLE handle) {
|
||||||
PCHECK(CloseHandle(handle));
|
CheckedCloseFile(handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScopedKernelHANDLECloseTraits::Free(HANDLE handle) {
|
void ScopedKernelHANDLECloseTraits::Free(HANDLE handle) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user