web-dev-qa-db-fra.com

Comment implémenter la lecture de lecture pour trouver le chemin

Utilisation de la fonction Readlink utilisée comme solution à Comment puis-je trouver l'emplacement de l'exécutable en C? , comment puis-je obtenir le chemin dans un tableau de charret? En outre, qu'est-ce que les variables BUF et BUFSIZE représentent et comment puis-je les initialiser?

EDIT: J'essaie d'obtenir le chemin du programme en cours d'exécution, tout comme la question liée ci-dessus. La réponse à cette question a dit d'utiliser readlink("proc/self/exe"). Je ne sais pas comment mettre en œuvre cela dans mon programme. J'ai essayé:

char buf[1024];  
string var = readlink("/proc/self/exe", buf, bufsize);  

Ceci est évidemment incorrect.

24
a sandwhich

Ceci tilisez correctement la fonction Readlink () pour les utilisations correctes de la fonction readlink.

Si vous avez votre chemin dans un std::string, tu pourrais faire quelque chose comme ça:

#include <unistd.h>
#include <limits.h>

std::string do_readlink(std::string const& path) {
    char buff[PATH_MAX];
    ssize_t len = ::readlink(path.c_str(), buff, sizeof(buff)-1);
    if (len != -1) {
      buff[len] = '\0';
      return std::string(buff);
    }
    /* handle error condition */
}

Si vous n'êtes qu'après un chemin fixe:

std::string get_selfpath() {
    char buff[PATH_MAX];
    ssize_t len = ::readlink("/proc/self/exe", buff, sizeof(buff)-1);
    if (len != -1) {
      buff[len] = '\0';
      return std::string(buff);
    }
    /* handle error condition */
}

Pour l'utiliser:

int main()
{
  std::string selfpath = get_selfpath();
  std::cout << selfpath << std::endl;
  return 0;
}
38
Mat

Regardons quoi le manoir dit:

 readlink() places the contents of the symbolic link path in the buffer
 buf, which has size bufsiz.  readlink does not append a NUL character to
 buf.

D'ACCORD. Devrait être assez simple. Compte tenu de votre tampon de 1024 caractères:

 char buf[1024];

 /* The manpage says it won't null terminate.  Let's zero the buffer. */
 memset(buf, 0, sizeof(buf));

 /* Note we use sizeof(buf)-1 since we may need an extra char for NUL. */
 if (readlink("/proc/self/exe", buf, sizeof(buf)-1) < 0)
 {
    /* There was an error...  Perhaps the path does not exist
     * or the buffer is not big enough.  errno has the details. */
    perror("readlink");
    return -1;
 }
4
asveikau

Accepté réponse est presque correcte, sauf que vous ne pouvez pas compter sur PATH_MAX parce qu'il est

non garantie à définir par le système POSIX si ne pas cette limite.

(De readlink (2) manpage)

De plus, quand il est défini, il ne représente pas toujours la limite " true ". (Voir http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )

La page de manuel de l'readlink donnent également une façon de le faire sur symlink:

L'utilisation d'un tampon statiquement taille peut ne pas fournir assez de place pour le contenu du lien symbolique. La taille requise pour le tampon peut être obtenu à partir de la valeur de stat.st_size renvoyé par un appel à lstat (2) sur le lien. Cependant, le nombre d'octets écrits par readlink () et linkat en lecture () doit être vérifié pour vous assurer que la taille du lien symbolique n'a pas augmenté entre les appels.

Toutefois, dans le cas de/proc/self/exe/comme pour la plupart des fichiers/proc, stat.st_size serait 0. La seule solution restante que je vois est de redimensionner le tampon alors qu'il ne correspond pas.

Je suggère l'utilisation de vector<char> Suivre comme à cette fin:

std::string get_selfpath()
{
    std::vector<char> buf(400);
    ssize_t len;

    do
    {
        buf.resize(buf.size() + 100);
        len = ::readlink("/proc/self/exe", &(buf[0]), buf.size());
    } while (buf.size() == len);

    if (len > 0)
    {
        buf[len] = '\0';
        return (std::string(&(buf[0])));
    }
    /* handle error */
    return "";
}
3
Wddysr
char *
readlink_malloc (const char *filename)
{
  int size = 100;
  char *buffer = NULL;

  while (1)
    {
      buffer = (char *) xrealloc (buffer, size);
      int nchars = readlink (filename, buffer, size);
      if (nchars < 0)
        {
          free (buffer);
          return NULL;
        }
      if (nchars < size)
        return buffer;
      size *= 2;
    }
}

Tiré de: http://www.delorie.com/gnu/docs/glibc/libc_279.html

2
onelineproof
#include <stdlib.h>
#include <unistd.h>

static char *exename(void)
{
    char *buf;
    char *newbuf;
    size_t cap;
    ssize_t len;

    buf = NULL;
    for (cap = 64; cap <= 16384; cap *= 2) {
        newbuf = realloc(buf, cap);
        if (newbuf == NULL) {
            break;
        }
        buf = newbuf;
        len = readlink("/proc/self/exe", buf, cap);
        if (len < 0) {
            break;
        }
        if ((size_t)len < cap) {
            buf[len] = 0;
            return buf;
        }
    }
    free(buf);
    return NULL;
}

#include <stdio.h>

int main(void)
{
    char *e = exename();
    printf("%s\n", e ? e : "unknown");
    free(e);
    return 0;
}

Cela utilise le traditionnel "lorsque vous ne connaissez pas la bonne taille du tampon, réaffectant des pouvoirs croissants de deux" astuces. Nous supposons que l'allocation de moins de 64 octets pour un chemin de chemin ne vaut pas l'effort. Nous supposons également qu'un chemin d'accès exécutable tant que des octets de 16384 (2 ** 14) doit indiquer une sorte d'anomalie dans la manière dont le programme a été installé, et il n'est pas utile de connaître le chemin de chemin alors que nous rencontrerons bientôt des problèmes plus importants à s'inquiéter. À propos.

Il n'est pas nécessaire de déranger avec les constantes comme PATH_MAX. Réservez tant de mémoire est surchargée pour presque tous les chemins de match, et comme indiqué dans une autre réponse, il n'est pas garanti d'être la limite supérieure réelle de toute façon. Pour cette application, nous pouvons choisir une limite supérieure de bon sens, telle que 16384. Même pour les applications sans limite supérieure de sens commun, la réaffectation de pouvoirs croissants de deux est une bonne approche. Vous n'avez besoin que de log n Appelle à un résultat n-octet, et la quantité de capacité de mémoire que vous gaspillez est proportionnelle à la longueur du résultat. Il évite également les conditions de course lorsque la longueur de la chaîne change entre la fonction realloc() et la fonction readlink().

0
Lassi