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