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