GNU/Linux >> Tutoriales Linux >  >> Linux

Cómo implementar readlink para encontrar la ruta

La respuesta aceptada es casi correcta, excepto que no puede confiar en PATH_MAX porque es

no se garantiza que se defina por POSIX si el sistema no tiene dicho límite.

(De la página de manual de readlink(2))

Además, cuando se define, no siempre representa el límite "verdadero". (Ver http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )

La página de manual del enlace de lectura también ofrece una forma de hacerlo en el enlace simbólico:

Es posible que el uso de un búfer de tamaño estático no proporcione suficiente espacio para el contenido del enlace simbólico. El tamaño requerido para el búfer se puede obtener del valor stat.st_size devuelto por una llamada a lstat(2) en el enlace. Sin embargo, la cantidad de bytes escritos por readlink() y read-linkat() debe verificarse para asegurarse de que el tamaño del enlace simbólico no aumente entre las llamadas.

Sin embargo, en el caso de /proc/self/exe/ como para la mayoría de los archivos /proc, stat.st_size sería 0. La única solución restante que veo es cambiar el tamaño del búfer mientras no encaja.

Sugiero el uso de vector<char> como sigue para este propósito:

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

Esto Use la función readlink() correctamente para los usos correctos del readlink función.

Si tienes tu camino en un std::string , podrías hacer algo como esto:

#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 solo busca una ruta fija:

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 */
}

Para usarlo:

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

Veamos lo que dice la página de manual:

 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.

ESTÁ BIEN. Debería ser lo suficientemente simple. Dado su búfer de 1024 caracteres:

 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. Cómo encontrar si el disco es SSD o HDD en Linux

  2. Cómo auditar permisos con el comando de búsqueda

  3. Cómo usar el comando find de Linux para buscar archivos

  4. ¿Cómo encontrar la ruta de instalación de git en Mac o Linux?

  5. ¿Cómo encuentro el UUID de un sistema de archivos?

Cómo encontrar el número de puerto de un servicio en Linux

Cómo encontrar la dirección IP de una máquina virtual KVM

Cómo encontrar el tamaño total de un directorio en Linux

Cómo encontrar archivos con el comando fd en Linux

Cómo encontrar la lista de repositorios instalados en Linux

Cómo configurar la ruta JAVA_HOME en Debian 11