xapian-core  1.4.27
errno_to_string.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2014,2015,2016,2021 Olly Betts
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining a copy
7  * of this software and associated documentation files (the "Software"), to
8  * deal in the Software without restriction, including without limitation the
9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10  * sell copies of the Software, and to permit persons to whom the Software is
11  * furnished to do so, subject to the following conditions:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22  * IN THE SOFTWARE.
23  */
24 
25 #include <config.h>
26 
27 #include "errno_to_string.h"
28 
29 // On Linux, sys_errlist and sys_nerr need <stdio.h>, though the man page
30 // says <errno.h>. The man page seems to match other platforms such as
31 // NetBSD, so include both headers to ensure we get them.
32 #include <errno.h>
33 // <cstring> doesn't give us strerror_r() with Sun C++ 5.9.
34 #include <string.h>
35 #if defined HAVE__SYS_ERRLIST_AND__SYS_NERR || \
36  defined HAVE_SYS_ERRLIST_AND_SYS_NERR
37 # include <stdio.h>
38 // With mingw and MSVC they're provided by <stdlib.h>.
39 # include <stdlib.h>
40 #endif
41 
42 #include "str.h"
43 
44 using namespace std;
45 
46 void
47 errno_to_string(int e, string& s)
48 {
49  // Use a thread-safe way to convert an errno value to a string if possible.
50 #ifdef HAVE_STRERRORDESC_NP
51  // GNU-specific replacement for sys_errlist and sys_nerr, added in glibc
52  // 2.32.
53  const char* desc = strerrordesc_np(e);
54  if (desc) {
55  s += desc;
56  } else {
57  s += "Unknown error ";
58  s += str(e);
59  }
60 #elif defined HAVE__SYS_ERRLIST_AND__SYS_NERR
61  // Old-style Unix fixed array of strings.
62  if (e >= 0 && e < _sys_nerr && _sys_errlist[e]) {
63  s += _sys_errlist[e];
64  } else {
65  s += "Unknown error ";
66  s += str(e);
67  }
68 #elif defined HAVE_SYS_ERRLIST_AND_SYS_NERR
69  // Old-style Unix fixed array of strings.
70  if (e >= 0 && e < sys_nerr && sys_errlist[e]) {
71  s += sys_errlist[e];
72  } else {
73  s += "Unknown error ";
74  s += str(e);
75  }
76 #elif HAVE_DECL_STRERROR_R
77  // POSIX specifies strerror_r() to provide a thread-safe way to translate
78  // an errno value to a string.
79  //
80  // Unhelpfully this requires us to pass in a buffer, but we don't know how
81  // big to make it to reliably be able to convert all possible errno values,
82  // and the implementation is permitted to return localised strings so the
83  // maximum possible length may vary depending on the current locale
84  // settings.
85  //
86  // If the buffer passed is too small, then with older glibc errno gets
87  // stomped on, so growing the buffer on error and retrying isn't a great
88  // answer. Hence we only use strerror_r() if we don't have a better
89  // alternative.
90  //
91  // Another reason to have support for alternative approaches is that
92  // strerror_r() is marked as "optional" by POSIX.
93  //
94  // A further complication is there's a GNU-specific strerror_r() with a
95  // different return value type.
96  //
97  // The strerror_r(3) man page on Linux suggests a buffer size of 1024
98  // characters, noting that glibc uses this size for strerror(). The
99  // actual longest on Linux in English is EILSEQ which needs 50 bytes.
100  char buf[1024];
101 # ifdef STRERROR_R_CHAR_P
102  // Returns char* pointing to string describing error.
103  s += strerror_r(e, buf, sizeof(buf));
104 # else
105  // XSI-compliant strerror_r returns int: 0 means success; a positive error
106  // number should be returned on error, but glibc < 2.13 returns -1 and sets
107  // errno.
108  int r = strerror_r(e, buf, sizeof(buf));
109  if (r == 0) {
110  s += buf;
111  } else {
112  s += "Unknown error ";
113  s += str(e);
114  }
115 # endif
116 #else
117  // Not thread safe.
118  //
119  // We can assume the return value is non-NULL because "C99 and POSIX.1-2008
120  // require the return value to be non-NULL" and we require C++11 which
121  // incorporates C99.
122  s += strerror(e);
123 #endif
124 }
Convert errno value to std::string, thread-safe if possible.
STL namespace.
Convert types to std::string.
void errno_to_string(int e, string &s)
string str(int value)
Convert int to std::string.
Definition: str.cc:90