2 // Automated Testing Framework (atf)
4 // Copyright (c) 2007 The NetBSD Foundation, Inc.
5 // All rights reserved.
7 // Redistribution and use in source and binary forms, with or without
8 // modification, are permitted provided that the following conditions
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.
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.
30 #if !defined(TOOLS_IO_HPP)
37 #include "auto_array.hpp"
43 // ------------------------------------------------------------------------
44 // The "file_handle" class.
45 // ------------------------------------------------------------------------
48 //! \brief Simple RAII model for system file handles.
50 //! The \a file_handle class is a simple RAII model for native system file
51 //! handles. This class wraps one of such handles grabbing its ownership,
52 //! and automaticaly closes it upon destruction. It is basically used
53 //! inside the library to avoid leaking open file handles, shall an
54 //! unexpected execution trace occur.
56 //! A \a file_handle object can be copied but doing so invalidates the
57 //! source object. There can only be a single valid \a file_handle object
58 //! for a given system file handle. This is similar to std::auto_ptr\<\>'s
61 //! This class also provides some convenience methods to issue special file
62 //! operations under their respective platforms.
68 //! \brief Opaque name for the native handle type.
70 //! Each operating system identifies file handles using a specific type.
71 //! The \a handle_type type is used to transparently refer to file
72 //! handles regarless of the operating system in which this class is
75 //! If this class is used in a POSIX system, \a NativeSystemHandle is
76 //! an integer type while it is a \a HANDLE in a Win32 system.
78 typedef int handle_type
;
81 //! \brief Constructs an invalid file handle.
83 //! This constructor creates a new \a file_handle object that represents
84 //! an invalid file handle. An invalid file handle can be copied but
85 //! cannot be manipulated in any way (except checking for its validity).
92 //! \brief Constructs a new file handle from a native file handle.
94 //! This constructor creates a new \a file_handle object that takes
95 //! ownership of the given \a h native file handle. The user must not
96 //! close \a h on his own during the lifetime of the new object.
97 //! Ownership can be reclaimed using disown().
99 //! \pre The native file handle must be valid; a close operation must
104 file_handle(handle_type h
);
107 //! \brief Copy constructor; invalidates the source handle.
109 //! This copy constructor creates a new file handle from a given one.
110 //! Ownership of the native file handle is transferred to the new
111 //! object, effectively invalidating the source file handle. This
112 //! avoids having two live \a file_handle objects referring to the
113 //! same native file handle. The source file handle need not be
114 //! valid in the name of simplicity.
116 //! \post The source file handle is invalid.
117 //! \post The new file handle owns the source's native file handle.
119 file_handle(const file_handle
& fh
);
122 //! \brief Releases resources if the handle is valid.
124 //! If the file handle is valid, the destructor closes it.
131 //! \brief Assignment operator; invalidates the source handle.
133 //! This assignment operator transfers ownership of the RHS file
134 //! handle to the LHS one, effectively invalidating the source file
135 //! handle. This avoids having two live \a file_handle objects
136 //! referring to the same native file handle. The source file
137 //! handle need not be valid in the name of simplicity.
139 //! \post The RHS file handle is invalid.
140 //! \post The LHS file handle owns RHS' native file handle.
141 //! \return A reference to the LHS file handle.
143 file_handle
& operator=(const file_handle
& fh
);
146 //! \brief Checks whether the file handle is valid or not.
148 //! Returns a boolean indicating whether the file handle is valid or
149 //! not. If the file handle is invalid, no other applications can be
150 //! executed other than the destructor.
152 //! \return True if the file handle is valid; false otherwise.
154 bool is_valid(void) const;
157 //! \brief Closes the file handle.
159 //! Explicitly closes the file handle, which must be valid. Upon
160 //! exit, the handle is not valid any more.
162 //! \pre The file handle is valid.
163 //! \post The file handle is invalid.
164 //! \post The native file handle is closed.
169 //! \brief Reclaims ownership of the native file handle.
171 //! Explicitly reclaims ownership of the native file handle contained
172 //! in the \a file_handle object, returning the native file handle.
173 //! The caller is responsible of closing it later on.
175 //! \pre The file handle is valid.
176 //! \post The file handle is invalid.
177 //! \return The native file handle.
179 handle_type
disown(void);
182 //! \brief Gets the native file handle.
184 //! Returns the native file handle for the \a file_handle object.
185 //! The caller can issue any operation on it except closing it.
186 //! If closing is required, disown() shall be used.
188 //! \pre The file handle is valid.
189 //! \return The native file handle.
191 handle_type
get(void) const;
194 //! \brief Changes the native file handle to the given one.
196 //! Given a new native file handle \a h, this operation assigns this
197 //! handle to the current object, closing its old native file handle.
198 //! In other words, it first calls dup2() to remap the old handle to
199 //! the new one and then closes the old handle.
201 //! If \a h matches the current value of the handle, this is a no-op.
202 //! This is done for simplicity, to avoid the caller having to check
203 //! this condition on its own.
205 //! If \a h is open, it is automatically closed by dup2().
207 //! This operation is only available in POSIX systems.
209 //! \pre The file handle is valid.
210 //! \pre The native file handle \a h is valid; i.e., it must be
212 //! \post The file handle's native file handle is \a h.
213 //! \throw system_error If the internal remapping operation fails.
215 void posix_remap(handle_type h
);
219 //! \brief Internal handle value.
221 //! This variable holds the native handle value for the file handle
222 //! hold by this object. It is interesting to note that this needs
223 //! to be mutable because the copy constructor and the assignment
224 //! operator invalidate the source object.
226 mutable handle_type m_handle
;
229 //! \brief Constant function representing an invalid handle value.
231 //! Returns the platform-specific handle value that represents an
232 //! invalid handle. This is a constant function rather than a regular
233 //! constant because, in the latter case, we cannot define it under
234 //! Win32 due to the value being of a complex type.
236 static handle_type
invalid_value(void);
239 // ------------------------------------------------------------------------
240 // The "systembuf" class.
241 // ------------------------------------------------------------------------
244 //! \brief std::streambuf implementation for system file handles.
246 //! systembuf provides a std::streambuf implementation for system file
247 //! handles. Contrarywise to file_handle, this class does \b not take
248 //! ownership of the native file handle; this should be taken care of
251 //! This class follows the expected semantics of a std::streambuf object.
252 //! However, it is not copyable to avoid introducing inconsistences with
253 //! the on-disk file and the in-memory buffers.
255 class systembuf
: public std::streambuf
258 systembuf(const systembuf
&);
259 systembuf
& operator=(const systembuf
&);
262 typedef int handle_type
;
265 //! \brief Constructs a new systembuf for the given file handle.
267 //! This constructor creates a new systembuf object that reads or
268 //! writes data from/to the \a h native file handle. This handle
269 //! is \b not owned by the created systembuf object; the code
270 //! should take care of it externally.
272 //! This class buffers input and output; the buffer size may be
273 //! tuned through the \a bufsize parameter, which defaults to 8192
278 explicit systembuf(handle_type h
, std::size_t bufsize
= 8192);
283 //! \brief Native file handle used by the systembuf object.
285 handle_type m_handle
;
288 //! \brief Internal buffer size used during read and write operations.
290 std::size_t m_bufsize
;
293 //! \brief Internal buffer used during read operations.
298 //! \brief Internal buffer used during write operations.
304 //! \brief Reads new data from the native file handle.
306 //! This operation is called by input methods when there are no more
307 //! data in the input buffer. The function fills the buffer with new
308 //! data, if available.
310 //! \pre All input positions are exhausted (gptr() >= egptr()).
311 //! \post The input buffer has new data, if available.
312 //! \returns traits_type::eof() if a read error occurrs or there are
313 //! no more data to be read. Otherwise returns
314 //! traits_type::to_int_type(*gptr()).
316 virtual int_type
underflow(void);
319 //! \brief Makes room in the write buffer for additional data.
321 //! This operation is called by output methods when there is no more
322 //! space in the output buffer to hold a new element. The function
323 //! first flushes the buffer's contents to disk and then clears it to
324 //! leave room for more characters. The given \a c character is
325 //! stored at the beginning of the new space.
327 //! \pre All output positions are exhausted (pptr() >= epptr()).
328 //! \post The output buffer has more space if no errors occurred
329 //! during the write to disk.
330 //! \post *(pptr() - 1) is \a c.
331 //! \returns traits_type::eof() if a write error occurrs. Otherwise
332 //! returns traits_type::not_eof(c).
334 virtual int_type
overflow(int c
);
337 //! \brief Flushes the output buffer to disk.
339 //! Synchronizes the systembuf buffers with the contents of the file
340 //! associated to this object through the native file handle. The
341 //! output buffer is flushed to disk and cleared to leave new room
344 //! \returns 0 on success, -1 if an error occurred.
346 virtual int sync(void);
349 // ------------------------------------------------------------------------
350 // The "pistream" class.
351 // ------------------------------------------------------------------------
354 //! \brief Child process' output stream.
356 //! The pistream class represents an output communication channel with the
357 //! child process. The child process writes data to this stream and the
358 //! parent process can read it through the pistream object. In other
359 //! words, from the child's point of view, the communication channel is an
360 //! output one, but from the parent's point of view it is an input one;
361 //! hence the confusing pistream name.
363 //! pistream objects cannot be copied because they own the file handle
364 //! they use to communicate with the child and because they buffer data
365 //! that flows through the communication channel.
367 //! A pistream object behaves as a std::istream stream in all senses.
368 //! The class is only provided because it must provide a method to let
369 //! the caller explicitly close the communication channel.
371 //! \remark <b>Blocking remarks</b>: Functions that read data from this
372 //! stream can block if the associated file handle blocks during the read.
373 //! As this class is used to communicate with child processes through
374 //! anonymous pipes, the most typical blocking condition happens when the
375 //! child has no more data to send to the pipe's system buffer. When
376 //! this happens, the buffer eventually empties and the system blocks
377 //! until the writer generates some data.
379 class pistream
: public std::istream
382 pistream(const pistream
&);
383 pistream
& operator=(const pistream
&);
386 //! \brief The systembuf object used to manage this stream's data.
388 systembuf m_systembuf
;
392 //! \brief Creates a new process' output stream.
394 //! Given a file handle, this constructor creates a new pistream
395 //! object that owns the given file handle \a fh. Ownership of
396 //! \a fh is transferred to the created pistream object.
398 //! \pre \a fh is valid.
399 //! \post \a fh is invalid.
400 //! \post The new pistream object owns \a fh.
402 explicit pistream(const int);
405 // ------------------------------------------------------------------------
406 // The "muxer" class.
407 // ------------------------------------------------------------------------
412 muxer
& operator=(const muxer
&);
417 const size_t m_bufsize
;
418 tools::auto_array
< std::string
> m_buffers
;
421 virtual void line_callback(const size_t, const std::string
&) = 0;
423 size_t read_one(const size_t, const int, std::string
&, const bool);
426 muxer(const int*, const size_t, const size_t bufsize
= 1024);
427 virtual ~muxer(void);
429 void mux(volatile const bool&);
436 #endif // !defined(TOOLS_IO_HPP)