Blame gnulib-tests/strerror_r.c

Packit Service fdd496
/* strerror_r.c --- POSIX compatible system error routine
Packit Service fdd496
Packit Service fdd496
   Copyright (C) 2010-2017 Free Software Foundation, Inc.
Packit Service fdd496
Packit Service fdd496
   This program is free software: you can redistribute it and/or modify
Packit Service fdd496
   it under the terms of the GNU General Public License as published by
Packit Service fdd496
   the Free Software Foundation; either version 3 of the License, or
Packit Service fdd496
   (at your option) any later version.
Packit Service fdd496
Packit Service fdd496
   This program is distributed in the hope that it will be useful,
Packit Service fdd496
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service fdd496
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service fdd496
   GNU General Public License for more details.
Packit Service fdd496
Packit Service fdd496
   You should have received a copy of the GNU General Public License
Packit Service fdd496
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
Packit Service fdd496
Packit Service fdd496
/* Written by Bruno Haible <bruno@clisp.org>, 2010.  */
Packit Service fdd496
Packit Service fdd496
#include <config.h>
Packit Service fdd496
Packit Service fdd496
/* Enable declaration of sys_nerr and sys_errlist in <errno.h> on NetBSD.  */
Packit Service fdd496
#define _NETBSD_SOURCE 1
Packit Service fdd496
Packit Service fdd496
/* Specification.  */
Packit Service fdd496
#include <string.h>
Packit Service fdd496
Packit Service fdd496
#include <errno.h>
Packit Service fdd496
#include <stdio.h>
Packit Service fdd496
#include <stdlib.h>
Packit Service fdd496
#if !HAVE_SNPRINTF
Packit Service fdd496
# include <stdarg.h>
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#include "strerror-override.h"
Packit Service fdd496
Packit Service fdd496
#if (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__) && HAVE___XPG_STRERROR_R /* glibc >= 2.3.4, cygwin >= 1.7.9 */
Packit Service fdd496
Packit Service fdd496
# define USE_XPG_STRERROR_R 1
Packit Service fdd496
extern
Packit Service fdd496
#ifdef __cplusplus
Packit Service fdd496
"C"
Packit Service fdd496
#endif
Packit Service fdd496
int __xpg_strerror_r (int errnum, char *buf, size_t buflen);
Packit Service fdd496
Packit Service fdd496
#elif HAVE_DECL_STRERROR_R && !(__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__)
Packit Service fdd496
Packit Service fdd496
/* The system's strerror_r function is OK, except that its third argument
Packit Service fdd496
   is 'int', not 'size_t', or its return type is wrong.  */
Packit Service fdd496
Packit Service fdd496
# include <limits.h>
Packit Service fdd496
Packit Service fdd496
# define USE_SYSTEM_STRERROR_R 1
Packit Service fdd496
Packit Service fdd496
#else /* (__GLIBC__ >= 2 || defined __UCLIBC__ || defined __CYGWIN__ ? !HAVE___XPG_STRERROR_R : !HAVE_DECL_STRERROR_R) */
Packit Service fdd496
Packit Service fdd496
/* Use the system's strerror().  Exclude glibc and cygwin because the
Packit Service fdd496
   system strerror_r has the wrong return type, and cygwin 1.7.9
Packit Service fdd496
   strerror_r clobbers strerror.  */
Packit Service fdd496
# undef strerror
Packit Service fdd496
Packit Service fdd496
# define USE_SYSTEM_STRERROR 1
Packit Service fdd496
Packit Service fdd496
# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __sgi || (defined __sun && !defined _LP64) || defined __CYGWIN__
Packit Service fdd496
Packit Service fdd496
/* No locking needed.  */
Packit Service fdd496
Packit Service fdd496
/* Get catgets internationalization functions.  */
Packit Service fdd496
#  if HAVE_CATGETS
Packit Service fdd496
#   include <nl_types.h>
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
#ifdef __cplusplus
Packit Service fdd496
extern "C" {
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Get sys_nerr, sys_errlist on HP-UX (otherwise only declared in C++ mode).
Packit Service fdd496
   Get sys_nerr, sys_errlist on IRIX (otherwise only declared with _SGIAPI).  */
Packit Service fdd496
#  if defined __hpux || defined __sgi
Packit Service fdd496
extern int sys_nerr;
Packit Service fdd496
extern char *sys_errlist[];
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
/* Get sys_nerr on Solaris.  */
Packit Service fdd496
#  if defined __sun && !defined _LP64
Packit Service fdd496
extern int sys_nerr;
Packit Service fdd496
#  endif
Packit Service fdd496
Packit Service fdd496
#ifdef __cplusplus
Packit Service fdd496
}
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
# else
Packit Service fdd496
Packit Service fdd496
#  include "glthread/lock.h"
Packit Service fdd496
Packit Service fdd496
/* This lock protects the buffer returned by strerror().  We assume that
Packit Service fdd496
   no other uses of strerror() exist in the program.  */
Packit Service fdd496
gl_lock_define_initialized(static, strerror_lock)
Packit Service fdd496
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* On MSVC, there is no snprintf() function, just a _snprintf().
Packit Service fdd496
   It is of lower quality, but sufficient for the simple use here.
Packit Service fdd496
   We only have to make sure to NUL terminate the result (_snprintf
Packit Service fdd496
   does not NUL terminate, like strncpy).  */
Packit Service fdd496
#if !HAVE_SNPRINTF
Packit Service fdd496
static int
Packit Service fdd496
local_snprintf (char *buf, size_t buflen, const char *format, ...)
Packit Service fdd496
{
Packit Service fdd496
  va_list args;
Packit Service fdd496
  int result;
Packit Service fdd496
Packit Service fdd496
  va_start (args, format);
Packit Service fdd496
  result = _vsnprintf (buf, buflen, format, args);
Packit Service fdd496
  va_end (args);
Packit Service fdd496
  if (buflen > 0 && (result < 0 || result >= buflen))
Packit Service fdd496
    buf[buflen - 1] = '\0';
Packit Service fdd496
  return result;
Packit Service fdd496
}
Packit Service fdd496
# define snprintf local_snprintf
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
/* Copy as much of MSG into BUF as possible, without corrupting errno.
Packit Service fdd496
   Return 0 if MSG fit in BUFLEN, otherwise return ERANGE.  */
Packit Service fdd496
static int
Packit Service fdd496
safe_copy (char *buf, size_t buflen, const char *msg)
Packit Service fdd496
{
Packit Service fdd496
  size_t len = strlen (msg);
Packit Service fdd496
  int ret;
Packit Service fdd496
Packit Service fdd496
  if (len < buflen)
Packit Service fdd496
    {
Packit Service fdd496
      /* Although POSIX allows memcpy() to corrupt errno, we don't
Packit Service fdd496
         know of any implementation where this is a real problem.  */
Packit Service fdd496
      memcpy (buf, msg, len + 1);
Packit Service fdd496
      ret = 0;
Packit Service fdd496
    }
Packit Service fdd496
  else
Packit Service fdd496
    {
Packit Service fdd496
      memcpy (buf, msg, buflen - 1);
Packit Service fdd496
      buf[buflen - 1] = '\0';
Packit Service fdd496
      ret = ERANGE;
Packit Service fdd496
    }
Packit Service fdd496
  return ret;
Packit Service fdd496
}
Packit Service fdd496
Packit Service fdd496
Packit Service fdd496
int
Packit Service fdd496
strerror_r (int errnum, char *buf, size_t buflen)
Packit Service fdd496
#undef strerror_r
Packit Service fdd496
{
Packit Service fdd496
  /* Filter this out now, so that rest of this replacement knows that
Packit Service fdd496
     there is room for a non-empty message and trailing NUL.  */
Packit Service fdd496
  if (buflen <= 1)
Packit Service fdd496
    {
Packit Service fdd496
      if (buflen)
Packit Service fdd496
        *buf = '\0';
Packit Service fdd496
      return ERANGE;
Packit Service fdd496
    }
Packit Service fdd496
  *buf = '\0';
Packit Service fdd496
Packit Service fdd496
  /* Check for gnulib overrides.  */
Packit Service fdd496
  {
Packit Service fdd496
    char const *msg = strerror_override (errnum);
Packit Service fdd496
Packit Service fdd496
    if (msg)
Packit Service fdd496
      return safe_copy (buf, buflen, msg);
Packit Service fdd496
  }
Packit Service fdd496
Packit Service fdd496
  {
Packit Service fdd496
    int ret;
Packit Service fdd496
    int saved_errno = errno;
Packit Service fdd496
Packit Service fdd496
#if USE_XPG_STRERROR_R
Packit Service fdd496
Packit Service fdd496
    {
Packit Service fdd496
      ret = __xpg_strerror_r (errnum, buf, buflen);
Packit Service fdd496
      if (ret < 0)
Packit Service fdd496
        ret = errno;
Packit Service fdd496
      if (!*buf)
Packit Service fdd496
        {
Packit Service fdd496
          /* glibc 2.13 would not touch buf on err, so we have to fall
Packit Service fdd496
             back to GNU strerror_r which always returns a thread-safe
Packit Service fdd496
             untruncated string to (partially) copy into our buf.  */
Packit Service fdd496
          safe_copy (buf, buflen, strerror_r (errnum, buf, buflen));
Packit Service fdd496
        }
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
#elif USE_SYSTEM_STRERROR_R
Packit Service fdd496
Packit Service fdd496
    if (buflen > INT_MAX)
Packit Service fdd496
      buflen = INT_MAX;
Packit Service fdd496
Packit Service fdd496
# ifdef __hpux
Packit Service fdd496
    /* On HP-UX 11.31, strerror_r always fails when buflen < 80; it
Packit Service fdd496
       also fails to change buf on EINVAL.  */
Packit Service fdd496
    {
Packit Service fdd496
      char stackbuf[80];
Packit Service fdd496
Packit Service fdd496
      if (buflen < sizeof stackbuf)
Packit Service fdd496
        {
Packit Service fdd496
          ret = strerror_r (errnum, stackbuf, sizeof stackbuf);
Packit Service fdd496
          if (ret == 0)
Packit Service fdd496
            ret = safe_copy (buf, buflen, stackbuf);
Packit Service fdd496
        }
Packit Service fdd496
      else
Packit Service fdd496
        ret = strerror_r (errnum, buf, buflen);
Packit Service fdd496
    }
Packit Service fdd496
# else
Packit Service fdd496
    ret = strerror_r (errnum, buf, buflen);
Packit Service fdd496
Packit Service fdd496
    /* Some old implementations may return (-1, EINVAL) instead of EINVAL.  */
Packit Service fdd496
    if (ret < 0)
Packit Service fdd496
      ret = errno;
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
# ifdef _AIX
Packit Service fdd496
    /* AIX returns 0 rather than ERANGE when truncating strings; try
Packit Service fdd496
       again until we are sure we got the entire string.  */
Packit Service fdd496
    if (!ret && strlen (buf) == buflen - 1)
Packit Service fdd496
      {
Packit Service fdd496
        char stackbuf[STACKBUF_LEN];
Packit Service fdd496
        size_t len;
Packit Service fdd496
        strerror_r (errnum, stackbuf, sizeof stackbuf);
Packit Service fdd496
        len = strlen (stackbuf);
Packit Service fdd496
        /* STACKBUF_LEN should have been large enough.  */
Packit Service fdd496
        if (len + 1 == sizeof stackbuf)
Packit Service fdd496
          abort ();
Packit Service fdd496
        if (buflen <= len)
Packit Service fdd496
          ret = ERANGE;
Packit Service fdd496
      }
Packit Service fdd496
# else
Packit Service fdd496
    /* Solaris 10 does not populate buf on ERANGE.  OpenBSD 4.7
Packit Service fdd496
       truncates early on ERANGE rather than return a partial integer.
Packit Service fdd496
       We prefer the maximal string.  We set buf[0] earlier, and we
Packit Service fdd496
       know of no implementation that modifies buf to be an
Packit Service fdd496
       unterminated string, so this strlen should be portable in
Packit Service fdd496
       practice (rather than pulling in a safer strnlen).  */
Packit Service fdd496
    if (ret == ERANGE && strlen (buf) < buflen - 1)
Packit Service fdd496
      {
Packit Service fdd496
        char stackbuf[STACKBUF_LEN];
Packit Service fdd496
Packit Service fdd496
        /* STACKBUF_LEN should have been large enough.  */
Packit Service fdd496
        if (strerror_r (errnum, stackbuf, sizeof stackbuf) == ERANGE)
Packit Service fdd496
          abort ();
Packit Service fdd496
        safe_copy (buf, buflen, stackbuf);
Packit Service fdd496
      }
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
#else /* USE_SYSTEM_STRERROR */
Packit Service fdd496
Packit Service fdd496
    /* Try to do what strerror (errnum) does, but without clobbering the
Packit Service fdd496
       buffer used by strerror().  */
Packit Service fdd496
Packit Service fdd496
# if defined __NetBSD__ || defined __hpux || ((defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__) || defined __CYGWIN__ /* NetBSD, HP-UX, native Windows, Cygwin */
Packit Service fdd496
Packit Service fdd496
    /* NetBSD:         sys_nerr, sys_errlist are declared through _NETBSD_SOURCE
Packit Service fdd496
                       and <errno.h> above.
Packit Service fdd496
       HP-UX:          sys_nerr, sys_errlist are declared explicitly above.
Packit Service fdd496
       native Windows: sys_nerr, sys_errlist are declared in <stdlib.h>.
Packit Service fdd496
       Cygwin:         sys_nerr, sys_errlist are declared in <errno.h>.  */
Packit Service fdd496
    if (errnum >= 0 && errnum < sys_nerr)
Packit Service fdd496
      {
Packit Service fdd496
#  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
Packit Service fdd496
#   if defined __NetBSD__
Packit Service fdd496
        nl_catd catd = catopen ("libc", NL_CAT_LOCALE);
Packit Service fdd496
        const char *errmsg =
Packit Service fdd496
          (catd != (nl_catd)-1
Packit Service fdd496
           ? catgets (catd, 1, errnum, sys_errlist[errnum])
Packit Service fdd496
           : sys_errlist[errnum]);
Packit Service fdd496
#   endif
Packit Service fdd496
#   if defined __hpux
Packit Service fdd496
        nl_catd catd = catopen ("perror", NL_CAT_LOCALE);
Packit Service fdd496
        const char *errmsg =
Packit Service fdd496
          (catd != (nl_catd)-1
Packit Service fdd496
           ? catgets (catd, 1, 1 + errnum, sys_errlist[errnum])
Packit Service fdd496
           : sys_errlist[errnum]);
Packit Service fdd496
#   endif
Packit Service fdd496
#  else
Packit Service fdd496
        const char *errmsg = sys_errlist[errnum];
Packit Service fdd496
#  endif
Packit Service fdd496
        if (errmsg == NULL || *errmsg == '\0')
Packit Service fdd496
          ret = EINVAL;
Packit Service fdd496
        else
Packit Service fdd496
          ret = safe_copy (buf, buflen, errmsg);
Packit Service fdd496
#  if HAVE_CATGETS && (defined __NetBSD__ || defined __hpux)
Packit Service fdd496
        if (catd != (nl_catd)-1)
Packit Service fdd496
          catclose (catd);
Packit Service fdd496
#  endif
Packit Service fdd496
      }
Packit Service fdd496
    else
Packit Service fdd496
      ret = EINVAL;
Packit Service fdd496
Packit Service fdd496
# elif defined __sgi || (defined __sun && !defined _LP64) /* IRIX, Solaris <= 9 32-bit */
Packit Service fdd496
Packit Service fdd496
    /* For a valid error number, the system's strerror() function returns
Packit Service fdd496
       a pointer to a not copied string, not to a buffer.  */
Packit Service fdd496
    if (errnum >= 0 && errnum < sys_nerr)
Packit Service fdd496
      {
Packit Service fdd496
        char *errmsg = strerror (errnum);
Packit Service fdd496
Packit Service fdd496
        if (errmsg == NULL || *errmsg == '\0')
Packit Service fdd496
          ret = EINVAL;
Packit Service fdd496
        else
Packit Service fdd496
          ret = safe_copy (buf, buflen, errmsg);
Packit Service fdd496
      }
Packit Service fdd496
    else
Packit Service fdd496
      ret = EINVAL;
Packit Service fdd496
Packit Service fdd496
# else
Packit Service fdd496
Packit Service fdd496
    gl_lock_lock (strerror_lock);
Packit Service fdd496
Packit Service fdd496
    {
Packit Service fdd496
      char *errmsg = strerror (errnum);
Packit Service fdd496
Packit Service fdd496
      /* For invalid error numbers, strerror() on
Packit Service fdd496
           - IRIX 6.5 returns NULL,
Packit Service fdd496
           - HP-UX 11 returns an empty string.  */
Packit Service fdd496
      if (errmsg == NULL || *errmsg == '\0')
Packit Service fdd496
        ret = EINVAL;
Packit Service fdd496
      else
Packit Service fdd496
        ret = safe_copy (buf, buflen, errmsg);
Packit Service fdd496
    }
Packit Service fdd496
Packit Service fdd496
    gl_lock_unlock (strerror_lock);
Packit Service fdd496
Packit Service fdd496
# endif
Packit Service fdd496
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
#if (defined _WIN32 || defined __WIN32__) && !defined __CYGWIN__
Packit Service fdd496
    /* MSVC 14 defines names for many error codes in the range 100..140,
Packit Service fdd496
       but _sys_errlist contains strings only for the error codes
Packit Service fdd496
       < _sys_nerr = 43.  */
Packit Service fdd496
    if (ret == EINVAL)
Packit Service fdd496
      {
Packit Service fdd496
        const char *errmsg;
Packit Service fdd496
Packit Service fdd496
        switch (errnum)
Packit Service fdd496
          {
Packit Service fdd496
          case 100 /* EADDRINUSE */:
Packit Service fdd496
            errmsg = "Address already in use";
Packit Service fdd496
            break;
Packit Service fdd496
          case 101 /* EADDRNOTAVAIL */:
Packit Service fdd496
            errmsg = "Cannot assign requested address";
Packit Service fdd496
            break;
Packit Service fdd496
          case 102 /* EAFNOSUPPORT */:
Packit Service fdd496
            errmsg = "Address family not supported by protocol";
Packit Service fdd496
            break;
Packit Service fdd496
          case 103 /* EALREADY */:
Packit Service fdd496
            errmsg = "Operation already in progress";
Packit Service fdd496
            break;
Packit Service fdd496
          case 105 /* ECANCELED */:
Packit Service fdd496
            errmsg = "Operation canceled";
Packit Service fdd496
            break;
Packit Service fdd496
          case 106 /* ECONNABORTED */:
Packit Service fdd496
            errmsg = "Software caused connection abort";
Packit Service fdd496
            break;
Packit Service fdd496
          case 107 /* ECONNREFUSED */:
Packit Service fdd496
            errmsg = "Connection refused";
Packit Service fdd496
            break;
Packit Service fdd496
          case 108 /* ECONNRESET */:
Packit Service fdd496
            errmsg = "Connection reset by peer";
Packit Service fdd496
            break;
Packit Service fdd496
          case 109 /* EDESTADDRREQ */:
Packit Service fdd496
            errmsg = "Destination address required";
Packit Service fdd496
            break;
Packit Service fdd496
          case 110 /* EHOSTUNREACH */:
Packit Service fdd496
            errmsg = "No route to host";
Packit Service fdd496
            break;
Packit Service fdd496
          case 112 /* EINPROGRESS */:
Packit Service fdd496
            errmsg = "Operation now in progress";
Packit Service fdd496
            break;
Packit Service fdd496
          case 113 /* EISCONN */:
Packit Service fdd496
            errmsg = "Transport endpoint is already connected";
Packit Service fdd496
            break;
Packit Service fdd496
          case 114 /* ELOOP */:
Packit Service fdd496
            errmsg = "Too many levels of symbolic links";
Packit Service fdd496
            break;
Packit Service fdd496
          case 115 /* EMSGSIZE */:
Packit Service fdd496
            errmsg = "Message too long";
Packit Service fdd496
            break;
Packit Service fdd496
          case 116 /* ENETDOWN */:
Packit Service fdd496
            errmsg = "Network is down";
Packit Service fdd496
            break;
Packit Service fdd496
          case 117 /* ENETRESET */:
Packit Service fdd496
            errmsg = "Network dropped connection on reset";
Packit Service fdd496
            break;
Packit Service fdd496
          case 118 /* ENETUNREACH */:
Packit Service fdd496
            errmsg = "Network is unreachable";
Packit Service fdd496
            break;
Packit Service fdd496
          case 119 /* ENOBUFS */:
Packit Service fdd496
            errmsg = "No buffer space available";
Packit Service fdd496
            break;
Packit Service fdd496
          case 123 /* ENOPROTOOPT */:
Packit Service fdd496
            errmsg = "Protocol not available";
Packit Service fdd496
            break;
Packit Service fdd496
          case 126 /* ENOTCONN */:
Packit Service fdd496
            errmsg = "Transport endpoint is not connected";
Packit Service fdd496
            break;
Packit Service fdd496
          case 128 /* ENOTSOCK */:
Packit Service fdd496
            errmsg = "Socket operation on non-socket";
Packit Service fdd496
            break;
Packit Service fdd496
          case 129 /* ENOTSUP */:
Packit Service fdd496
            errmsg = "Not supported";
Packit Service fdd496
            break;
Packit Service fdd496
          case 130 /* EOPNOTSUPP */:
Packit Service fdd496
            errmsg = "Operation not supported";
Packit Service fdd496
            break;
Packit Service fdd496
          case 132 /* EOVERFLOW */:
Packit Service fdd496
            errmsg = "Value too large for defined data type";
Packit Service fdd496
            break;
Packit Service fdd496
          case 133 /* EOWNERDEAD */:
Packit Service fdd496
            errmsg = "Owner died";
Packit Service fdd496
            break;
Packit Service fdd496
          case 134 /* EPROTO */:
Packit Service fdd496
            errmsg = "Protocol error";
Packit Service fdd496
            break;
Packit Service fdd496
          case 135 /* EPROTONOSUPPORT */:
Packit Service fdd496
            errmsg = "Protocol not supported";
Packit Service fdd496
            break;
Packit Service fdd496
          case 136 /* EPROTOTYPE */:
Packit Service fdd496
            errmsg = "Protocol wrong type for socket";
Packit Service fdd496
            break;
Packit Service fdd496
          case 138 /* ETIMEDOUT */:
Packit Service fdd496
            errmsg = "Connection timed out";
Packit Service fdd496
            break;
Packit Service fdd496
          case 140 /* EWOULDBLOCK */:
Packit Service fdd496
            errmsg = "Operation would block";
Packit Service fdd496
            break;
Packit Service fdd496
          default:
Packit Service fdd496
            errmsg = NULL;
Packit Service fdd496
            break;
Packit Service fdd496
          }
Packit Service fdd496
        if (errmsg != NULL)
Packit Service fdd496
          ret = safe_copy (buf, buflen, errmsg);
Packit Service fdd496
      }
Packit Service fdd496
#endif
Packit Service fdd496
Packit Service fdd496
    if (ret == EINVAL && !*buf)
Packit Service fdd496
      snprintf (buf, buflen, "Unknown error %d", errnum);
Packit Service fdd496
Packit Service fdd496
    errno = saved_errno;
Packit Service fdd496
    return ret;
Packit Service fdd496
  }
Packit Service fdd496
}