1*00b67f09SDavid van Moolenbroek // 2*00b67f09SDavid van Moolenbroek // Automated Testing Framework (atf) 3*00b67f09SDavid van Moolenbroek // 4*00b67f09SDavid van Moolenbroek // Copyright (c) 2007 The NetBSD Foundation, Inc. 5*00b67f09SDavid van Moolenbroek // All rights reserved. 6*00b67f09SDavid van Moolenbroek // 7*00b67f09SDavid van Moolenbroek // Redistribution and use in source and binary forms, with or without 8*00b67f09SDavid van Moolenbroek // modification, are permitted provided that the following conditions 9*00b67f09SDavid van Moolenbroek // are met: 10*00b67f09SDavid van Moolenbroek // 1. Redistributions of source code must retain the above copyright 11*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer. 12*00b67f09SDavid van Moolenbroek // 2. Redistributions in binary form must reproduce the above copyright 13*00b67f09SDavid van Moolenbroek // notice, this list of conditions and the following disclaimer in the 14*00b67f09SDavid van Moolenbroek // documentation and/or other materials provided with the distribution. 15*00b67f09SDavid van Moolenbroek // 16*00b67f09SDavid van Moolenbroek // THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17*00b67f09SDavid van Moolenbroek // CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18*00b67f09SDavid van Moolenbroek // INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19*00b67f09SDavid van Moolenbroek // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20*00b67f09SDavid van Moolenbroek // IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21*00b67f09SDavid van Moolenbroek // DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*00b67f09SDavid van Moolenbroek // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23*00b67f09SDavid van Moolenbroek // GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24*00b67f09SDavid van Moolenbroek // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25*00b67f09SDavid van Moolenbroek // IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26*00b67f09SDavid van Moolenbroek // OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27*00b67f09SDavid van Moolenbroek // IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28*00b67f09SDavid van Moolenbroek // 29*00b67f09SDavid van Moolenbroek 30*00b67f09SDavid van Moolenbroek #if !defined(_ATF_RUN_IO_HPP_) 31*00b67f09SDavid van Moolenbroek #define _ATF_RUN_IO_HPP_ 32*00b67f09SDavid van Moolenbroek 33*00b67f09SDavid van Moolenbroek #include <istream> 34*00b67f09SDavid van Moolenbroek #include <ostream> 35*00b67f09SDavid van Moolenbroek #include <streambuf> 36*00b67f09SDavid van Moolenbroek 37*00b67f09SDavid van Moolenbroek #include "fs.hpp" 38*00b67f09SDavid van Moolenbroek 39*00b67f09SDavid van Moolenbroek #include "../atf-c++/detail/auto_array.hpp" 40*00b67f09SDavid van Moolenbroek #include "../atf-c++/noncopyable.hpp" 41*00b67f09SDavid van Moolenbroek 42*00b67f09SDavid van Moolenbroek namespace atf { 43*00b67f09SDavid van Moolenbroek namespace atf_run { 44*00b67f09SDavid van Moolenbroek 45*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 46*00b67f09SDavid van Moolenbroek // The "file_handle" class. 47*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 48*00b67f09SDavid van Moolenbroek 49*00b67f09SDavid van Moolenbroek //! 50*00b67f09SDavid van Moolenbroek //! \brief Simple RAII model for system file handles. 51*00b67f09SDavid van Moolenbroek //! 52*00b67f09SDavid van Moolenbroek //! The \a file_handle class is a simple RAII model for native system file 53*00b67f09SDavid van Moolenbroek //! handles. This class wraps one of such handles grabbing its ownership, 54*00b67f09SDavid van Moolenbroek //! and automaticaly closes it upon destruction. It is basically used 55*00b67f09SDavid van Moolenbroek //! inside the library to avoid leaking open file handles, shall an 56*00b67f09SDavid van Moolenbroek //! unexpected execution trace occur. 57*00b67f09SDavid van Moolenbroek //! 58*00b67f09SDavid van Moolenbroek //! A \a file_handle object can be copied but doing so invalidates the 59*00b67f09SDavid van Moolenbroek //! source object. There can only be a single valid \a file_handle object 60*00b67f09SDavid van Moolenbroek //! for a given system file handle. This is similar to std::auto_ptr\<\>'s 61*00b67f09SDavid van Moolenbroek //! semantics. 62*00b67f09SDavid van Moolenbroek //! 63*00b67f09SDavid van Moolenbroek //! This class also provides some convenience methods to issue special file 64*00b67f09SDavid van Moolenbroek //! operations under their respective platforms. 65*00b67f09SDavid van Moolenbroek //! 66*00b67f09SDavid van Moolenbroek class file_handle 67*00b67f09SDavid van Moolenbroek { 68*00b67f09SDavid van Moolenbroek public: 69*00b67f09SDavid van Moolenbroek //! 70*00b67f09SDavid van Moolenbroek //! \brief Opaque name for the native handle type. 71*00b67f09SDavid van Moolenbroek //! 72*00b67f09SDavid van Moolenbroek //! Each operating system identifies file handles using a specific type. 73*00b67f09SDavid van Moolenbroek //! The \a handle_type type is used to transparently refer to file 74*00b67f09SDavid van Moolenbroek //! handles regarless of the operating system in which this class is 75*00b67f09SDavid van Moolenbroek //! used. 76*00b67f09SDavid van Moolenbroek //! 77*00b67f09SDavid van Moolenbroek //! If this class is used in a POSIX system, \a NativeSystemHandle is 78*00b67f09SDavid van Moolenbroek //! an integer type while it is a \a HANDLE in a Win32 system. 79*00b67f09SDavid van Moolenbroek //! 80*00b67f09SDavid van Moolenbroek typedef int handle_type; 81*00b67f09SDavid van Moolenbroek 82*00b67f09SDavid van Moolenbroek //! 83*00b67f09SDavid van Moolenbroek //! \brief Constructs an invalid file handle. 84*00b67f09SDavid van Moolenbroek //! 85*00b67f09SDavid van Moolenbroek //! This constructor creates a new \a file_handle object that represents 86*00b67f09SDavid van Moolenbroek //! an invalid file handle. An invalid file handle can be copied but 87*00b67f09SDavid van Moolenbroek //! cannot be manipulated in any way (except checking for its validity). 88*00b67f09SDavid van Moolenbroek //! 89*00b67f09SDavid van Moolenbroek //! \see is_valid() 90*00b67f09SDavid van Moolenbroek //! 91*00b67f09SDavid van Moolenbroek file_handle(void); 92*00b67f09SDavid van Moolenbroek 93*00b67f09SDavid van Moolenbroek //! 94*00b67f09SDavid van Moolenbroek //! \brief Constructs a new file handle from a native file handle. 95*00b67f09SDavid van Moolenbroek //! 96*00b67f09SDavid van Moolenbroek //! This constructor creates a new \a file_handle object that takes 97*00b67f09SDavid van Moolenbroek //! ownership of the given \a h native file handle. The user must not 98*00b67f09SDavid van Moolenbroek //! close \a h on his own during the lifetime of the new object. 99*00b67f09SDavid van Moolenbroek //! Ownership can be reclaimed using disown(). 100*00b67f09SDavid van Moolenbroek //! 101*00b67f09SDavid van Moolenbroek //! \pre The native file handle must be valid; a close operation must 102*00b67f09SDavid van Moolenbroek //! succeed on it. 103*00b67f09SDavid van Moolenbroek //! 104*00b67f09SDavid van Moolenbroek //! \see disown() 105*00b67f09SDavid van Moolenbroek //! 106*00b67f09SDavid van Moolenbroek file_handle(handle_type h); 107*00b67f09SDavid van Moolenbroek 108*00b67f09SDavid van Moolenbroek //! 109*00b67f09SDavid van Moolenbroek //! \brief Copy constructor; invalidates the source handle. 110*00b67f09SDavid van Moolenbroek //! 111*00b67f09SDavid van Moolenbroek //! This copy constructor creates a new file handle from a given one. 112*00b67f09SDavid van Moolenbroek //! Ownership of the native file handle is transferred to the new 113*00b67f09SDavid van Moolenbroek //! object, effectively invalidating the source file handle. This 114*00b67f09SDavid van Moolenbroek //! avoids having two live \a file_handle objects referring to the 115*00b67f09SDavid van Moolenbroek //! same native file handle. The source file handle need not be 116*00b67f09SDavid van Moolenbroek //! valid in the name of simplicity. 117*00b67f09SDavid van Moolenbroek //! 118*00b67f09SDavid van Moolenbroek //! \post The source file handle is invalid. 119*00b67f09SDavid van Moolenbroek //! \post The new file handle owns the source's native file handle. 120*00b67f09SDavid van Moolenbroek //! 121*00b67f09SDavid van Moolenbroek file_handle(const file_handle& fh); 122*00b67f09SDavid van Moolenbroek 123*00b67f09SDavid van Moolenbroek //! 124*00b67f09SDavid van Moolenbroek //! \brief Releases resources if the handle is valid. 125*00b67f09SDavid van Moolenbroek //! 126*00b67f09SDavid van Moolenbroek //! If the file handle is valid, the destructor closes it. 127*00b67f09SDavid van Moolenbroek //! 128*00b67f09SDavid van Moolenbroek //! \see is_valid() 129*00b67f09SDavid van Moolenbroek //! 130*00b67f09SDavid van Moolenbroek ~file_handle(void); 131*00b67f09SDavid van Moolenbroek 132*00b67f09SDavid van Moolenbroek //! 133*00b67f09SDavid van Moolenbroek //! \brief Assignment operator; invalidates the source handle. 134*00b67f09SDavid van Moolenbroek //! 135*00b67f09SDavid van Moolenbroek //! This assignment operator transfers ownership of the RHS file 136*00b67f09SDavid van Moolenbroek //! handle to the LHS one, effectively invalidating the source file 137*00b67f09SDavid van Moolenbroek //! handle. This avoids having two live \a file_handle objects 138*00b67f09SDavid van Moolenbroek //! referring to the same native file handle. The source file 139*00b67f09SDavid van Moolenbroek //! handle need not be valid in the name of simplicity. 140*00b67f09SDavid van Moolenbroek //! 141*00b67f09SDavid van Moolenbroek //! \post The RHS file handle is invalid. 142*00b67f09SDavid van Moolenbroek //! \post The LHS file handle owns RHS' native file handle. 143*00b67f09SDavid van Moolenbroek //! \return A reference to the LHS file handle. 144*00b67f09SDavid van Moolenbroek //! 145*00b67f09SDavid van Moolenbroek file_handle& operator=(const file_handle& fh); 146*00b67f09SDavid van Moolenbroek 147*00b67f09SDavid van Moolenbroek //! 148*00b67f09SDavid van Moolenbroek //! \brief Checks whether the file handle is valid or not. 149*00b67f09SDavid van Moolenbroek //! 150*00b67f09SDavid van Moolenbroek //! Returns a boolean indicating whether the file handle is valid or 151*00b67f09SDavid van Moolenbroek //! not. If the file handle is invalid, no other applications can be 152*00b67f09SDavid van Moolenbroek //! executed other than the destructor. 153*00b67f09SDavid van Moolenbroek //! 154*00b67f09SDavid van Moolenbroek //! \return True if the file handle is valid; false otherwise. 155*00b67f09SDavid van Moolenbroek //! 156*00b67f09SDavid van Moolenbroek bool is_valid(void) const; 157*00b67f09SDavid van Moolenbroek 158*00b67f09SDavid van Moolenbroek //! 159*00b67f09SDavid van Moolenbroek //! \brief Closes the file handle. 160*00b67f09SDavid van Moolenbroek //! 161*00b67f09SDavid van Moolenbroek //! Explicitly closes the file handle, which must be valid. Upon 162*00b67f09SDavid van Moolenbroek //! exit, the handle is not valid any more. 163*00b67f09SDavid van Moolenbroek //! 164*00b67f09SDavid van Moolenbroek //! \pre The file handle is valid. 165*00b67f09SDavid van Moolenbroek //! \post The file handle is invalid. 166*00b67f09SDavid van Moolenbroek //! \post The native file handle is closed. 167*00b67f09SDavid van Moolenbroek //! 168*00b67f09SDavid van Moolenbroek void close(void); 169*00b67f09SDavid van Moolenbroek 170*00b67f09SDavid van Moolenbroek //! 171*00b67f09SDavid van Moolenbroek //! \brief Reclaims ownership of the native file handle. 172*00b67f09SDavid van Moolenbroek //! 173*00b67f09SDavid van Moolenbroek //! Explicitly reclaims ownership of the native file handle contained 174*00b67f09SDavid van Moolenbroek //! in the \a file_handle object, returning the native file handle. 175*00b67f09SDavid van Moolenbroek //! The caller is responsible of closing it later on. 176*00b67f09SDavid van Moolenbroek //! 177*00b67f09SDavid van Moolenbroek //! \pre The file handle is valid. 178*00b67f09SDavid van Moolenbroek //! \post The file handle is invalid. 179*00b67f09SDavid van Moolenbroek //! \return The native file handle. 180*00b67f09SDavid van Moolenbroek //! 181*00b67f09SDavid van Moolenbroek handle_type disown(void); 182*00b67f09SDavid van Moolenbroek 183*00b67f09SDavid van Moolenbroek //! 184*00b67f09SDavid van Moolenbroek //! \brief Gets the native file handle. 185*00b67f09SDavid van Moolenbroek //! 186*00b67f09SDavid van Moolenbroek //! Returns the native file handle for the \a file_handle object. 187*00b67f09SDavid van Moolenbroek //! The caller can issue any operation on it except closing it. 188*00b67f09SDavid van Moolenbroek //! If closing is required, disown() shall be used. 189*00b67f09SDavid van Moolenbroek //! 190*00b67f09SDavid van Moolenbroek //! \pre The file handle is valid. 191*00b67f09SDavid van Moolenbroek //! \return The native file handle. 192*00b67f09SDavid van Moolenbroek //! 193*00b67f09SDavid van Moolenbroek handle_type get(void) const; 194*00b67f09SDavid van Moolenbroek 195*00b67f09SDavid van Moolenbroek //! 196*00b67f09SDavid van Moolenbroek //! \brief Changes the native file handle to the given one. 197*00b67f09SDavid van Moolenbroek //! 198*00b67f09SDavid van Moolenbroek //! Given a new native file handle \a h, this operation assigns this 199*00b67f09SDavid van Moolenbroek //! handle to the current object, closing its old native file handle. 200*00b67f09SDavid van Moolenbroek //! In other words, it first calls dup2() to remap the old handle to 201*00b67f09SDavid van Moolenbroek //! the new one and then closes the old handle. 202*00b67f09SDavid van Moolenbroek //! 203*00b67f09SDavid van Moolenbroek //! If \a h matches the current value of the handle, this is a no-op. 204*00b67f09SDavid van Moolenbroek //! This is done for simplicity, to avoid the caller having to check 205*00b67f09SDavid van Moolenbroek //! this condition on its own. 206*00b67f09SDavid van Moolenbroek //! 207*00b67f09SDavid van Moolenbroek //! If \a h is open, it is automatically closed by dup2(). 208*00b67f09SDavid van Moolenbroek //! 209*00b67f09SDavid van Moolenbroek //! This operation is only available in POSIX systems. 210*00b67f09SDavid van Moolenbroek //! 211*00b67f09SDavid van Moolenbroek //! \pre The file handle is valid. 212*00b67f09SDavid van Moolenbroek //! \pre The native file handle \a h is valid; i.e., it must be 213*00b67f09SDavid van Moolenbroek //! closeable. 214*00b67f09SDavid van Moolenbroek //! \post The file handle's native file handle is \a h. 215*00b67f09SDavid van Moolenbroek //! \throw system_error If the internal remapping operation fails. 216*00b67f09SDavid van Moolenbroek //! 217*00b67f09SDavid van Moolenbroek void posix_remap(handle_type h); 218*00b67f09SDavid van Moolenbroek 219*00b67f09SDavid van Moolenbroek private: 220*00b67f09SDavid van Moolenbroek //! 221*00b67f09SDavid van Moolenbroek //! \brief Internal handle value. 222*00b67f09SDavid van Moolenbroek //! 223*00b67f09SDavid van Moolenbroek //! This variable holds the native handle value for the file handle 224*00b67f09SDavid van Moolenbroek //! hold by this object. It is interesting to note that this needs 225*00b67f09SDavid van Moolenbroek //! to be mutable because the copy constructor and the assignment 226*00b67f09SDavid van Moolenbroek //! operator invalidate the source object. 227*00b67f09SDavid van Moolenbroek //! 228*00b67f09SDavid van Moolenbroek mutable handle_type m_handle; 229*00b67f09SDavid van Moolenbroek 230*00b67f09SDavid van Moolenbroek //! 231*00b67f09SDavid van Moolenbroek //! \brief Constant function representing an invalid handle value. 232*00b67f09SDavid van Moolenbroek //! 233*00b67f09SDavid van Moolenbroek //! Returns the platform-specific handle value that represents an 234*00b67f09SDavid van Moolenbroek //! invalid handle. This is a constant function rather than a regular 235*00b67f09SDavid van Moolenbroek //! constant because, in the latter case, we cannot define it under 236*00b67f09SDavid van Moolenbroek //! Win32 due to the value being of a complex type. 237*00b67f09SDavid van Moolenbroek //! 238*00b67f09SDavid van Moolenbroek static handle_type invalid_value(void); 239*00b67f09SDavid van Moolenbroek }; 240*00b67f09SDavid van Moolenbroek 241*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 242*00b67f09SDavid van Moolenbroek // The "systembuf" class. 243*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 244*00b67f09SDavid van Moolenbroek 245*00b67f09SDavid van Moolenbroek //! 246*00b67f09SDavid van Moolenbroek //! \brief std::streambuf implementation for system file handles. 247*00b67f09SDavid van Moolenbroek //! 248*00b67f09SDavid van Moolenbroek //! systembuf provides a std::streambuf implementation for system file 249*00b67f09SDavid van Moolenbroek //! handles. Contrarywise to file_handle, this class does \b not take 250*00b67f09SDavid van Moolenbroek //! ownership of the native file handle; this should be taken care of 251*00b67f09SDavid van Moolenbroek //! somewhere else. 252*00b67f09SDavid van Moolenbroek //! 253*00b67f09SDavid van Moolenbroek //! This class follows the expected semantics of a std::streambuf object. 254*00b67f09SDavid van Moolenbroek //! However, it is not copyable to avoid introducing inconsistences with 255*00b67f09SDavid van Moolenbroek //! the on-disk file and the in-memory buffers. 256*00b67f09SDavid van Moolenbroek //! 257*00b67f09SDavid van Moolenbroek class systembuf : public std::streambuf, atf::noncopyable 258*00b67f09SDavid van Moolenbroek { 259*00b67f09SDavid van Moolenbroek public: 260*00b67f09SDavid van Moolenbroek typedef int handle_type; 261*00b67f09SDavid van Moolenbroek 262*00b67f09SDavid van Moolenbroek //! 263*00b67f09SDavid van Moolenbroek //! \brief Constructs a new systembuf for the given file handle. 264*00b67f09SDavid van Moolenbroek //! 265*00b67f09SDavid van Moolenbroek //! This constructor creates a new systembuf object that reads or 266*00b67f09SDavid van Moolenbroek //! writes data from/to the \a h native file handle. This handle 267*00b67f09SDavid van Moolenbroek //! is \b not owned by the created systembuf object; the code 268*00b67f09SDavid van Moolenbroek //! should take care of it externally. 269*00b67f09SDavid van Moolenbroek //! 270*00b67f09SDavid van Moolenbroek //! This class buffers input and output; the buffer size may be 271*00b67f09SDavid van Moolenbroek //! tuned through the \a bufsize parameter, which defaults to 8192 272*00b67f09SDavid van Moolenbroek //! bytes. 273*00b67f09SDavid van Moolenbroek //! 274*00b67f09SDavid van Moolenbroek //! \see pistream. 275*00b67f09SDavid van Moolenbroek //! 276*00b67f09SDavid van Moolenbroek explicit systembuf(handle_type h, std::size_t bufsize = 8192); 277*00b67f09SDavid van Moolenbroek ~systembuf(void); 278*00b67f09SDavid van Moolenbroek 279*00b67f09SDavid van Moolenbroek private: 280*00b67f09SDavid van Moolenbroek //! 281*00b67f09SDavid van Moolenbroek //! \brief Native file handle used by the systembuf object. 282*00b67f09SDavid van Moolenbroek //! 283*00b67f09SDavid van Moolenbroek handle_type m_handle; 284*00b67f09SDavid van Moolenbroek 285*00b67f09SDavid van Moolenbroek //! 286*00b67f09SDavid van Moolenbroek //! \brief Internal buffer size used during read and write operations. 287*00b67f09SDavid van Moolenbroek //! 288*00b67f09SDavid van Moolenbroek std::size_t m_bufsize; 289*00b67f09SDavid van Moolenbroek 290*00b67f09SDavid van Moolenbroek //! 291*00b67f09SDavid van Moolenbroek //! \brief Internal buffer used during read operations. 292*00b67f09SDavid van Moolenbroek //! 293*00b67f09SDavid van Moolenbroek char* m_read_buf; 294*00b67f09SDavid van Moolenbroek 295*00b67f09SDavid van Moolenbroek //! 296*00b67f09SDavid van Moolenbroek //! \brief Internal buffer used during write operations. 297*00b67f09SDavid van Moolenbroek //! 298*00b67f09SDavid van Moolenbroek char* m_write_buf; 299*00b67f09SDavid van Moolenbroek 300*00b67f09SDavid van Moolenbroek protected: 301*00b67f09SDavid van Moolenbroek //! 302*00b67f09SDavid van Moolenbroek //! \brief Reads new data from the native file handle. 303*00b67f09SDavid van Moolenbroek //! 304*00b67f09SDavid van Moolenbroek //! This operation is called by input methods when there are no more 305*00b67f09SDavid van Moolenbroek //! data in the input buffer. The function fills the buffer with new 306*00b67f09SDavid van Moolenbroek //! data, if available. 307*00b67f09SDavid van Moolenbroek //! 308*00b67f09SDavid van Moolenbroek //! \pre All input positions are exhausted (gptr() >= egptr()). 309*00b67f09SDavid van Moolenbroek //! \post The input buffer has new data, if available. 310*00b67f09SDavid van Moolenbroek //! \returns traits_type::eof() if a read error occurrs or there are 311*00b67f09SDavid van Moolenbroek //! no more data to be read. Otherwise returns 312*00b67f09SDavid van Moolenbroek //! traits_type::to_int_type(*gptr()). 313*00b67f09SDavid van Moolenbroek //! 314*00b67f09SDavid van Moolenbroek virtual int_type underflow(void); 315*00b67f09SDavid van Moolenbroek 316*00b67f09SDavid van Moolenbroek //! 317*00b67f09SDavid van Moolenbroek //! \brief Makes room in the write buffer for additional data. 318*00b67f09SDavid van Moolenbroek //! 319*00b67f09SDavid van Moolenbroek //! This operation is called by output methods when there is no more 320*00b67f09SDavid van Moolenbroek //! space in the output buffer to hold a new element. The function 321*00b67f09SDavid van Moolenbroek //! first flushes the buffer's contents to disk and then clears it to 322*00b67f09SDavid van Moolenbroek //! leave room for more characters. The given \a c character is 323*00b67f09SDavid van Moolenbroek //! stored at the beginning of the new space. 324*00b67f09SDavid van Moolenbroek //! 325*00b67f09SDavid van Moolenbroek //! \pre All output positions are exhausted (pptr() >= epptr()). 326*00b67f09SDavid van Moolenbroek //! \post The output buffer has more space if no errors occurred 327*00b67f09SDavid van Moolenbroek //! during the write to disk. 328*00b67f09SDavid van Moolenbroek //! \post *(pptr() - 1) is \a c. 329*00b67f09SDavid van Moolenbroek //! \returns traits_type::eof() if a write error occurrs. Otherwise 330*00b67f09SDavid van Moolenbroek //! returns traits_type::not_eof(c). 331*00b67f09SDavid van Moolenbroek //! 332*00b67f09SDavid van Moolenbroek virtual int_type overflow(int c); 333*00b67f09SDavid van Moolenbroek 334*00b67f09SDavid van Moolenbroek //! 335*00b67f09SDavid van Moolenbroek //! \brief Flushes the output buffer to disk. 336*00b67f09SDavid van Moolenbroek //! 337*00b67f09SDavid van Moolenbroek //! Synchronizes the systembuf buffers with the contents of the file 338*00b67f09SDavid van Moolenbroek //! associated to this object through the native file handle. The 339*00b67f09SDavid van Moolenbroek //! output buffer is flushed to disk and cleared to leave new room 340*00b67f09SDavid van Moolenbroek //! for more data. 341*00b67f09SDavid van Moolenbroek //! 342*00b67f09SDavid van Moolenbroek //! \returns 0 on success, -1 if an error occurred. 343*00b67f09SDavid van Moolenbroek //! 344*00b67f09SDavid van Moolenbroek virtual int sync(void); 345*00b67f09SDavid van Moolenbroek }; 346*00b67f09SDavid van Moolenbroek 347*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 348*00b67f09SDavid van Moolenbroek // The "pistream" class. 349*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 350*00b67f09SDavid van Moolenbroek 351*00b67f09SDavid van Moolenbroek //! 352*00b67f09SDavid van Moolenbroek //! \brief Child process' output stream. 353*00b67f09SDavid van Moolenbroek //! 354*00b67f09SDavid van Moolenbroek //! The pistream class represents an output communication channel with the 355*00b67f09SDavid van Moolenbroek //! child process. The child process writes data to this stream and the 356*00b67f09SDavid van Moolenbroek //! parent process can read it through the pistream object. In other 357*00b67f09SDavid van Moolenbroek //! words, from the child's point of view, the communication channel is an 358*00b67f09SDavid van Moolenbroek //! output one, but from the parent's point of view it is an input one; 359*00b67f09SDavid van Moolenbroek //! hence the confusing pistream name. 360*00b67f09SDavid van Moolenbroek //! 361*00b67f09SDavid van Moolenbroek //! pistream objects cannot be copied because they own the file handle 362*00b67f09SDavid van Moolenbroek //! they use to communicate with the child and because they buffer data 363*00b67f09SDavid van Moolenbroek //! that flows through the communication channel. 364*00b67f09SDavid van Moolenbroek //! 365*00b67f09SDavid van Moolenbroek //! A pistream object behaves as a std::istream stream in all senses. 366*00b67f09SDavid van Moolenbroek //! The class is only provided because it must provide a method to let 367*00b67f09SDavid van Moolenbroek //! the caller explicitly close the communication channel. 368*00b67f09SDavid van Moolenbroek //! 369*00b67f09SDavid van Moolenbroek //! \remark <b>Blocking remarks</b>: Functions that read data from this 370*00b67f09SDavid van Moolenbroek //! stream can block if the associated file handle blocks during the read. 371*00b67f09SDavid van Moolenbroek //! As this class is used to communicate with child processes through 372*00b67f09SDavid van Moolenbroek //! anonymous pipes, the most typical blocking condition happens when the 373*00b67f09SDavid van Moolenbroek //! child has no more data to send to the pipe's system buffer. When 374*00b67f09SDavid van Moolenbroek //! this happens, the buffer eventually empties and the system blocks 375*00b67f09SDavid van Moolenbroek //! until the writer generates some data. 376*00b67f09SDavid van Moolenbroek //! 377*00b67f09SDavid van Moolenbroek class pistream : public std::istream, noncopyable 378*00b67f09SDavid van Moolenbroek { 379*00b67f09SDavid van Moolenbroek //! 380*00b67f09SDavid van Moolenbroek //! \brief The systembuf object used to manage this stream's data. 381*00b67f09SDavid van Moolenbroek //! 382*00b67f09SDavid van Moolenbroek systembuf m_systembuf; 383*00b67f09SDavid van Moolenbroek 384*00b67f09SDavid van Moolenbroek public: 385*00b67f09SDavid van Moolenbroek //! 386*00b67f09SDavid van Moolenbroek //! \brief Creates a new process' output stream. 387*00b67f09SDavid van Moolenbroek //! 388*00b67f09SDavid van Moolenbroek //! Given a file handle, this constructor creates a new pistream 389*00b67f09SDavid van Moolenbroek //! object that owns the given file handle \a fh. Ownership of 390*00b67f09SDavid van Moolenbroek //! \a fh is transferred to the created pistream object. 391*00b67f09SDavid van Moolenbroek //! 392*00b67f09SDavid van Moolenbroek //! \pre \a fh is valid. 393*00b67f09SDavid van Moolenbroek //! \post \a fh is invalid. 394*00b67f09SDavid van Moolenbroek //! \post The new pistream object owns \a fh. 395*00b67f09SDavid van Moolenbroek //! 396*00b67f09SDavid van Moolenbroek explicit pistream(const int); 397*00b67f09SDavid van Moolenbroek }; 398*00b67f09SDavid van Moolenbroek 399*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 400*00b67f09SDavid van Moolenbroek // The "muxer" class. 401*00b67f09SDavid van Moolenbroek // ------------------------------------------------------------------------ 402*00b67f09SDavid van Moolenbroek 403*00b67f09SDavid van Moolenbroek class muxer : noncopyable { 404*00b67f09SDavid van Moolenbroek const int* m_fds; 405*00b67f09SDavid van Moolenbroek const size_t m_nfds; 406*00b67f09SDavid van Moolenbroek 407*00b67f09SDavid van Moolenbroek const size_t m_bufsize; 408*00b67f09SDavid van Moolenbroek atf::auto_array< std::string > m_buffers; 409*00b67f09SDavid van Moolenbroek 410*00b67f09SDavid van Moolenbroek protected: 411*00b67f09SDavid van Moolenbroek virtual void line_callback(const size_t, const std::string&) = 0; 412*00b67f09SDavid van Moolenbroek 413*00b67f09SDavid van Moolenbroek size_t read_one(const size_t, const int, std::string&, const bool); 414*00b67f09SDavid van Moolenbroek 415*00b67f09SDavid van Moolenbroek public: 416*00b67f09SDavid van Moolenbroek muxer(const int*, const size_t, const size_t bufsize = 1024); 417*00b67f09SDavid van Moolenbroek virtual ~muxer(void); 418*00b67f09SDavid van Moolenbroek 419*00b67f09SDavid van Moolenbroek void mux(volatile const bool&); 420*00b67f09SDavid van Moolenbroek void flush(void); 421*00b67f09SDavid van Moolenbroek }; 422*00b67f09SDavid van Moolenbroek 423*00b67f09SDavid van Moolenbroek } // namespace atf_run 424*00b67f09SDavid van Moolenbroek } // namespace atf 425*00b67f09SDavid van Moolenbroek 426*00b67f09SDavid van Moolenbroek #endif // !defined(_ATF_RUN_IO_HPP_) 427