web-dev-qa-db-fra.com

Comment convertir errno sous UNIX en chaîne correspondante?

Existe-t-il une fonction sous UNIX pour convertir l'errno en sa chaîne correspondante, par exemple EIDRM à "EIDRM". C'est très ennuyeux de déboguer pour vérifier les erreurs avec ces errnos entiers.

39
avd

strerror() devrait le faire. http://linux.die.net/man/3/strerror

Pour votre information, afin que vous puissiez trouver ces choses plus facilement, vous-même: si vous tapez man errno (ou quelle que soit la fonction que vous étudiez) et regardez tout en bas de la page de manuel, vous verrez une liste de fonctions connexes. Si vous man chacun de ceux-ci (en devinant lequel (s) faire en premier en fonction de leurs noms), vous trouverez souvent la réponse à des questions similaires.

69
atk

Juste une autre solution qui résout exactement le problème que vous avez, mais en Python au lieu de C:

>>> import errno
>>> errno.errorcode[errno.EIDRM]
'EIDRM'
12

Il y a maintenant un utilitaire errno distribué avec le paquet moreutils.

5
Stephen Niedzielski

Je ne suis pas sûr de ces noms de style enum, mais à des fins de débogage et de rapport d'erreurs, vous pouvez utiliser perror(3) ou strerror(3) Fonctions C qui renvoient une représentation lisible par l'homme du code d'erreur. Veuillez vous référer aux pages de manuel pour plus de détails.

4

Si vous voulez en effet EIDRM et non sa chaîne d'erreur: non. Cependant, sur OpenBSD,

man errno|egrep ' [0-9]+ E[A-Z]+'|sed 's/^ *//'|cut -d' ' -f1,2

imprime un joli tableau de "...\n89 EIDM\n ..." que vous pouvez convertir en une structure de données pour le langage de programmation dans lequel vous souhaitez avoir cette fonction.

3
ayrnieu

Il n'y a pas de fonction standard pour le faire sous UNIX.

Mais j'ai récemment écrit la bibliothèque errnoname qui a une fonction errnoname qui fait exactement cela.

strerror (également strerror_r, strerror_l, perror) affiche une indication "conviviale" sur l'erreur, mais leurs sorties sont

  • généralement sans papiers,
  • non standardisé,
  • pas garanti de suivre les contraintes de longueur ou de format,
  • souvent différent selon les paramètres régionaux, et
  • n'ont pas toujours de sens dans toutes les situations (par exemple, ils ont tendance à imprimer File exists pour EEXIST, même si cette erreur est souvent renvoyée pour des choses qui ne sont pas des fichiers ).

Ce qui signifie qu'ils sont superficiellement conviviaux mais

  • un autre code ne peut pas les analyser de manière fiable (pire pour l'automatisation, la surveillance, les scripts, les programmes wrapper, etc.),
  • peut induire en erreur dans les cas Edge, et
  • gêner les utilisateurs techniques expérimentés.

Ironiquement, il n'y a rien qui empêche ces fonctions d'utiliser simplement le nom symbolique errno comme chaîne d'erreur dans toutes les circonstances - ce serait dans la lettre de la norme, surtout si elles ne l'a fait pour une locale spécifique, comme la locale spéciale C. Mais aucune bibliothèque à ma connaissance ne fait cela.

Quoi qu'il en soit, puisque mon errnoname est publié sous la "licence BSD Zero-Clause" (0BSD), qui est une licence permissive, ou plus précisément une licence équivalente du domaine public, vous pouvez en faire ce que vous voulez .

Pour rendre cette réponse autonome, tout en restant dans les limites des caractères de réponse, voici deux variantes abrégées de la fonction errnoname.

Dans errnoname, ils sont tous deux implémentés, mais ici, j'ai séparé le Gist de chacun pour les rendre plus lisibles.

Quelques notes:

  1. Cela couvre la totalité ou la plupart des noms de errno pour Linux, Darwin (Mac OS X et iOS X), FreeBSD, NetBSD, OpenBSD, DragonflyBSD et plusieurs Unix à source fermée, à partir de début janvier 2020.

  2. Il renvoie un pointeur nul si vous lui donnez une valeur errno dont il ne connaît pas le nom.

Variante 1: simple, universelle

Celui-ci est très portable et simple, sans étuis Edge à s'inquiéter. Il compilera avec à peu près n'importe quel compilateur C89 ou meilleur que vous pouvez lui lancer. (Probablement même les compilateurs C++, qui deviennent de plus en plus rares à mesure que les langages divergent.)

Cette variante peut compiler en code très efficace (une recherche de tableau au lieu d'une instruction switch) sur les compilateurs modernes lorsque les optimisations sont suffisamment élevées, mais peut ne dépend pas de la situation exacte.

#include <errno.h>

char const * errnoname(int errno_)
{
    switch(errno_)
    {
#ifdef E2BIG
        case E2BIG: return "E2BIG";
#endif
#ifdef EACCES
        case EACCES: return "EACCES";
#endif
/*
    repeat for the other 100+ errno names,
    don't forget to handle possible duplicates
    like EAGAIN and EWOULDBLOCK
*/
    }
    return 0;
}

Variante 2: explicitement efficace, bon pour la plupart des systèmes

Celui-ci est plus efficace évidemment, et compilera en code efficace de manière très fiable, car il rend la recherche de tableau explicite et ne dépend pas des optimisations de l'ordinateur.

Il est sûr à utiliser tant que le système a des valeurs errno positives, relativement petites et raisonnablement contiguës.

Peut uniquement compiler sur des compilateurs qui implémentent des initialiseurs désignés hors service pour les tableaux (C99 ou mieux, à l'exclusion de toutes les versions C++ jusqu'à présent.)

#include <errno.h>

char const * errnoname(int errno_)
{
    static char const * const names[] =
    {
#ifdef E2BIG
        [E2BIG] = "E2BIG",
#endif
#ifdef EACCES
        [EACCES] = "EACCES",
#endif
/*
    repeat for the other 100+ errno names,
    don't forget to handle possible duplicates
    like EAGAIN and EWOULDBLOCK
*/
    };
    if(errno_ >= 0 && errno_ < (sizeof(names) / sizeof(*names)))
    {
        return names[errno_];
    }
    return 0;
}
1
mtraceur