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 39 extern "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 50 atf::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 58 atf::system_error::~system_error(void) 59 throw() 60 { 61 } 62 63 int 64 atf::system_error::code(void) 65 const 66 throw() 67 { 68 return m_sys_err; 69 } 70 71 const char* 72 atf::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 92 static 93 void 94 throw_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 104 static 105 void 106 throw_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 114 static 115 void 116 throw_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 126 void 127 atf::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