How to check if file is executable in C++?
Asked Answered
N

7

3

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

Nascent answered 19/4, 2011 at 16:36 Comment(3)
"executable", what does it mean for you? E.g. Python script file (with shebang like #!/usr/bin/python)?Comstock
Duplicate of your earlier post? #5719938Candracandy
stat() for example?Circumspection
P
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.

Pasto answered 19/4, 2011 at 16:48 Comment(4)
This is probably a better solution than mine; I had forgotten about access().Merell
Are you saying that access() is not implemented by itself doing a stat() and getpid(), getuid(), getgid()? I would imagine that the overhead is pretty much the same.Lettie
The implementation of access() is unknown. But that's not what I said - filling out a stat struct has a cost.Pasto
This will return true for a directory.Giesecke
M
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;
}
Merell answered 19/4, 2011 at 16:42 Comment(2)
But this answers "can someone execute the file?" not "can I execute the file?" Perhaps the OP should consider access(2).Cumulative
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.Lettie
T
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.

Taurine answered 19/4, 2011 at 17:26 Comment(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.Cumulative
R
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.

Rodi answered 19/4, 2011 at 16:41 Comment(0)
B
3

You probably want to look at stat

Breathing answered 19/4, 2011 at 16:41 Comment(0)
S
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");
    }
}
Swanhildas answered 19/4, 2011 at 16:55 Comment(1)
@Blender - according to developer.apple.com, yes, this will work on Mac OS X.Cumulative
G
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);
}
Giesecke answered 4/5, 2023 at 19:59 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.