如何在C++中检查文件是否可执行?

3

我有一个文件路径,如何检查它是否可执行?(Unix,C++)


“可执行文件”,对你来说意味着什么?例如,带有 shebang(如 #!/usr/bin/python)的 Python 脚本文件? - c-smile
你之前的帖子重复了吗?https://dev59.com/0FbTa4cB1Zd3GeqP-F99 - Void
例如stat() - Jesper Juhl
7个回答

8

访问(2):

#include <unistd.h>

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

调用stat(2)函数时,填充结构体的开销较大。除非你需要那些额外的信息。


1
这可能比我的解决方案更好;我忘记了 access() - David R Tribble
2
你是说access()函数本身没有实现stat()、getpid()、getuid()和getgid()吗?我想开销应该差不多。 - Alexis Wilke
access()的实现是未知的。但这不是我说的 - 填写stat结构有一个成本。 - Paul Beckingham
1
这将针对目录返回 true。 - einpoklum

6

检查权限(状态)位。

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

2
但这个回答是“有人可以执行这个文件吗?”而不是“我可以执行这个文件吗?”也许楼主应该考虑使用access(2) - Robᵩ
1
请注意,设置EXEC位并不意味着您可以执行文件。您还需要测试所有者和组以及如果您拥有Secure Linux,则是stat无法提供的安全设置。 - Alexis Wilke

4
在access(2)的man页面底部有一个警告:
注意:access()是一个潜在的安全漏洞,不应该使用。
请记住,在您使用路径字符串调用access()和尝试执行由路径字符串引用的文件之间存在竞争条件,文件系统可能会发生更改。如果这种竞争条件是一个问题,请首先使用open()打开文件并使用fstat()检查权限。

1
我不确定open()/fstat()是否消除了手册中描述的竞争条件。竞争的情况是,在OP的情况下,文件在access()和execv()之间可能会改变其可执行性。通过您的解决方法,它仍然可以在fstat()和execv()之间更改。我认为手册作者的意图是,你应该直接调用execv()——如果失败了,那么你就有了答案。 - Robᵩ

3

您需要调用POSIX函数stat(2)并检查它将填充的struct stat对象的st_mode字段。


3
您可能想要查看 stat

1
考虑使用access(2),它会相对于当前进程的uid和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");
    }
}

@Blender - 根据developer.apple.com的说法,是的,这将在Mac OS X上运行。 - Robᵩ

0
你可以使用这个:
#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);
}

为什么不直接使用access()呢?因为它可以接受可以递归的目录,而这些目录并非可执行文件。
如果你想更加符合标准并且可以使用C++17,可以尝试:
#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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接