readlink sets errno to ENOENT

577 Views Asked by At

I'm an inexperienced Linux programmer and am trying to learn to use readlink() based on this question and answer.

My call to readlink() returns -1 and sets errno to 2 (ENOENT).

The code:

#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#include <algorithm>
#include <cstdio>

int main(int argc, char* argv[])
{
  char szTmp[100];
  snprintf(szTmp, 100, "proc/%d/exe", getpid());
  std::cout << "szTmp is " << szTmp << std::endl;
  char executingFolder[500];
  errno = 0;
  int bytes = std::min(readlink(szTmp, executingFolder, 500), (ssize_t)499);

  if (bytes > 0)
  {
    executingFolder[bytes] = '\0';
  }

  std::cout << "bytes is " << bytes << std::endl;
  std::cout << "errno is " << errno;
  if (ENOENT == errno)
  {
    std::cout << " ENOENT";
  }
  std::cout << std::endl;
  std::cout << "Executing folder is \"" << executingFolder << "\"" << std::endl;

  return 0;
}

The output:

(An example from one iteration since pid changes)

szTmp is proc/22272/exe
bytes is -1
errno is 2 ENOENT
Executing folder is ""

Things I have tried:

  • After compilation: sudo ./a.out (thinking that directory access was restricted because of lack of permission). Result: unchanged behavior from ./a.out
  • SIGINT the program during execution, and verified that /proc/<pid>/exe exists. Result: it consistently exists for each run of the program.
  • Verified that the value of the target link is well within 499 chars.

Can someone please help identify the problem? Having read the readlink man page and online descriptions, and the noted StackOverflow article, I am still unclear what is wrong.

Thank you.

2

There are 2 best solutions below

3
On BEST ANSWER

proc/1234/exe is a relative path.

I think you want /proc/%d/exe, which is an absolute path, and correctly refers to the /proc directory.


Secondly, because readlink() will truncate the result in case the buffer is too small, you should consider the case where the return value is == bufsiz to be an error, as truncation may have happened. You can't know.


Also, "Executing folder" is not what /proc/<pid>/exe gives you. /proc/<pid>/exe is a symlink to the currently running executable (file), not a directory.

1
On

proc/22272/exe is a relative path name. It resolves to the file exe, in the directory 22272, in the directory proc, in your current directory. Unless your current directory is /, that's unlikely to exist.

You want an absolute path name, starting with /, in this case /proc/22272/exe.

Change this:

snprintf(szTmp, 100, "proc/%d/exe", getpid());

to this:

snprintf(szTmp, 100, "/proc/%d/exe", getpid());

But before you fix your program, you might try this:

( cd / ; ~/a.out )

(assuming a.out is in your home directory).