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