So I have a path to file. How to check if it is executable? (unix, C++)
-
"executable", what does it mean for you? E.g. Python script file (with shebang like #!/usr/bin/python)? – c-smile Apr 19 '11 at 16:41
-
Duplicate of your earlier post? http://stackoverflow.com/questions/5719438/how-to-find-out-if-path-leads-to-executable-file – Void - Othman Apr 19 '11 at 16:56
-
`stat()` for example? – Jesper Juhl May 04 '23 at 21:47
7 Answers
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.

- 14,495
- 5
- 33
- 67
-
1This is probably a better solution than mine; I had forgotten about `access()`. – David R Tribble Apr 19 '11 at 17:01
-
2Are 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. – Alexis Wilke Jun 09 '14 at 00:13
-
The implementation of access() is unknown. But that's not what I said - filling out a stat struct has a cost. – Paul Beckingham Jun 18 '14 at 21:06
-
1
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;
}

- 11,918
- 5
- 42
- 52
-
2But 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
-
1Note 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
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.

- 1,238
- 8
- 12
-
1I'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
You would have to call the POSIX function stat(2)
and examine st_mode
field of the stuct stat
object it would fill in.

- 46,567
- 13
- 103
- 169
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");
}
}

- 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
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);
}

- 118,144
- 57
- 340
- 684