Search code examples
c++osx-mavericksportingc++03darwin

What is the equivalent of /proc/self/exe on Macintosh OS X Mavericks?


I'm porting a Linux C++03 application to Darwin OS X and have some code that reads the symbolic link at /proc/self/exe to determine the directory in which the executable running is located.

How can I compute the directory of the current executable running on Macintosh Darwin OS X Mavericks in C++?

Here is my existing code that works on Linux:

bool
resolveBinaryLocation(string &binaryDirname)
{
  // Read the symbolic link '/proc/self/exe'.
  const char *linkName = "/proc/self/exe";
  const size_t bufSize = PATH_MAX + 1;
  char dirNameBuffer[bufSize];
  const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));

  if (ret == -1) {
    // Permission denied (We must be inetd with this app run as other than root).
    return false;
  }

  dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.

  binaryDirname = dirNameBuffer;

  // Erase the name of the executable:
  string::size_type last = binaryDirname.size() - 1;
  string::size_type idx  = binaryDirname.rfind(DSI_PATH_CHAR, last);

  // Add one to keep the trailing directory separator.
  binaryDirname.erase(idx + 1);

  return true;
}

Solution

  • Here is what I settled upon as a solution:

    bool
    resolveBinaryLocation(string &binaryDirname)
    {
      const size_t bufSize = PATH_MAX + 1;
      char dirNameBuffer[bufSize];
    
    #ifdef __APPLE__
      uint32_t size = bufSize;
    
      if (_NSGetExecutablePath(dirNameBuffer, &size) != 0) {
        // Buffer size is too small.
        return false;
      }
    #else // not __APPLE__
      // Read the symbolic link '/proc/self/exe'.
      const char *linkName = "/proc/self/exe";
      const int ret = int(readlink(linkName, dirNameBuffer, bufSize - 1));
    
      if (ret == -1) {
        // Permission denied (We must be inetd with this app run as other than root).
        return false;
      }
        
      dirNameBuffer[ret] = 0; // Terminate the string with a NULL character.
    #endif // else not __APPLE__
    
      binaryDirname = dirNameBuffer;
    
      // Erase the name of the executable:
      string::size_type last = binaryDirname.size() - 1;
      string::size_type idx  = binaryDirname.rfind(DSI_PATH_CHAR, last);
    
      // Add one to keep the trailing directory separator.
      binaryDirname.erase(idx + 1);
    
      return true;
    }