GNU/Linux >> Tutoriels Linux >  >> Linux

Comment implémenter readlink pour trouver le chemin

La réponse acceptée est presque correcte, sauf que vous ne pouvez pas compter sur PATH_MAX car c'est

pas garanti d'être défini par POSIX si le système n'a pas une telle limite.

(De la page de manuel readlink(2))

De plus, lorsqu'elle est définie, elle ne représente pas toujours la "vraie" limite. (Voir http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )

La page de manuel de readlink donne également un moyen de le faire sur le lien symbolique :

L'utilisation d'un tampon de taille statique peut ne pas fournir suffisamment d'espace pour le contenu du lien symbolique. La taille requise pour le tampon peut être obtenue à partir de la valeur stat.st_size renvoyée par un appel à lstat(2) sur le lien. Cependant, le nombre d'octets écrits par readlink() et read‐linkat() doit être vérifié pour s'assurer que la taille du lien symbolique n'a pas augmenté entre les appels.

Cependant, 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 tant qu'il ne rentre pas.

Je suggère l'utilisation de vector<char> comme suit à cet effet :

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 "";
}

Utilisez correctement la fonction readlink() pour les utilisations correctes du readlink fonction.

Si vous avez votre chemin dans un std::string , vous pourriez faire quelque chose comme ceci :

#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 recherchez uniquement 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;
}

Regardons ce que dit la page de manuel :

 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. Étant donné 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;
 }

Linux
  1. Comment utiliser la commande Linux find pour rechercher des fichiers

  2. Comment trouver l'emplacement de l'exécutable en C ?

  3. comment trouver le propriétaire d'un fichier ou d'un répertoire en python

  4. Comment puis-je trouver la taille de pile maximale ?

  5. Comment diriger les résultats de 'find' vers mv sous Linux

Comment trouver le numéro de port d'un service sous Linux

Comment trouver l'adresse IP d'une machine virtuelle KVM

Comment trouver la taille totale d'un répertoire sous Linux

Comment rechercher des fichiers avec la commande fd sous Linux

Comment trouver la liste des référentiels installés sous Linux

Comment configurer le chemin JAVA_HOME dans Debian 11