1
/* strerror.c - Describing an error code.
2
Copyright (C) 2003 g10 Code GmbH
4
This file is part of libgpg-error.
6
libgpg-error is free software; you can redistribute it and/or
7
modify it under the terms of the GNU Lesser General Public License
8
as published by the Free Software Foundation; either version 2.1 of
9
the License, or (at your option) any later version.
11
libgpg-error is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
Lesser General Public License for more details.
16
You should have received a copy of the GNU Lesser General Public
17
License along with libgpg-error; if not, write to the Free
18
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
30
#include <gpg-error.h>
33
#include "err-codes.h"
35
/* Return a pointer to a string containing a description of the error
36
code in the error value ERR. This function is not thread-safe. */
38
gpg_strerror (gpg_error_t err)
40
gpg_err_code_t code = gpg_err_code (err);
42
if (code & GPG_ERR_SYSTEM_ERROR)
44
int no = gpg_err_code_to_errno (code);
48
code = GPG_ERR_UNKNOWN_ERRNO;
50
return dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
54
#ifdef HAVE_STRERROR_R
55
#ifdef STRERROR_R_CHAR_P
56
/* The GNU C library and probably some other systems have this weird
57
variant of strerror_r. */
59
/* Return a dynamically allocated string in *STR describing the system
60
error NO. If this call succeeds, return 1. If this call fails due
61
to a resource shortage, set *STR to NULL and return 1. If this
62
call fails because the error number is not valid, don't set *STR
65
system_strerror_r (int no, char *buf, size_t buflen)
69
errstr = strerror_r (no, buf, buflen);
72
size_t errstr_len = strlen (errstr) + 1;
73
size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
74
memcpy (buf, errstr, cpy_len);
76
return cpy_len == errstr_len ? 0 : ERANGE;
80
/* We can not tell if the buffer was large enough, but we can
81
try to make a guess. */
82
if (strlen (buf) + 1 >= buflen)
89
#else /* STRERROR_R_CHAR_P */
90
/* Now the POSIX version. */
93
system_strerror_r (int no, char *buf, size_t buflen)
95
return strerror_r (no, buf, buflen);
98
#endif /* STRERROR_R_CHAR_P */
100
#else /* HAVE_STRERROR_H */
101
/* Without strerror_r(), we can still provide a non-thread-safe
102
version. Maybe we are even lucky and the system's strerror() is
103
already thread-safe. */
106
system_strerror_r (int no, char *buf, size_t buflen)
108
char *errstr = strerror (no);
112
int saved_errno = errno;
114
if (saved_errno != EINVAL)
115
snprintf (buf, buflen, "strerror failed: %i\n", errno);
120
size_t errstr_len = strlen (errstr) + 1;
121
size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
122
memcpy (buf, errstr, cpy_len);
123
return cpy_len == errstr_len ? 0 : ERANGE;
129
/* Return the error string for ERR in the user-supplied buffer BUF of
130
size BUFLEN. This function is, in contrast to gpg_strerror,
131
thread-safe if a thread-safe strerror_r() function is provided by
132
the system. If the function succeeds, 0 is returned and BUF
133
contains the string describing the error. If the buffer was not
134
large enough, ERANGE is returned and BUF contains as much of the
135
beginning of the error string as fits into the buffer. */
137
gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen)
139
gpg_err_code_t code = gpg_err_code (err);
144
if (code & GPG_ERR_SYSTEM_ERROR)
146
int no = gpg_err_code_to_errno (code);
149
int system_err = system_strerror_r (no, buf, buflen);
151
if (system_err != EINVAL)
154
buf[buflen - 1] = '\0';
158
code = GPG_ERR_UNKNOWN_ERRNO;
161
errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
162
errstr_len = strlen (errstr) + 1;
163
cpy_len = errstr_len < buflen ? errstr_len : buflen;
164
memcpy (buf, errstr, cpy_len);
166
buf[buflen - 1] = '\0';
168
return cpy_len == errstr_len ? 0 : ERANGE;