Move POSIX wrappers to separate files.
This commit is contained in:
+1
-165
@@ -29,171 +29,7 @@
|
||||
|
||||
#if FMT_USE_FILE_DESCRIPTORS
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifndef _WIN32
|
||||
# include <unistd.h>
|
||||
#else
|
||||
# include <io.h>
|
||||
|
||||
# define O_CREAT _O_CREAT
|
||||
# define O_TRUNC _O_TRUNC
|
||||
# define S_IRUSR _S_IREAD
|
||||
# define S_IWUSR _S_IWRITE
|
||||
|
||||
#endif // _WIN32
|
||||
|
||||
// Retries the expression while it evaluates to -1 and error equals to EINTR.
|
||||
#ifndef _WIN32
|
||||
# define FMT_RETRY(result, expression) \
|
||||
do { \
|
||||
result = (expression); \
|
||||
} while (result == -1 && errno == EINTR)
|
||||
#else
|
||||
# define FMT_RETRY(result, expression) result = (expression)
|
||||
#endif
|
||||
|
||||
namespace {
|
||||
#ifdef _WIN32
|
||||
// On Windows the count argument to read and write is unsigned, so convert
|
||||
// it from size_t preventing integer overflow.
|
||||
inline unsigned ConvertRWCount(std::size_t count) {
|
||||
return count <= UINT_MAX ? static_cast<unsigned>(count) : UINT_MAX;
|
||||
}
|
||||
#else
|
||||
inline std::size_t ConvertRWCount(std::size_t count) { return count; }
|
||||
#endif
|
||||
}
|
||||
|
||||
BufferedFile::~BufferedFile() FMT_NOEXCEPT(true) {
|
||||
if (file_ && FMT_SYSTEM(fclose(file_)) != 0)
|
||||
fmt::ReportSystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
void BufferedFile::close() {
|
||||
if (!file_)
|
||||
return;
|
||||
int result = FMT_SYSTEM(fclose(file_));
|
||||
file_ = 0;
|
||||
if (result != 0)
|
||||
fmt::ThrowSystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
int BufferedFile::fileno() const {
|
||||
int fd = FMT_POSIX_CALL(fileno(file_));
|
||||
if (fd == -1)
|
||||
fmt::ThrowSystemError(errno, "cannot get file descriptor");
|
||||
return fd;
|
||||
}
|
||||
|
||||
File::File(const char *path, int oflag) {
|
||||
int mode = S_IRUSR | S_IWUSR;
|
||||
#ifdef _WIN32
|
||||
fd_ = -1;
|
||||
FMT_POSIX_CALL(sopen_s(&fd_, path, oflag, _SH_DENYNO, mode));
|
||||
#else
|
||||
FMT_RETRY(fd_, FMT_POSIX_CALL(open(path, oflag, mode)));
|
||||
#endif
|
||||
if (fd_ == -1)
|
||||
fmt::ThrowSystemError(errno, "cannot open file {}") << path;
|
||||
}
|
||||
|
||||
File::~File() FMT_NOEXCEPT(true) {
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
if (fd_ != -1 && FMT_POSIX_CALL(close(fd_)) != 0)
|
||||
fmt::ReportSystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
void File::close() {
|
||||
if (fd_ == -1)
|
||||
return;
|
||||
// Don't retry close in case of EINTR!
|
||||
// See http://linux.derkeiler.com/Mailing-Lists/Kernel/2005-09/3000.html
|
||||
int result = FMT_POSIX_CALL(close(fd_));
|
||||
fd_ = -1;
|
||||
if (result != 0)
|
||||
fmt::ThrowSystemError(errno, "cannot close file");
|
||||
}
|
||||
|
||||
std::streamsize File::read(void *buffer, std::size_t count) {
|
||||
std::streamsize result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, ConvertRWCount(count))));
|
||||
if (result == -1)
|
||||
fmt::ThrowSystemError(errno, "cannot read from file");
|
||||
return result;
|
||||
}
|
||||
|
||||
std::streamsize File::write(const void *buffer, std::size_t count) {
|
||||
std::streamsize result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, ConvertRWCount(count))));
|
||||
if (result == -1)
|
||||
fmt::ThrowSystemError(errno, "cannot write to file");
|
||||
return result;
|
||||
}
|
||||
|
||||
File File::dup(int fd) {
|
||||
// Don't retry as dup doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009695399/functions/dup.html
|
||||
int new_fd = FMT_POSIX_CALL(dup(fd));
|
||||
if (new_fd == -1)
|
||||
fmt::ThrowSystemError(errno, "cannot duplicate file descriptor {}") << fd;
|
||||
return File(new_fd);
|
||||
}
|
||||
|
||||
void File::dup2(int fd) {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1) {
|
||||
fmt::ThrowSystemError(errno,
|
||||
"cannot duplicate file descriptor {} to {}") << fd_ << fd;
|
||||
}
|
||||
}
|
||||
|
||||
void File::dup2(int fd, ErrorCode &ec) FMT_NOEXCEPT(true) {
|
||||
int result = 0;
|
||||
FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd)));
|
||||
if (result == -1)
|
||||
ec = ErrorCode(errno);
|
||||
}
|
||||
|
||||
void File::pipe(File &read_end, File &write_end) {
|
||||
// Close the descriptors first to make sure that assignments don't throw
|
||||
// and there are no leaks.
|
||||
read_end.close();
|
||||
write_end.close();
|
||||
int fds[2] = {};
|
||||
#ifdef _WIN32
|
||||
// Make the default pipe capacity same as on Linux 2.6.11+.
|
||||
enum { DEFAULT_CAPACITY = 65536 };
|
||||
int result = FMT_POSIX_CALL(pipe(fds, DEFAULT_CAPACITY, _O_BINARY));
|
||||
#else
|
||||
// Don't retry as the pipe function doesn't return EINTR.
|
||||
// http://pubs.opengroup.org/onlinepubs/009696799/functions/pipe.html
|
||||
int result = FMT_POSIX_CALL(pipe(fds));
|
||||
#endif
|
||||
if (result != 0)
|
||||
fmt::ThrowSystemError(errno, "cannot create pipe");
|
||||
// The following assignments don't throw because read_fd and write_fd
|
||||
// are closed.
|
||||
read_end = File(fds[0]);
|
||||
write_end = File(fds[1]);
|
||||
}
|
||||
|
||||
BufferedFile File::fdopen(const char *mode) {
|
||||
// Don't retry as fdopen doesn't return EINTR.
|
||||
FILE *f = FMT_POSIX_CALL(fdopen(fd_, mode));
|
||||
if (!f) {
|
||||
fmt::ThrowSystemError(errno,
|
||||
"cannot associate stream with file descriptor");
|
||||
}
|
||||
BufferedFile file(f);
|
||||
fd_ = -1;
|
||||
return file;
|
||||
}
|
||||
#include "posix.cc"
|
||||
|
||||
void OutputRedirect::Flush() {
|
||||
#if EOF != -1
|
||||
|
||||
Reference in New Issue
Block a user