/// // Copyright (C) 2003, 2004, Fredrik Arnerup & Rasmus Kaj, See COPYING /// #include "filedescriptors.h" #include "filesys.h" #include #include int filedesc::move(int to, int from) { if (to == from) return 0; if (fcntl(from,F_GETFL,0) == -1) return -1; close(to); if (fcntl(from,F_DUPFD,to) == -1) return -1; close(from); return 0; } filedesc::BufBase::BufBase(int fd, bool should_close, int bufsize) : fd_(fd), should_close_(should_close), bufsize_(bufsize) {} filedesc::BufBase::~BufBase() { if(should_close_) ::close(fd_); } void filedesc::BufBase::close() { ::close(fd_); should_close_ = false; // Don't close again later } filedesc::OutBuf::OutBuf(int fd, bool should_close, int bufsize) : BufBase(fd, should_close, bufsize), outbuffer_(new char[bufsize_+1]) { setp(outbuffer_, outbuffer_+bufsize_); } filedesc::OutBuf::~OutBuf() { try { overflow(EOF); } catch(const std::exception &e) { std::cerr << "failed to flush OutBuf for fd " << fd_ << ": " << e.what() << std::endl; } delete[] outbuffer_; } int filedesc::OutBuf::sync() { return overflow(EOF); } int filedesc::OutBuf::overflow (int c) { char *endpos = pptr(); if (c != EOF) { if(endpos <= outbuffer_+bufsize_) *(endpos++) = static_cast(c); else std::cerr << "Oups: We might miss a character here." << std::endl; } int nbyte = endpos - pbase(); if(nbyte > 0) { // std::cerr << "Doing an actual write: \"" // << std::string(pbase(), endpos) << "\"" << std::endl; int status = write(fd_, pbase(), nbyte); if(status == -1) { throw ClibException("write"); } else if(status == nbyte) { } else { std::cerr << "Wrote only " << status << " bytes, not " << nbyte << std::endl; } setp(outbuffer_, outbuffer_+bufsize_); } else { // std::cerr << "Owerflow with nothing to write." << std::endl; return 0; } return 1; /// \todo Really check what the return values are supposed to mean! } filedesc::InBuf::InBuf(int fd, bool should_close, int bufsize) : BufBase(fd, should_close, bufsize), inbuffer_(new char[bufsize_]) { setg(inbuffer_, inbuffer_ + bufsize_, inbuffer_ + bufsize_); } filedesc::InBuf::~InBuf() { delete[] inbuffer_; } int filedesc::InBuf::underflow () { if(gptr() && gptr() < egptr()) { // Shouldn't have been called? return *gptr(); } const int status = read(fd_, inbuffer_, bufsize_); // std::cerr << "Actual read yielded " << status // << " (" << egptr() - gptr() << ") " << std::endl; if(status == -1) { throw ClibException("read"); } if(status <= 0) return EOF; // std::cerr << "--\n" << std::string(inbuffer_, inbuffer_+status) << "\n--" // << " [" << inbuffer_[0] << ']' << std::endl; setg(inbuffer_, inbuffer_, inbuffer_+status); return inbuffer_[0]; } filedesc::IoBuf::IoBuf(int fd, bool should_close, int bufsize) : BufBase(fd, should_close, bufsize), OutBuf(fd, should_close, bufsize), InBuf(fd, should_close, bufsize) {}