1240116Smarcel// 2240116Smarcel// Automated Testing Framework (atf) 3240116Smarcel// 4240116Smarcel// Copyright (c) 2007 The NetBSD Foundation, Inc. 5240116Smarcel// All rights reserved. 6240116Smarcel// 7240116Smarcel// Redistribution and use in source and binary forms, with or without 8240116Smarcel// modification, are permitted provided that the following conditions 9240116Smarcel// are met: 10240116Smarcel// 1. Redistributions of source code must retain the above copyright 11240116Smarcel// notice, this list of conditions and the following disclaimer. 12240116Smarcel// 2. Redistributions in binary form must reproduce the above copyright 13240116Smarcel// notice, this list of conditions and the following disclaimer in the 14240116Smarcel// documentation and/or other materials provided with the distribution. 15240116Smarcel// 16240116Smarcel// THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND 17240116Smarcel// CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, 18240116Smarcel// INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 19240116Smarcel// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20240116Smarcel// IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS BE LIABLE FOR ANY 21240116Smarcel// DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22240116Smarcel// DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 23240116Smarcel// GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 24240116Smarcel// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER 25240116Smarcel// IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR 26240116Smarcel// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN 27240116Smarcel// IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28240116Smarcel// 29240116Smarcel 30240116Smarcel#if !defined(_ATF_RUN_IO_HPP_) 31240116Smarcel#define _ATF_RUN_IO_HPP_ 32240116Smarcel 33240116Smarcel#include <istream> 34240116Smarcel#include <ostream> 35240116Smarcel#include <streambuf> 36240116Smarcel 37240116Smarcel#include "fs.hpp" 38240116Smarcel 39240116Smarcel#include "../atf-c++/utils.hpp" 40240116Smarcel 41240116Smarcelnamespace atf { 42240116Smarcelnamespace atf_run { 43240116Smarcel 44240116Smarcel// ------------------------------------------------------------------------ 45240116Smarcel// The "file_handle" class. 46240116Smarcel// ------------------------------------------------------------------------ 47240116Smarcel 48240116Smarcel//! 49240116Smarcel//! \brief Simple RAII model for system file handles. 50240116Smarcel//! 51240116Smarcel//! The \a file_handle class is a simple RAII model for native system file 52240116Smarcel//! handles. This class wraps one of such handles grabbing its ownership, 53240116Smarcel//! and automaticaly closes it upon destruction. It is basically used 54240116Smarcel//! inside the library to avoid leaking open file handles, shall an 55240116Smarcel//! unexpected execution trace occur. 56240116Smarcel//! 57240116Smarcel//! A \a file_handle object can be copied but doing so invalidates the 58240116Smarcel//! source object. There can only be a single valid \a file_handle object 59240116Smarcel//! for a given system file handle. This is similar to std::auto_ptr\<\>'s 60240116Smarcel//! semantics. 61240116Smarcel//! 62240116Smarcel//! This class also provides some convenience methods to issue special file 63240116Smarcel//! operations under their respective platforms. 64240116Smarcel//! 65240116Smarcelclass file_handle 66240116Smarcel{ 67240116Smarcelpublic: 68240116Smarcel //! 69240116Smarcel //! \brief Opaque name for the native handle type. 70240116Smarcel //! 71240116Smarcel //! Each operating system identifies file handles using a specific type. 72240116Smarcel //! The \a handle_type type is used to transparently refer to file 73240116Smarcel //! handles regarless of the operating system in which this class is 74240116Smarcel //! used. 75240116Smarcel //! 76240116Smarcel //! If this class is used in a POSIX system, \a NativeSystemHandle is 77240116Smarcel //! an integer type while it is a \a HANDLE in a Win32 system. 78240116Smarcel //! 79240116Smarcel typedef int handle_type; 80240116Smarcel 81240116Smarcel //! 82240116Smarcel //! \brief Constructs an invalid file handle. 83240116Smarcel //! 84240116Smarcel //! This constructor creates a new \a file_handle object that represents 85240116Smarcel //! an invalid file handle. An invalid file handle can be copied but 86240116Smarcel //! cannot be manipulated in any way (except checking for its validity). 87240116Smarcel //! 88240116Smarcel //! \see is_valid() 89240116Smarcel //! 90240116Smarcel file_handle(void); 91240116Smarcel 92240116Smarcel //! 93240116Smarcel //! \brief Constructs a new file handle from a native file handle. 94240116Smarcel //! 95240116Smarcel //! This constructor creates a new \a file_handle object that takes 96240116Smarcel //! ownership of the given \a h native file handle. The user must not 97240116Smarcel //! close \a h on his own during the lifetime of the new object. 98240116Smarcel //! Ownership can be reclaimed using disown(). 99240116Smarcel //! 100240116Smarcel //! \pre The native file handle must be valid; a close operation must 101240116Smarcel //! succeed on it. 102240116Smarcel //! 103240116Smarcel //! \see disown() 104240116Smarcel //! 105240116Smarcel file_handle(handle_type h); 106240116Smarcel 107240116Smarcel //! 108240116Smarcel //! \brief Copy constructor; invalidates the source handle. 109240116Smarcel //! 110240116Smarcel //! This copy constructor creates a new file handle from a given one. 111240116Smarcel //! Ownership of the native file handle is transferred to the new 112240116Smarcel //! object, effectively invalidating the source file handle. This 113240116Smarcel //! avoids having two live \a file_handle objects referring to the 114240116Smarcel //! same native file handle. The source file handle need not be 115240116Smarcel //! valid in the name of simplicity. 116240116Smarcel //! 117240116Smarcel //! \post The source file handle is invalid. 118240116Smarcel //! \post The new file handle owns the source's native file handle. 119240116Smarcel //! 120240116Smarcel file_handle(const file_handle& fh); 121240116Smarcel 122240116Smarcel //! 123240116Smarcel //! \brief Releases resources if the handle is valid. 124240116Smarcel //! 125240116Smarcel //! If the file handle is valid, the destructor closes it. 126240116Smarcel //! 127240116Smarcel //! \see is_valid() 128240116Smarcel //! 129240116Smarcel ~file_handle(void); 130240116Smarcel 131240116Smarcel //! 132240116Smarcel //! \brief Assignment operator; invalidates the source handle. 133240116Smarcel //! 134240116Smarcel //! This assignment operator transfers ownership of the RHS file 135240116Smarcel //! handle to the LHS one, effectively invalidating the source file 136240116Smarcel //! handle. This avoids having two live \a file_handle objects 137240116Smarcel //! referring to the same native file handle. The source file 138240116Smarcel //! handle need not be valid in the name of simplicity. 139240116Smarcel //! 140240116Smarcel //! \post The RHS file handle is invalid. 141240116Smarcel //! \post The LHS file handle owns RHS' native file handle. 142240116Smarcel //! \return A reference to the LHS file handle. 143240116Smarcel //! 144240116Smarcel file_handle& operator=(const file_handle& fh); 145240116Smarcel 146240116Smarcel //! 147240116Smarcel //! \brief Checks whether the file handle is valid or not. 148240116Smarcel //! 149240116Smarcel //! Returns a boolean indicating whether the file handle is valid or 150240116Smarcel //! not. If the file handle is invalid, no other applications can be 151240116Smarcel //! executed other than the destructor. 152240116Smarcel //! 153240116Smarcel //! \return True if the file handle is valid; false otherwise. 154240116Smarcel //! 155240116Smarcel bool is_valid(void) const; 156240116Smarcel 157240116Smarcel //! 158240116Smarcel //! \brief Closes the file handle. 159240116Smarcel //! 160240116Smarcel //! Explicitly closes the file handle, which must be valid. Upon 161240116Smarcel //! exit, the handle is not valid any more. 162240116Smarcel //! 163240116Smarcel //! \pre The file handle is valid. 164240116Smarcel //! \post The file handle is invalid. 165240116Smarcel //! \post The native file handle is closed. 166240116Smarcel //! 167240116Smarcel void close(void); 168240116Smarcel 169240116Smarcel //! 170240116Smarcel //! \brief Reclaims ownership of the native file handle. 171240116Smarcel //! 172240116Smarcel //! Explicitly reclaims ownership of the native file handle contained 173240116Smarcel //! in the \a file_handle object, returning the native file handle. 174240116Smarcel //! The caller is responsible of closing it later on. 175240116Smarcel //! 176240116Smarcel //! \pre The file handle is valid. 177240116Smarcel //! \post The file handle is invalid. 178240116Smarcel //! \return The native file handle. 179240116Smarcel //! 180240116Smarcel handle_type disown(void); 181240116Smarcel 182240116Smarcel //! 183240116Smarcel //! \brief Gets the native file handle. 184240116Smarcel //! 185240116Smarcel //! Returns the native file handle for the \a file_handle object. 186240116Smarcel //! The caller can issue any operation on it except closing it. 187240116Smarcel //! If closing is required, disown() shall be used. 188240116Smarcel //! 189240116Smarcel //! \pre The file handle is valid. 190240116Smarcel //! \return The native file handle. 191240116Smarcel //! 192240116Smarcel handle_type get(void) const; 193240116Smarcel 194240116Smarcel //! 195240116Smarcel //! \brief Changes the native file handle to the given one. 196240116Smarcel //! 197240116Smarcel //! Given a new native file handle \a h, this operation assigns this 198240116Smarcel //! handle to the current object, closing its old native file handle. 199240116Smarcel //! In other words, it first calls dup2() to remap the old handle to 200240116Smarcel //! the new one and then closes the old handle. 201240116Smarcel //! 202240116Smarcel //! If \a h matches the current value of the handle, this is a no-op. 203240116Smarcel //! This is done for simplicity, to avoid the caller having to check 204240116Smarcel //! this condition on its own. 205240116Smarcel //! 206240116Smarcel //! If \a h is open, it is automatically closed by dup2(). 207240116Smarcel //! 208240116Smarcel //! This operation is only available in POSIX systems. 209240116Smarcel //! 210240116Smarcel //! \pre The file handle is valid. 211240116Smarcel //! \pre The native file handle \a h is valid; i.e., it must be 212240116Smarcel //! closeable. 213240116Smarcel //! \post The file handle's native file handle is \a h. 214240116Smarcel //! \throw system_error If the internal remapping operation fails. 215240116Smarcel //! 216240116Smarcel void posix_remap(handle_type h); 217240116Smarcel 218240116Smarcelprivate: 219240116Smarcel //! 220240116Smarcel //! \brief Internal handle value. 221240116Smarcel //! 222240116Smarcel //! This variable holds the native handle value for the file handle 223240116Smarcel //! hold by this object. It is interesting to note that this needs 224240116Smarcel //! to be mutable because the copy constructor and the assignment 225240116Smarcel //! operator invalidate the source object. 226240116Smarcel //! 227240116Smarcel mutable handle_type m_handle; 228240116Smarcel 229240116Smarcel //! 230240116Smarcel //! \brief Constant function representing an invalid handle value. 231240116Smarcel //! 232240116Smarcel //! Returns the platform-specific handle value that represents an 233240116Smarcel //! invalid handle. This is a constant function rather than a regular 234240116Smarcel //! constant because, in the latter case, we cannot define it under 235240116Smarcel //! Win32 due to the value being of a complex type. 236240116Smarcel //! 237240116Smarcel static handle_type invalid_value(void); 238240116Smarcel}; 239240116Smarcel 240240116Smarcel// ------------------------------------------------------------------------ 241240116Smarcel// The "systembuf" class. 242240116Smarcel// ------------------------------------------------------------------------ 243240116Smarcel 244240116Smarcel//! 245240116Smarcel//! \brief std::streambuf implementation for system file handles. 246240116Smarcel//! 247240116Smarcel//! systembuf provides a std::streambuf implementation for system file 248240116Smarcel//! handles. Contrarywise to file_handle, this class does \b not take 249240116Smarcel//! ownership of the native file handle; this should be taken care of 250240116Smarcel//! somewhere else. 251240116Smarcel//! 252240116Smarcel//! This class follows the expected semantics of a std::streambuf object. 253240116Smarcel//! However, it is not copyable to avoid introducing inconsistences with 254240116Smarcel//! the on-disk file and the in-memory buffers. 255240116Smarcel//! 256240116Smarcelclass systembuf : 257240116Smarcel public std::streambuf, atf::utils::noncopyable 258240116Smarcel{ 259240116Smarcelpublic: 260240116Smarcel typedef int handle_type; 261240116Smarcel 262240116Smarcel //! 263240116Smarcel //! \brief Constructs a new systembuf for the given file handle. 264240116Smarcel //! 265240116Smarcel //! This constructor creates a new systembuf object that reads or 266240116Smarcel //! writes data from/to the \a h native file handle. This handle 267240116Smarcel //! is \b not owned by the created systembuf object; the code 268240116Smarcel //! should take care of it externally. 269240116Smarcel //! 270240116Smarcel //! This class buffers input and output; the buffer size may be 271240116Smarcel //! tuned through the \a bufsize parameter, which defaults to 8192 272240116Smarcel //! bytes. 273240116Smarcel //! 274240116Smarcel //! \see pistream. 275240116Smarcel //! 276240116Smarcel explicit systembuf(handle_type h, std::size_t bufsize = 8192); 277240116Smarcel ~systembuf(void); 278240116Smarcel 279240116Smarcelprivate: 280240116Smarcel //! 281240116Smarcel //! \brief Native file handle used by the systembuf object. 282240116Smarcel //! 283240116Smarcel handle_type m_handle; 284240116Smarcel 285240116Smarcel //! 286240116Smarcel //! \brief Internal buffer size used during read and write operations. 287240116Smarcel //! 288240116Smarcel std::size_t m_bufsize; 289240116Smarcel 290240116Smarcel //! 291240116Smarcel //! \brief Internal buffer used during read operations. 292240116Smarcel //! 293240116Smarcel char* m_read_buf; 294240116Smarcel 295240116Smarcel //! 296240116Smarcel //! \brief Internal buffer used during write operations. 297240116Smarcel //! 298240116Smarcel char* m_write_buf; 299240116Smarcel 300240116Smarcelprotected: 301240116Smarcel //! 302240116Smarcel //! \brief Reads new data from the native file handle. 303240116Smarcel //! 304240116Smarcel //! This operation is called by input methods when there are no more 305240116Smarcel //! data in the input buffer. The function fills the buffer with new 306240116Smarcel //! data, if available. 307240116Smarcel //! 308240116Smarcel //! \pre All input positions are exhausted (gptr() >= egptr()). 309240116Smarcel //! \post The input buffer has new data, if available. 310240116Smarcel //! \returns traits_type::eof() if a read error occurrs or there are 311240116Smarcel //! no more data to be read. Otherwise returns 312240116Smarcel //! traits_type::to_int_type(*gptr()). 313240116Smarcel //! 314240116Smarcel virtual int_type underflow(void); 315240116Smarcel 316240116Smarcel //! 317240116Smarcel //! \brief Makes room in the write buffer for additional data. 318240116Smarcel //! 319240116Smarcel //! This operation is called by output methods when there is no more 320240116Smarcel //! space in the output buffer to hold a new element. The function 321240116Smarcel //! first flushes the buffer's contents to disk and then clears it to 322240116Smarcel //! leave room for more characters. The given \a c character is 323240116Smarcel //! stored at the beginning of the new space. 324240116Smarcel //! 325240116Smarcel //! \pre All output positions are exhausted (pptr() >= epptr()). 326240116Smarcel //! \post The output buffer has more space if no errors occurred 327240116Smarcel //! during the write to disk. 328240116Smarcel //! \post *(pptr() - 1) is \a c. 329240116Smarcel //! \returns traits_type::eof() if a write error occurrs. Otherwise 330240116Smarcel //! returns traits_type::not_eof(c). 331240116Smarcel //! 332240116Smarcel virtual int_type overflow(int c); 333240116Smarcel 334240116Smarcel //! 335240116Smarcel //! \brief Flushes the output buffer to disk. 336240116Smarcel //! 337240116Smarcel //! Synchronizes the systembuf buffers with the contents of the file 338240116Smarcel //! associated to this object through the native file handle. The 339240116Smarcel //! output buffer is flushed to disk and cleared to leave new room 340240116Smarcel //! for more data. 341240116Smarcel //! 342240116Smarcel //! \returns 0 on success, -1 if an error occurred. 343240116Smarcel //! 344240116Smarcel virtual int sync(void); 345240116Smarcel}; 346240116Smarcel 347240116Smarcel// ------------------------------------------------------------------------ 348240116Smarcel// The "pistream" class. 349240116Smarcel// ------------------------------------------------------------------------ 350240116Smarcel 351240116Smarcel//! 352240116Smarcel//! \brief Child process' output stream. 353240116Smarcel//! 354240116Smarcel//! The pistream class represents an output communication channel with the 355240116Smarcel//! child process. The child process writes data to this stream and the 356240116Smarcel//! parent process can read it through the pistream object. In other 357240116Smarcel//! words, from the child's point of view, the communication channel is an 358240116Smarcel//! output one, but from the parent's point of view it is an input one; 359240116Smarcel//! hence the confusing pistream name. 360240116Smarcel//! 361240116Smarcel//! pistream objects cannot be copied because they own the file handle 362240116Smarcel//! they use to communicate with the child and because they buffer data 363240116Smarcel//! that flows through the communication channel. 364240116Smarcel//! 365240116Smarcel//! A pistream object behaves as a std::istream stream in all senses. 366240116Smarcel//! The class is only provided because it must provide a method to let 367240116Smarcel//! the caller explicitly close the communication channel. 368240116Smarcel//! 369240116Smarcel//! \remark <b>Blocking remarks</b>: Functions that read data from this 370240116Smarcel//! stream can block if the associated file handle blocks during the read. 371240116Smarcel//! As this class is used to communicate with child processes through 372240116Smarcel//! anonymous pipes, the most typical blocking condition happens when the 373240116Smarcel//! child has no more data to send to the pipe's system buffer. When 374240116Smarcel//! this happens, the buffer eventually empties and the system blocks 375240116Smarcel//! until the writer generates some data. 376240116Smarcel//! 377240116Smarcelclass pistream : 378240116Smarcel public std::istream, utils::noncopyable 379240116Smarcel{ 380240116Smarcel //! 381240116Smarcel //! \brief The systembuf object used to manage this stream's data. 382240116Smarcel //! 383240116Smarcel systembuf m_systembuf; 384240116Smarcel 385240116Smarcelpublic: 386240116Smarcel //! 387240116Smarcel //! \brief Creates a new process' output stream. 388240116Smarcel //! 389240116Smarcel //! Given a file handle, this constructor creates a new pistream 390240116Smarcel //! object that owns the given file handle \a fh. Ownership of 391240116Smarcel //! \a fh is transferred to the created pistream object. 392240116Smarcel //! 393240116Smarcel //! \pre \a fh is valid. 394240116Smarcel //! \post \a fh is invalid. 395240116Smarcel //! \post The new pistream object owns \a fh. 396240116Smarcel //! 397240116Smarcel explicit pistream(const int); 398240116Smarcel}; 399240116Smarcel 400240116Smarcel// ------------------------------------------------------------------------ 401240116Smarcel// The "muxer" class. 402240116Smarcel// ------------------------------------------------------------------------ 403240116Smarcel 404240116Smarcelclass muxer : utils::noncopyable { 405240116Smarcel const int* m_fds; 406240116Smarcel const size_t m_nfds; 407240116Smarcel 408240116Smarcel const size_t m_bufsize; 409240116Smarcel atf::utils::auto_array< std::string > m_buffers; 410240116Smarcel 411240116Smarcelprotected: 412240116Smarcel virtual void line_callback(const size_t, const std::string&) = 0; 413240116Smarcel 414240116Smarcel size_t read_one(const size_t, const int, std::string&, const bool); 415240116Smarcel 416240116Smarcelpublic: 417240116Smarcel muxer(const int*, const size_t, const size_t bufsize = 1024); 418240116Smarcel virtual ~muxer(void); 419240116Smarcel 420240116Smarcel void mux(volatile const bool&); 421240116Smarcel void flush(void); 422240116Smarcel}; 423240116Smarcel 424240116Smarcel} // namespace atf_run 425240116Smarcel} // namespace atf 426240116Smarcel 427240116Smarcel#endif // !defined(_ATF_RUN_IO_HPP_) 428