3

So I have a path to file. How to check if it is executable? (unix, C++)

jww
  • 97,681
  • 90
  • 411
  • 885
Rella
  • 65,003
  • 109
  • 363
  • 636

7 Answers7

8

access(2):

#include <unistd.h>

if (! access (path_name, X_OK))
    // executable

Calls to stat(2) have higher overhead filling out the struct. Unless of course you need that extra information.

Paul Beckingham
  • 14,495
  • 5
  • 33
  • 67
6

Check the permissions (status) bits.

#include <sys/stat.h>

bool can_exec(const char *file)
{
    struct stat  st;

    if (stat(file, &st) < 0)
        return false;
    if ((st.st_mode & S_IEXEC) != 0)
        return true;
    return false;
}
David R Tribble
  • 11,918
  • 5
  • 42
  • 52
  • 2
    But this answers "can *someone* execute the file?" not "can *I* execute the file?" Perhaps the OP should consider [access(2)](http://linux.die.net/man/2/access). – Robᵩ Apr 19 '11 at 16:52
  • 1
    Note that the fact that the EXEC bit is set does not mean you can execute a file. You need to also test the owner and group and if you have Secure Linux then the security settings which stat does not give you. – Alexis Wilke Jun 09 '14 at 01:23
4

There is a caveat at the bottom of the man page for access(2):

CAVEAT Access() is a potential security hole and should never be used.

Keep in mind that a race condition exists between the time you call access() with a path string and the time you try to execute the file referred by the path string, the file system can change. If this race condition is a concern, first open the file with open() and use fstat() to check permissions.

jbruni
  • 1,238
  • 8
  • 12
  • 1
    I'm not sure that open()/fstat() closes the race condition that the man page describes. The race is that, in the OP's situation, the file could change its executability between access() and execv(). With your work-around, it could still change between fstat() and execv(). I think the man page authors' intent is that you ought to just go ahead and call execv() -- if it fails, then you have your answer. – Robᵩ Apr 20 '11 at 13:56
3

You would have to call the POSIX function stat(2) and examine st_mode field of the stuct stat object it would fill in.

Cubbi
  • 46,567
  • 13
  • 103
  • 169
3

You probably want to look at stat

Jay
  • 13,803
  • 4
  • 42
  • 69
1

Consider using access(2), which checks for permissions relative to the current process's uid and gid:

#include <unistd.h>
#include <stdio.h>

int can_exec(const char *file)
{
    return !access(file, X_OK);
}

int main(int ac, char **av) {
    while(av++,--ac) {
        printf("%s: %s executable\n", *av, can_exec(*av)?"IS":"IS NOT");
    }
}
Robᵩ
  • 163,533
  • 20
  • 239
  • 308
  • @Blender - according to [developer.apple.com](http://developer.apple.com/library/mac/#documentation/Darwin/Reference/ManPages/man2/access.2.html), yes, this will work on Mac OS X. – Robᵩ Apr 20 '11 at 13:53
0

You might use this:

#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

int is_executable_file(char const * file_path)
{
    struct stat sb;
    return 
        (stat(file_path, &sb) == 0) &&  
        S_ISREG(sb.st_mode) && 
        (access(file_path, X_OK) == 0);
}

Why not just access()? Since it will accept directories which can be recursed - which are not executable files.

If you want to be a little more standard-friendly and can use C++17, try:

#include <filesystem>
#include <unistd.h>

int is_executable_file(const std::filesystem::path& file_path)
{
    return 
        std::filesystem::is_regular_file(file_path) &&
        (access(file_path.c_str(), X_OK) == 0);
}
einpoklum
  • 118,144
  • 57
  • 340
  • 684