Sharath
Sharath

Reputation: 1775

How to find the full path of the C++ Linux program from within?

I have this requirement where I need to find the full path for the C++ program from within. For Windows, I have the following solution. The argv[0] may or may not contain the full path. But I need to be certain.

TCHAR drive[_MAX_DRIVE], dir[_MAX_DIR], base[_MAX_FNAME], ext[_MAX_EXT];
TCHAR fullPath[255+1];
_splitpath(argv[0],drive,dir,base,ext);
SearchPath(NULL,base,ext,255,fullPath,NULL);

What is the Linux (gcc) equivalent for the above code? Would love to see a portable code.

Upvotes: 16

Views: 27113

Answers (6)

MetallicPriest
MetallicPriest

Reputation: 30735

string get_path( )
{
        char arg1[20];
        char exepath[PATH_MAX + 1] = {0};

        sprintf( arg1, "/proc/%d/exe", getpid() );
        readlink( arg1, exepath, PATH_MAX );
        return string( exepath );
}

Upvotes: 6

olooney
olooney

Reputation: 2483

The top answer to this question lists techniques for a whole bunch of OSes.

Upvotes: 8

suspic
suspic

Reputation: 51

#include <string>
#include <unistd.h>
#include <limits.h>

std::string getApplicationDirectory() {
    char result[ PATH_MAX ];
    ssize_t count = readlink( "/proc/self/exe", result, PATH_MAX );
    std::string appPath = std::string( result, (count > 0) ? count : 0 );

    std::size_t found = appPath.find_last_of("/\\");
    return appPath.substr(0,found);
}

Upvotes: 1

user541686
user541686

Reputation: 210352

If you came here when Googling for GetModuleFileName Linux... you're probably looking for the ability to do this for dynamically-loaded libraries. This is how you do it:

struct link_map *lm;
dlinfo(module, RTLD_DI_LINKMAP, &lm);
lm->l_name  // use this

Upvotes: 1

ETech
ETech

Reputation: 1607

For Linux:
Function to execute system command

int syscommand(string aCommand, string & result) {
    FILE * f;
    if ( !(f = popen( aCommand.c_str(), "r" )) ) {
            cout << "Can not open file" << endl;
            return NEGATIVE_ANSWER;
        }
        const int BUFSIZE = 4096;
        char buf[ BUFSIZE ];
        if (fgets(buf,BUFSIZE,f)!=NULL) {
            result = buf;
        }
        pclose( f );
        return POSITIVE_ANSWER;
    }

Then we get app name

string getBundleName () {
    pid_t procpid = getpid();
    stringstream toCom;
    toCom << "cat /proc/" << procpid << "/comm";
    string fRes="";
    syscommand(toCom.str(),fRes);
    size_t last_pos = fRes.find_last_not_of(" \n\r\t") + 1;
    if (last_pos != string::npos) {
        fRes.erase(last_pos);
    }
    return fRes;
}

Then we extract application path

    string getBundlePath () {
    pid_t procpid = getpid();
    string appName = getBundleName();
    stringstream command;
    command <<  "readlink /proc/" << procpid << "/exe | sed \"s/\\(\\/" << appName << "\\)$//\"";
    string fRes;
    syscommand(command.str(),fRes);
    return fRes;
    }

Do not forget to trim the line after

Upvotes: 1

Kerrek SB
Kerrek SB

Reputation: 476940

On Linux (Posix?) you have a symbolic link /proc/self/exe which links to the full path of the executable.

On Windows, use GetModuleFileName.

Never rely on argv[0], which is not guaranteed to be anything useful.

Note that paths and file systems are not part of the language and thus necessarily a platform-dependent feature.

Upvotes: 18

Related Questions