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(HAVE_CONFIG_H) 31#include "bconfig.h" 32#endif 33 34#include <cstdarg> 35#include <cstdio> 36#include <cstring> 37#include <new> 38 39extern "C" { 40#include "../../atf-c/error.h" 41}; 42 43#include "exceptions.hpp" 44#include "sanity.hpp" 45 46// ------------------------------------------------------------------------ 47// The "system_error" type. 48// ------------------------------------------------------------------------ 49 50atf::system_error::system_error(const std::string& who, 51 const std::string& message, 52 int sys_err) : 53 std::runtime_error(who + ": " + message), 54 m_sys_err(sys_err) 55{ 56} 57 58atf::system_error::~system_error(void) 59 throw() 60{ 61} 62 63int 64atf::system_error::code(void) 65 const 66 throw() 67{ 68 return m_sys_err; 69} 70 71const char* 72atf::system_error::what(void) 73 const 74 throw() 75{ 76 try { 77 if (m_message.length() == 0) { 78 m_message = std::string(std::runtime_error::what()) + ": "; 79 m_message += ::strerror(m_sys_err); 80 } 81 82 return m_message.c_str(); 83 } catch (...) { 84 return "Unable to format system_error message"; 85 } 86} 87 88// ------------------------------------------------------------------------ 89// Free functions. 90// ------------------------------------------------------------------------ 91 92static 93void 94throw_libc_error(atf_error_t err) 95{ 96 PRE(atf_error_is(err, "libc")); 97 98 const int ecode = atf_libc_error_code(err); 99 const std::string msg = atf_libc_error_msg(err); 100 atf_error_free(err); 101 throw atf::system_error("XXX", msg, ecode); 102} 103 104static 105void 106throw_no_memory_error(atf_error_t err) 107{ 108 PRE(atf_error_is(err, "no_memory")); 109 110 atf_error_free(err); 111 throw std::bad_alloc(); 112} 113 114static 115void 116throw_unknown_error(atf_error_t err) 117{ 118 PRE(atf_is_error(err)); 119 120 static char buf[4096]; 121 atf_error_format(err, buf, sizeof(buf)); 122 atf_error_free(err); 123 throw std::runtime_error(buf); 124} 125 126void 127atf::throw_atf_error(atf_error_t err) 128{ 129 static struct handler { 130 const char* m_name; 131 void (*m_func)(atf_error_t); 132 } handlers[] = { 133 { "libc", throw_libc_error }, 134 { "no_memory", throw_no_memory_error }, 135 { NULL, throw_unknown_error }, 136 }; 137 138 PRE(atf_is_error(err)); 139 140 handler* h = handlers; 141 while (h->m_name != NULL) { 142 if (atf_error_is(err, h->m_name)) { 143 h->m_func(err); 144 UNREACHABLE; 145 } else 146 h++; 147 } 148 // XXX: I'm not sure that raising an "unknown" error is a wise thing 149 // to do here. The C++ binding is supposed to have feature parity 150 // with the C one, so all possible errors raised by the C library 151 // should have their counterpart in the C++ library. Still, removing 152 // this will require some code auditing that I can't afford at the 153 // moment. 154 INV(h->m_name == NULL && h->m_func != NULL); 155 h->m_func(err); 156 UNREACHABLE; 157} 158