xapian-core  1.4.19
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 // <cstring> doesn't give us strerror_r() with Sun C++ 5.9.
30 #include <string.h>
31 #if defined HAVE__SYS_ERRLIST_AND__SYS_NERR || \
32  defined HAVE_SYS_ERRLIST_AND_SYS_NERR
33 # include <stdio.h>
34 // Under mingw, these are in stdlib.h.
35 # include <stdlib.h>
36 #endif
37 
38 #include "str.h"
39 
40 using namespace std;
41 
42 void
43 errno_to_string(int e, string& s)
44 {
45  // Use a thread-safe way to convert an errno value to a string if possible.
46 #ifdef HAVE_STRERRORDESC_NP
47  // GNU-specific replacement for sys_errlist and sys_nerr, added in glibc
48  // 2.32.
49  const char* desc = strerrordesc_np(e);
50  if (desc) {
51  s += desc;
52  } else {
53  s += "Unknown error ";
54  s += str(e);
55  }
56 #elif defined HAVE__SYS_ERRLIST_AND__SYS_NERR
57  // Old-style Unix fixed array of strings.
58  if (e >= 0 && e < _sys_nerr && _sys_errlist[e]) {
59  s += _sys_errlist[e];
60  } else {
61  s += "Unknown error ";
62  s += str(e);
63  }
64 #elif defined HAVE_SYS_ERRLIST_AND_SYS_NERR
65  // Old-style Unix fixed array of strings.
66  if (e >= 0 && e < sys_nerr && sys_errlist[e]) {
67  s += sys_errlist[e];
68  } else {
69  s += "Unknown error ";
70  s += str(e);
71  }
72 #elif defined HAVE_STRERROR_R
73  // POSIX specifies strerror_r() to provide a thread-safe way to translate
74  // an errno value to a string.
75  //
76  // Unhelpfully this requires us to pass in a buffer, but we don't know how
77  // big to make it to reliably be able to convert all possible errno values,
78  // and the implementation is permitted to return localised strings so the
79  // maximum possible length may vary depending on the current locale
80  // settings.
81  //
82  // If the buffer passed is too small, then with older glibc errno gets
83  // stomped on, so growing the buffer on error and retrying isn't a great
84  // answer. Hence we only use strerror_r() if we don't have a better
85  // alternative.
86  //
87  // Another reason to have support for alternative approaches is that
88  // strerror_r() is marked as "optional" by POSIX.
89  //
90  // A further complication is there's a GNU-specific strerror_r() with a
91  // different return value type.
92  //
93  // The strerror_r(3) man page on Linux suggests a buffer size of 1024
94  // characters, noting that glibc uses this size for strerror(). The
95  // actual longest on Linux in English is EILSEQ which needs 50 bytes.
96  char buf[1024];
97 # ifdef STRERROR_R_CHAR_P
98  // Returns char* pointing to string describing error.
99  s += strerror_r(e, buf, sizeof(buf));
100 # else
101  // XSI-compliant strerror_r returns int: 0 means success; a positive error
102  // number should be returned on error, but glibc < 2.13 returns -1 and sets
103  // errno.
104  int r = strerror_r(e, buf, sizeof(buf));
105  if (r == 0) {
106  s += buf;
107  } else {
108  s += "Unknown error ";
109  s += str(e);
110  }
111 # endif
112 #else
113  // Not thread safe.
114  //
115  // We can assume the return value is non-NULL because "C99 and POSIX.1-2008
116  // require the return value to be non-NULL" and we require C++11 which
117  // incorporates C99.
118  s += strerror(e);
119 #endif
120 }
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