1 /*
2  * Copyright (C) 2009 Tommi Maekitalo
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * As a special exception, you may use this file as part of a free
10  * software library without restriction. Specifically, if other files
11  * instantiate templates or use macros or inline functions from this
12  * file, or you compile this file and link it with other files to
13  * produce an executable, this file does not by itself cause the
14  * resulting executable to be covered by the GNU General Public
15  * License. This exception does not however invalidate any other
16  * reasons why the executable file might be covered by the GNU Library
17  * General Public License.
18  *
19  * This library is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22  * Lesser General Public License for more details.
23  *
24  * You should have received a copy of the GNU Lesser General Public
25  * License along with this library; if not, write to the Free Software
26  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
27  *
28  */
29 
30 #include "error.h"
31 #include <sstream>
32 #include <vector>
33 #include <string.h>
34 
35 namespace cxxtools
36 {
37 
38 namespace
39 {
40     // XSI compliant strerror_r
errorOut(int (* errfn)(int,char *,size_t),std::ostream & out,int errnum)41     inline void errorOut(int (*errfn)(int, char*, size_t), std::ostream& out, int errnum)
42     {
43         std::vector<char> buffer(512);
44         while (errfn(errnum, &buffer[0], buffer.size()) != 0)
45         {
46             if (errno != ERANGE)
47             {
48                 out << "Unknown error " << errnum;
49                 return;
50             }
51 
52             buffer.resize(buffer.size() * 2);
53         }
54 
55         out << &buffer[0];
56     }
57 
58     // GNU specific strerror_r
errorOut(char * (* errfn)(int,char *,size_t),std::ostream & out,int errnum)59     inline void errorOut(char* (*errfn)(int, char*, size_t), std::ostream& out, int errnum)
60     {
61         std::vector<char> buffer(512);
62         while (true)
63         {
64             char* f = errfn(errnum, &buffer[0], buffer.size());
65             if (f != &buffer[0])
66             {
67                 out << f;
68                 return;
69             }
70 
71             if (strlen(&buffer[0]) < buffer.size() - 1)
72                 break;
73 
74             buffer.resize(buffer.size() * 2);
75         }
76 
77         out << &buffer[0];
78     }
79 
errorOut(std::ostream & out,int errnum)80     inline void errorOut(std::ostream& out, int errnum)
81     {
82       errorOut(strerror_r, out, errnum);
83     }
84 }
85 
getErrnoString(int errnum)86 std::string getErrnoString(int errnum)
87 {
88     std::ostringstream msg;
89     msg << "errno " << errnum << ": ";
90     errorOut(msg, errnum);
91     return msg.str();
92 }
93 
getErrnoString(int errnum,const char * fn)94 std::string getErrnoString(int errnum, const char* fn)
95 {
96     if (errnum != 0)
97     {
98         std::ostringstream msg;
99         msg << fn << ": errno " << errnum << ": ";
100         errorOut(msg, errnum);
101         return msg.str();
102     }
103     else
104         return fn;
105 }
106 
107 }
108