Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / atf / dist / atf-c++ / io.cpp
blobdfd9c18fd1c93a785f2b498cc6bcf3d7bba38f53
1 //
2 // Automated Testing Framework (atf)
3 //
4 // Copyright (c) 2007, 2008 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.
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 extern "C" {
31 #include <unistd.h>
34 #include <cerrno>
36 extern "C" {
37 #include "atf-c/error.h"
38 #include "atf-c/io.h"
41 #include "atf-c++/exceptions.hpp"
42 #include "atf-c++/io.hpp"
43 #include "atf-c++/sanity.hpp"
45 namespace impl = atf::io;
46 #define IMPL_NAME "atf::io"
48 // ------------------------------------------------------------------------
49 // The "file_handle" class.
50 // ------------------------------------------------------------------------
52 impl::file_handle::file_handle(void) :
53 m_handle(invalid_value())
57 impl::file_handle::file_handle(handle_type h) :
58 m_handle(h)
60 PRE(m_handle != invalid_value());
63 impl::file_handle::file_handle(const file_handle& fh) :
64 m_handle(fh.m_handle)
66 fh.m_handle = invalid_value();
69 impl::file_handle::~file_handle(void)
71 if (is_valid())
72 close();
75 impl::file_handle&
76 impl::file_handle::operator=(const file_handle& fh)
78 m_handle = fh.m_handle;
79 fh.m_handle = invalid_value();
81 return *this;
84 bool
85 impl::file_handle::is_valid(void)
86 const
88 return m_handle != invalid_value();
91 void
92 impl::file_handle::close(void)
94 PRE(is_valid());
96 ::close(m_handle);
98 m_handle = invalid_value();
101 impl::file_handle::handle_type
102 impl::file_handle::disown(void)
104 PRE(is_valid());
106 handle_type h = m_handle;
107 m_handle = invalid_value();
108 return h;
111 impl::file_handle::handle_type
112 impl::file_handle::get(void)
113 const
115 PRE(is_valid());
117 return m_handle;
120 void
121 impl::file_handle::posix_remap(handle_type h)
123 PRE(is_valid());
125 if (m_handle == h)
126 return;
128 if (::dup2(m_handle, h) == -1)
129 throw system_error(IMPL_NAME "::file_handle::posix_remap",
130 "dup2(2) failed", errno);
132 if (::close(m_handle) == -1) {
133 ::close(h);
134 throw system_error(IMPL_NAME "::file_handle::posix_remap",
135 "close(2) failed", errno);
138 m_handle = h;
141 impl::file_handle::handle_type
142 impl::file_handle::invalid_value(void)
144 return -1;
147 // ------------------------------------------------------------------------
148 // The "systembuf" class.
149 // ------------------------------------------------------------------------
151 impl::systembuf::systembuf(handle_type h, std::size_t bufsize) :
152 m_handle(h),
153 m_bufsize(bufsize),
154 m_read_buf(NULL),
155 m_write_buf(NULL)
157 PRE(m_handle >= 0);
158 PRE(m_bufsize > 0);
160 try {
161 m_read_buf = new char[bufsize];
162 m_write_buf = new char[bufsize];
163 } catch (...) {
164 if (m_read_buf != NULL)
165 delete [] m_read_buf;
166 if (m_write_buf != NULL)
167 delete [] m_write_buf;
168 throw;
171 setp(m_write_buf, m_write_buf + m_bufsize);
174 impl::systembuf::~systembuf(void)
176 sync(); // XXX Unsure if this is correct. But seems to be needed.
177 delete [] m_read_buf;
178 delete [] m_write_buf;
181 impl::systembuf::int_type
182 impl::systembuf::underflow(void)
184 PRE(gptr() >= egptr());
186 bool ok;
187 ssize_t cnt = ::read(m_handle, m_read_buf, m_bufsize);
188 ok = (cnt != -1 && cnt != 0);
190 if (!ok)
191 return traits_type::eof();
192 else {
193 setg(m_read_buf, m_read_buf, m_read_buf + cnt);
194 return traits_type::to_int_type(*gptr());
198 impl::systembuf::int_type
199 impl::systembuf::overflow(int c)
201 PRE(pptr() >= epptr());
202 if (sync() == -1)
203 return traits_type::eof();
204 if (!traits_type::eq_int_type(c, traits_type::eof())) {
205 traits_type::assign(*pptr(), c);
206 pbump(1);
208 return traits_type::not_eof(c);
212 impl::systembuf::sync(void)
214 ssize_t cnt = pptr() - pbase();
216 bool ok;
217 ok = ::write(m_handle, pbase(), cnt) == cnt;
219 if (ok)
220 pbump(-cnt);
221 return ok ? 0 : -1;
224 // ------------------------------------------------------------------------
225 // The "pipe" class.
226 // ------------------------------------------------------------------------
228 impl::pipe::pipe(void)
230 file_handle::handle_type hs[2];
232 if (::pipe(hs) == -1)
233 throw system_error(IMPL_NAME "::pipe::pipe",
234 "pipe(2) failed", errno);
236 m_read_end = file_handle(hs[0]);
237 m_write_end = file_handle(hs[1]);
240 impl::file_handle&
241 impl::pipe::rend(void)
243 return m_read_end;
246 impl::file_handle&
247 impl::pipe::wend(void)
249 return m_write_end;
252 // ------------------------------------------------------------------------
253 // The "pistream" class.
254 // ------------------------------------------------------------------------
256 impl::pistream::pistream(impl::file_handle& fh) :
257 std::istream(NULL),
258 m_handle(fh),
259 m_systembuf(m_handle.get())
261 rdbuf(&m_systembuf);
264 void
265 impl::pistream::close(void)
267 m_handle.close();
270 impl::file_handle&
271 impl::pistream::handle(void)
273 return m_handle;
276 // ------------------------------------------------------------------------
277 // The "postream" class.
278 // ------------------------------------------------------------------------
280 impl::postream::postream(impl::file_handle& fh) :
281 std::ostream(NULL),
282 m_handle(fh),
283 m_systembuf(m_handle.get())
285 rdbuf(&m_systembuf);
288 void
289 impl::postream::close(void)
291 m_handle.close();
294 impl::file_handle&
295 impl::postream::handle(void)
297 return m_handle;
300 // ------------------------------------------------------------------------
301 // The "pollable_istream" class.
302 // ------------------------------------------------------------------------
304 impl::unbuffered_istream::unbuffered_istream(impl::file_handle& fh) :
305 m_fh(fh),
306 m_is_good(true)
310 impl::file_handle&
311 impl::unbuffered_istream::get_fh(void)
313 return m_fh;
316 bool
317 impl::unbuffered_istream::good(void)
318 const
320 return m_is_good;
323 size_t
324 impl::unbuffered_istream::read(void* buf, size_t buflen)
326 if (!m_is_good)
327 return 0;
329 ssize_t res = ::read(m_fh.get(), buf, buflen);
330 m_is_good = res > 0;
331 return res > 0 ? res : 0;
334 void
335 impl::unbuffered_istream::close(void)
337 m_is_good = false;
338 m_fh.close();
341 // ------------------------------------------------------------------------
342 // Free functions.
343 // ------------------------------------------------------------------------
345 impl::unbuffered_istream&
346 impl::getline(unbuffered_istream& uis, std::string& str)
348 str.clear();
349 char ch;
350 while (uis.read(&ch, sizeof(ch)) == sizeof(ch) && ch != '\n') {
351 if (ch != '\r')
352 str += ch;
354 return uis;
358 impl::cmp(const fs::path& p1, const fs::path& p2)
360 int r;
362 atf_error_t err = atf_io_cmp(&r, p1.c_path(), p2.c_path());
363 if (atf_is_error(err))
364 throw_atf_error(err);
366 return r;