Blame src/strerror.c

Packit fc043f
/* strerror.c - Describing an error code.
Packit fc043f
   Copyright (C) 2003 g10 Code GmbH
Packit fc043f
Packit fc043f
   This file is part of libgpg-error.
Packit fc043f
Packit fc043f
   libgpg-error is free software; you can redistribute it and/or
Packit fc043f
   modify it under the terms of the GNU Lesser General Public License
Packit fc043f
   as published by the Free Software Foundation; either version 2.1 of
Packit fc043f
   the License, or (at your option) any later version.
Packit fc043f
Packit fc043f
   libgpg-error is distributed in the hope that it will be useful, but
Packit fc043f
   WITHOUT ANY WARRANTY; without even the implied warranty of
Packit fc043f
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit fc043f
   Lesser General Public License for more details.
Packit fc043f
Packit fc043f
   You should have received a copy of the GNU Lesser General Public
Packit fc043f
   License along with libgpg-error; if not, write to the Free
Packit fc043f
   Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
Packit fc043f
   02111-1307, USA.  */
Packit fc043f
Packit fc043f
#if HAVE_CONFIG_H
Packit fc043f
#include <config.h>
Packit fc043f
#endif
Packit fc043f
Packit fc043f
#include <stdlib.h>
Packit fc043f
#include <stdio.h>
Packit fc043f
#include <string.h>
Packit fc043f
#include <errno.h>
Packit fc043f
Packit fc043f
#include <gpg-error.h>
Packit fc043f
Packit fc043f
#include "gettext.h"
Packit fc043f
#include "err-codes.h"
Packit fc043f
Packit fc043f
/* Return a pointer to a string containing a description of the error
Packit fc043f
   code in the error value ERR.  This function is not thread-safe.  */
Packit fc043f
const char *
Packit fc043f
_gpg_strerror (gpg_error_t err)
Packit fc043f
{
Packit fc043f
  gpg_err_code_t code = gpg_err_code (err);
Packit fc043f
Packit fc043f
  if (code & GPG_ERR_SYSTEM_ERROR)
Packit fc043f
    {
Packit fc043f
      int no = gpg_err_code_to_errno (code);
Packit fc043f
      if (no)
Packit fc043f
	return strerror (no);
Packit fc043f
      else
Packit fc043f
	code = GPG_ERR_UNKNOWN_ERRNO;
Packit fc043f
    }
Packit fc043f
  return dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
Packit fc043f
}
Packit fc043f
Packit fc043f
Packit fc043f
#ifdef HAVE_STRERROR_R
Packit fc043f
#ifdef STRERROR_R_CHAR_P
Packit fc043f
/* The GNU C library and probably some other systems have this weird
Packit fc043f
   variant of strerror_r.  */
Packit fc043f
Packit fc043f
/* Return a dynamically allocated string in *STR describing the system
Packit fc043f
   error NO.  If this call succeeds, return 1.  If this call fails due
Packit fc043f
   to a resource shortage, set *STR to NULL and return 1.  If this
Packit fc043f
   call fails because the error number is not valid, don't set *STR
Packit fc043f
   and return 0.  */
Packit fc043f
static int
Packit fc043f
system_strerror_r (int no, char *buf, size_t buflen)
Packit fc043f
{
Packit fc043f
  char *errstr;
Packit fc043f
Packit fc043f
  errstr = strerror_r (no, buf, buflen);
Packit fc043f
  if (errstr != buf)
Packit fc043f
    {
Packit fc043f
      size_t errstr_len = strlen (errstr) + 1;
Packit fc043f
      size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
Packit fc043f
      memcpy (buf, errstr, cpy_len);
Packit fc043f
Packit fc043f
      return cpy_len == errstr_len ? 0 : ERANGE;
Packit fc043f
    }
Packit fc043f
  else
Packit fc043f
    {
Packit fc043f
      /* We can not tell if the buffer was large enough, but we can
Packit fc043f
	 try to make a guess.  */
Packit fc043f
      if (strlen (buf) + 1 >= buflen)
Packit fc043f
	return ERANGE;
Packit fc043f
Packit fc043f
      return 0;
Packit fc043f
    }
Packit fc043f
}
Packit fc043f
Packit fc043f
#else	/* STRERROR_R_CHAR_P */
Packit fc043f
/* Now the POSIX version.  */
Packit fc043f
Packit fc043f
static int
Packit fc043f
system_strerror_r (int no, char *buf, size_t buflen)
Packit fc043f
{
Packit fc043f
  return strerror_r (no, buf, buflen);
Packit fc043f
}
Packit fc043f
Packit fc043f
#endif	/* STRERROR_R_CHAR_P */
Packit fc043f
Packit fc043f
#else	/* HAVE_STRERROR_H */
Packit fc043f
/* Without strerror_r(), we can still provide a non-thread-safe
Packit fc043f
   version.  Maybe we are even lucky and the system's strerror() is
Packit fc043f
   already thread-safe.  */
Packit fc043f
Packit fc043f
static int
Packit fc043f
system_strerror_r (int no, char *buf, size_t buflen)
Packit fc043f
{
Packit fc043f
  char *errstr = strerror (no);
Packit fc043f
Packit fc043f
  if (!errstr)
Packit fc043f
    {
Packit fc043f
      int saved_errno = errno;
Packit fc043f
Packit fc043f
      if (saved_errno != EINVAL)
Packit fc043f
	snprintf (buf, buflen, "strerror failed: %i\n", errno);
Packit fc043f
      return saved_errno;
Packit fc043f
    }
Packit fc043f
  else
Packit fc043f
    {
Packit fc043f
      size_t errstr_len = strlen (errstr) + 1;
Packit fc043f
      size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
Packit fc043f
      memcpy (buf, errstr, cpy_len);
Packit fc043f
      return cpy_len == errstr_len ? 0 : ERANGE;
Packit fc043f
    }
Packit fc043f
}
Packit fc043f
#endif
Packit fc043f
Packit fc043f
Packit fc043f
/* Return the error string for ERR in the user-supplied buffer BUF of
Packit fc043f
   size BUFLEN.  This function is, in contrast to gpg_strerror,
Packit fc043f
   thread-safe if a thread-safe strerror_r() function is provided by
Packit fc043f
   the system.  If the function succeeds, 0 is returned and BUF
Packit fc043f
   contains the string describing the error.  If the buffer was not
Packit fc043f
   large enough, ERANGE is returned and BUF contains as much of the
Packit fc043f
   beginning of the error string as fits into the buffer.  */
Packit fc043f
int
Packit fc043f
_gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen)
Packit fc043f
{
Packit fc043f
  gpg_err_code_t code = gpg_err_code (err);
Packit fc043f
  const char *errstr;
Packit fc043f
  size_t errstr_len;
Packit fc043f
  size_t cpy_len;
Packit fc043f
Packit fc043f
  if (code & GPG_ERR_SYSTEM_ERROR)
Packit fc043f
    {
Packit fc043f
      int no = gpg_err_code_to_errno (code);
Packit fc043f
      if (no)
Packit fc043f
	{
Packit fc043f
	  int system_err = system_strerror_r (no, buf, buflen);
Packit fc043f
Packit fc043f
	  if (system_err != EINVAL)
Packit fc043f
	    {
Packit fc043f
	      if (buflen)
Packit fc043f
		buf[buflen - 1] = '\0';
Packit fc043f
	      return system_err;
Packit fc043f
	    }
Packit fc043f
	}
Packit fc043f
      code = GPG_ERR_UNKNOWN_ERRNO;
Packit fc043f
    }
Packit fc043f
Packit fc043f
  errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
Packit fc043f
  errstr_len = strlen (errstr) + 1;
Packit fc043f
  cpy_len = errstr_len < buflen ? errstr_len : buflen;
Packit fc043f
  memcpy (buf, errstr, cpy_len);
Packit fc043f
  if (buflen)
Packit fc043f
    buf[buflen - 1] = '\0';
Packit fc043f
Packit fc043f
  return cpy_len == errstr_len ? 0 : ERANGE;
Packit fc043f
}