aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcus Brinkmann <[email protected]>2003-09-30 19:27:21 +0000
committerMarcus Brinkmann <[email protected]>2003-09-30 19:27:21 +0000
commit3946df08f9f77a441eff9f1a5c67a18d08563237 (patch)
tree5432214339a655aaac6b8fc1b1c4f832e55d3299
parentAdd item about error code. (diff)
downloadlibgpg-error-3946df08f9f77a441eff9f1a5c67a18d08563237.tar.gz
libgpg-error-3946df08f9f77a441eff9f1a5c67a18d08563237.zip
2003-09-30 Marcus Brinkmann <[email protected]>
* src/gpg-error.h: Include <stddef.h>. (gpg_strerror_r): Change prototype to match POSIX. Rewritten for that prototype. * src/strerror.c: Include <errno.h>. (gpg_strerror_r, system_strerror_r): Change prototype to match POSIX. Rewritten for that prototype. Rewritten for that prototype.
-rw-r--r--ChangeLog10
-rw-r--r--src/gpg-error.h15
-rw-r--r--src/strerror.c204
3 files changed, 79 insertions, 150 deletions
diff --git a/ChangeLog b/ChangeLog
index 10731b1..fc38af0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,13 @@
+2003-09-30 Marcus Brinkmann <[email protected]>
+
+ * src/gpg-error.h: Include <stddef.h>.
+ (gpg_strerror_r): Change prototype to match POSIX. Rewritten for
+ that prototype.
+ * src/strerror.c: Include <errno.h>.
+ (gpg_strerror_r, system_strerror_r): Change prototype to match
+ POSIX. Rewritten for that prototype. Rewritten for that
+ prototype.
+
2003-09-30 Werner Koch <[email protected]>
* src/gpg-error.h: Add PIN_NOT_SYNCED.
diff --git a/src/gpg-error.h b/src/gpg-error.h
index cf6d2f5..5f92564 100644
--- a/src/gpg-error.h
+++ b/src/gpg-error.h
@@ -21,6 +21,8 @@
#ifndef GPG_ERROR_H
#define GPG_ERROR_H 1
+#include <stddef.h>
+
#ifdef __GNUC__
#define GPG_ERR_INLINE __inline__
#elif __STDC_VERSION__ >= 199901L
@@ -496,11 +498,14 @@ gpg_err_source (gpg_error_t err)
code in the error value ERR. This function is not thread-safe. */
const char *gpg_strerror (gpg_error_t err);
-/* Return a pointer to a string containing a description of the error
- code in the error value ERR. The buffer for the string is
- allocated with malloc(), and has to be released by the user. On
- error, NULL is returned. */
-char *gpg_strerror_r (gpg_error_t err);
+/* Return the error string for ERR in the user-supplied buffer BUF of
+ size BUFLEN. This function is, in contrast to gpg_strerror,
+ thread-safe if a thread-safe strerror_r() function is provided by
+ the system. If the function succeeds, 0 is returned and BUF
+ contains the string describing the error. If the buffer was not
+ large enough, ERANGE is returned and BUF contains as much of the
+ beginning of the error string as fits into the buffer. */
+int gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen);
/* Return a pointer to a string containing a description of the error
source in the error value ERR. */
diff --git a/src/strerror.c b/src/strerror.c
index a8a5a63..dd6a6b3 100644
--- a/src/strerror.c
+++ b/src/strerror.c
@@ -24,6 +24,7 @@
#include <stdlib.h>
#include <string.h>
+#include <errno.h>
#include <gpg-error.h>
@@ -60,139 +61,39 @@ gpg_strerror (gpg_error_t err)
call fails because the error number is not valid, don't set *STR
and return 0. */
int
-system_strerror_r (int no, char **str)
+system_strerror_r (int no, char *buf, size_t buflen)
{
- int err;
- char *buffer;
- size_t buffer_len = 128;
+ char *errstr;
- buffer = malloc (buffer_len);
- if (!buffer)
+ errstr = strerror_r (no, buf, buflen);
+ if (errstr != buf)
{
- *str = NULL;
- return 1;
- }
+ size_t errstr_len = strlen (errstr) + 1;
+ size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
+ memcpy (buf, errstr, cpy_len);
- do
+ return cpy_len == errstr_len ? 0 : ERANGE;
+ }
+ else
{
- char *msg = strerror_r (no, buffer, buffer_len);
-
- if (!msg)
- {
- /* Possibly this means that the error code is unknown. */
- free (buffer);
- return 0;
- }
- else if (msg != buffer)
- {
- free (buffer);
- *str = strdup (msg);
- return 1;
- }
+ /* We can not tell if the buffer was large enough, but we can
+ try to make a guess. */
+ if (strlen (buf) + 1 >= buflen)
+ return ERANGE;
- buffer[buffer_len - 1] = '\0';
- if (strlen (buffer) == buffer_len - 1)
- {
- /* We might need more space. */
- size_t new_buffer_len = buffer_len * 2;
- char *new_buffer;
-
- if (new_buffer_len < buffer_len)
- {
- /* Overflow. Now, this is serious. */
- free (buffer);
- *str = NULL;
- return 1;
- }
-
- new_buffer = realloc (buffer, 2 * buffer_len);
- if (!new_buffer)
- {
- free (buffer);
- *str = NULL;
- return 1;
- }
- buffer = new_buffer;
- buffer_len = new_buffer_len;
- }
- else
- {
- *str = buffer;
- return 1;
- }
+ return 0;
}
- while (1);
}
#else /* STRERROR_R_CHAR_P */
/* Now the POSIX version. */
-/* Return a dynamically allocated string in *STR describing the system
- error NO. If this call succeeds, return 1. If this call fails due
- to a resource shortage, set *STR to NULL and return 1. If this
- call fails because the error number is not valid, don't set *STR
- and return 0. */
int
-system_strerror_r (int no, char **str)
+system_strerror_r (int no, char *buf, size_t buflen)
{
- int err;
- char *buffer;
- size_t buffer_len = 128;
-
- buffer = malloc (buffer_len);
- if (!buffer)
- {
- *str = NULL;
- return 1;
- }
-
- do
- {
- err = strerror_r (no, buffer, buffer_len);
-
- if (err == ERANGE)
- {
- size_t new_buffer_len = buffer_len * 2;
- char *new_buffer;
-
- if (new_buffer_len < buffer_len)
- {
- /* Overflow. Now, this is serious. */
- free (buffer);
- *str = NULL;
- return 1;
- }
-
- new_buffer = realloc (buffer, 2 * buffer_len);
- if (!new_buffer)
- {
- free (buffer);
- *str = NULL;
- return 1;
- }
- buffer = new_buffer;
- buffer_len = new_buffer_len;
- }
- }
- while (err == ERANGE);
-
- if (err == EINVAL)
- {
- /* This system error is not known. */
- free (buffer);
- return 0;
- }
- else if (err)
- {
- /* strerror_r() failed, but we don't know why. */
- free (buffer);
- *str = NULL;
- return 1;
- }
-
- *str = buffer;
- return 1;
+ return strerror_r (no, buf, buflen);
}
+
#endif /* STRERROR_R_CHAR_P */
#else /* HAVE_STRERROR_H */
@@ -200,55 +101,68 @@ system_strerror_r (int no, char **str)
version. Maybe we are even lucky and the system's strerror() is
already thread-safe. */
-/* Return a dynamically allocated string in *STR describing the system
- error NO. If this call succeeds, return 1. If this call fails due
- to a resource shortage, set *STR to NULL and return 1. If this
- call fails because the error number is not valid, don't set *STR
- and return 0. */
int
-system_strerror_r (int no, char **str)
+system_strerror_r (int no, char *buf, size_t buflen)
{
- char *msg = strerror (no);
+ char *errstr = strerror (no);
- if (!msg)
+ if (!errstr)
{
- if (errno == EINVAL)
- return 0;
- else
- {
- *str = NULL;
- return 1;
- }
+ int saved_errno = errno;
+
+ if (saved_errno != EINVAL)
+ snprintf (buf, buflen, "strerror failed: %i\n", errno);
+ return saved_errno;
}
else
{
- *str = strdup (msg);
- return 1;
+ size_t errstr_len = strlen (errstr) + 1;
+ size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
+ memcpy (buf, errstr, cpy_len);
+ return cpy_len == errstr_len ? 0 : ERANGE;
}
}
#endif
-/* Return a pointer to a string containing a description of the error
- code in the error value ERR. The buffer for the string is
- allocated with malloc(), and has to be released by the user. On
- error, NULL is returned. */
-char *
-gpg_strerror_r (gpg_error_t err)
+/* Return the error string for ERR in the user-supplied buffer BUF of
+ size BUFLEN. This function is, in contrast to gpg_strerror,
+ thread-safe if a thread-safe strerror_r() function is provided by
+ the system. If the function succeeds, 0 is returned and BUF
+ contains the string describing the error. If the buffer was not
+ large enough, ERANGE is returned and BUF contains as much of the
+ beginning of the error string as fits into the buffer. */
+int
+gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen)
{
gpg_err_code_t code = gpg_err_code (err);
+ const char *errstr;
+ size_t errstr_len;
+ size_t cpy_len;
if (code & GPG_ERR_SYSTEM_ERROR)
{
int no = gpg_err_code_to_errno (code);
if (no)
{
- char *str;
+ int system_err = system_strerror_r (no, buf, buflen);
- if (system_strerror_r (no, &str))
- return str;
+ if (system_err != EINVAL)
+ {
+ if (buflen)
+ buf[buflen - 1] = '\0';
+ return system_err;
+ }
}
code = GPG_ERR_UNKNOWN_ERRNO;
}
- return strdup (dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]));
+
+ errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
+ errstr_len = strlen (errstr) + 1;
+ cpy_len = errstr_len < buflen ? errstr_len : buflen;
+ memcpy (buf, errstr, cpy_len);
+ if (buflen)
+ buf[buflen - 1] = '\0';
+
+ return cpy_len == errstr_len ? 0 : ERANGE;
}