LCOV - code coverage report
Current view: top level - src - strerror.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 3 31 9.7 %
Date: 2016-09-12 12:50:44 Functions: 1 3 33.3 %

          Line data    Source code
       1             : /* strerror.c - Describing an error code.
       2             :    Copyright (C) 2003 g10 Code GmbH
       3             : 
       4             :    This file is part of libgpg-error.
       5             : 
       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.
      10             : 
      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.
      15             : 
      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
      19             :    02111-1307, USA.  */
      20             : 
      21             : #if HAVE_CONFIG_H
      22             : #include <config.h>
      23             : #endif
      24             : 
      25             : #include <stdlib.h>
      26             : #include <stdio.h>
      27             : #include <string.h>
      28             : #include <errno.h>
      29             : 
      30             : #include <gpg-error.h>
      31             : 
      32             : #include "gettext.h"
      33             : #include "err-codes.h"
      34             : 
      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.  */
      37             : const char *
      38           9 : _gpg_strerror (gpg_error_t err)
      39             : {
      40             :   gpg_err_code_t code = gpg_err_code (err);
      41             : 
      42           9 :   if (code & GPG_ERR_SYSTEM_ERROR)
      43             :     {
      44           0 :       int no = gpg_err_code_to_errno (code);
      45           0 :       if (no)
      46           0 :         return strerror (no);
      47             :       else
      48             :         code = GPG_ERR_UNKNOWN_ERRNO;
      49             :     }
      50           9 :   return dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
      51             : }
      52             : 
      53             : 
      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.  */
      58             : 
      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
      63             :    and return 0.  */
      64             : static int
      65           0 : system_strerror_r (int no, char *buf, size_t buflen)
      66             : {
      67             :   char *errstr;
      68             : 
      69           0 :   errstr = strerror_r (no, buf, buflen);
      70           0 :   if (errstr != buf)
      71             :     {
      72           0 :       size_t errstr_len = strlen (errstr) + 1;
      73           0 :       size_t cpy_len = errstr_len < buflen ? errstr_len : buflen;
      74           0 :       memcpy (buf, errstr, cpy_len);
      75             : 
      76           0 :       return cpy_len == errstr_len ? 0 : ERANGE;
      77             :     }
      78             :   else
      79             :     {
      80             :       /* We can not tell if the buffer was large enough, but we can
      81             :          try to make a guess.  */
      82           0 :       if (strlen (buf) + 1 >= buflen)
      83             :         return ERANGE;
      84             : 
      85           0 :       return 0;
      86             :     }
      87             : }
      88             : 
      89             : #else   /* STRERROR_R_CHAR_P */
      90             : /* Now the POSIX version.  */
      91             : 
      92             : static int
      93             : system_strerror_r (int no, char *buf, size_t buflen)
      94             : {
      95             :   return strerror_r (no, buf, buflen);
      96             : }
      97             : 
      98             : #endif  /* STRERROR_R_CHAR_P */
      99             : 
     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.  */
     104             : 
     105             : static int
     106             : system_strerror_r (int no, char *buf, size_t buflen)
     107             : {
     108             :   char *errstr = strerror (no);
     109             : 
     110             :   if (!errstr)
     111             :     {
     112             :       int saved_errno = errno;
     113             : 
     114             :       if (saved_errno != EINVAL)
     115             :         snprintf (buf, buflen, "strerror failed: %i\n", errno);
     116             :       return saved_errno;
     117             :     }
     118             :   else
     119             :     {
     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;
     124             :     }
     125             : }
     126             : #endif
     127             : 
     128             : 
     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.  */
     136             : int
     137           0 : _gpg_strerror_r (gpg_error_t err, char *buf, size_t buflen)
     138             : {
     139             :   gpg_err_code_t code = gpg_err_code (err);
     140             :   const char *errstr;
     141             :   size_t errstr_len;
     142             :   size_t cpy_len;
     143             : 
     144           0 :   if (code & GPG_ERR_SYSTEM_ERROR)
     145             :     {
     146           0 :       int no = gpg_err_code_to_errno (code);
     147           0 :       if (no)
     148             :         {
     149           0 :           int system_err = system_strerror_r (no, buf, buflen);
     150             : 
     151           0 :           if (system_err != EINVAL)
     152             :             {
     153           0 :               if (buflen)
     154           0 :                 buf[buflen - 1] = '\0';
     155           0 :               return system_err;
     156             :             }
     157             :         }
     158             :       code = GPG_ERR_UNKNOWN_ERRNO;
     159             :     }
     160             : 
     161           0 :   errstr = dgettext (PACKAGE, msgstr + msgidx[msgidxof (code)]);
     162           0 :   errstr_len = strlen (errstr) + 1;
     163           0 :   cpy_len = errstr_len < buflen ? errstr_len : buflen;
     164           0 :   memcpy (buf, errstr, cpy_len);
     165           0 :   if (buflen)
     166           0 :     buf[buflen - 1] = '\0';
     167             : 
     168           0 :   return cpy_len == errstr_len ? 0 : ERANGE;
     169             : }

Generated by: LCOV version 1.11