How to implement readlink to find the path How to implement readlink to find the path linux linux

How to implement readlink to find the path


This Use the readlink() function properly for the correct uses of the readlink function.

If you have your path in a std::string, you could do something like this:

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

If you're only after a fixed path:

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

To use it:

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


Accepted answer is almost correct, except you can't rely on PATH_MAX because it is

not guaranteed to be defined per POSIX if the system does not have such limit.

(From readlink(2) manpage)

Also, when it's defined it doesn't always represent the "true" limit. (See http://insanecoding.blogspot.fr/2007/11/pathmax-simply-isnt.html )

The readlink's manpage also give a way to do that on symlink :

Using a statically sized buffer might not provide enough room for the symbolic link contents. The required size for the buffer can be obtained from the stat.st_size value returned by a call to lstat(2) on the link. However, the number of bytes written by readlink() and read‐ linkat() should be checked to make sure that the size of the symbolic link did not increase between the calls.

However in the case of /proc/self/exe/ as for most of /proc files, stat.st_size would be 0. The only remaining solution I see is to resize buffer while it doesn't fit.

I suggest the use of vector<char> as follow for this purpose:

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


Let's look at what the manpage says:

 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.

OK. Should be simple enough. Given your buffer of 1024 chars:

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