【问题标题】:C how to find executable files only within given directory? [closed]C如何仅在给定目录中查找可执行文件? [关闭]
【发布时间】:2021-06-03 21:39:15
【问题描述】:

我正在编写一个模仿 UNIX shell 的 c 编程,我想知道是否有办法在特定目录中找到可执行文件(命令文件)

【问题讨论】:

  • 如果您的目标是一台带有 POSIX 扩展的机器,opendirectfstat?

标签: c shell


【解决方案1】:

通过可执行文件,我假设您正在查找不是设置了执行标志的目录的任何文件。
实现目标的一种方法是:

  1. 通过opendir获取目录对应的目录流。
  2. 使用 readdir 遍历目录流。
  3. 在每次迭代中,找到文件的绝对路径,可以通过连接目录路径和文件名来计算(可以通过访问dirent结构体的d_name获得),将此路径传递给stat ,并使用 inode documentation 中指定的位掩码检查执行权限。

代码:

#include <stdio.h>
#include <sys/types.h> //opendir, stat
#include <dirent.h> //opendir
#include <errno.h>
#include <string.h>
#include <sys/stat.h> //stat
#include <stdlib.h> //free, malloc

int main(int argc, char** argv) {
    if (argc < 2) {
        fprintf(stderr, "Usage: ./a.out path_to_a_directory \n");
        return 1;
    }
    char* path_to_directory = argv[1];
    int path_length = strlen(path_to_directory);
    int modified = 0;
    //Modify path so that a dash is at the end.
    if (path_to_directory[path_length - 1] != '/') {
        char* modified_path = (char *) malloc(sizeof(char) * (strlen(path_to_directory) + 2));
        //Copies the null character as well.
        strcpy(modified_path, path_to_directory);
        modified_path[path_length] = '/';
        modified_path[path_length + 1] = '\0';
        path_to_directory = modified_path;
        //Set flag to true so that the dynamically allocated memory is freed later.
        modified = 1;
    }

    //Get the directory stream corresponding to the directory. 
    DIR* in_directory_stream = opendir(path_to_directory);
    if (in_directory_stream == NULL) {
        fprintf(stderr, "Error: the specified directory cannot be found or opened. \n", errno);
        if (modified) free(path_to_directory);
        return 1;
    }
    dirent* entry = NULL; 
    printf("Files that are executable by at least one of the permission classes (owner, group, others) are: \n");
    while ((entry = readdir(in_directory_stream)) != NULL) {
        //All directories contain . and .., which corresponds to current and parent directory respectively,
        //in unix systems. Since we are looking for only executable files, we can ignore them. 
        if (!strcmp(".", entry->d_name)) {
            continue;
        }
        if (!strcmp("..", entry->d_name)) {
            continue;
        }
        //Get file information. 
        struct stat entry_info;
        /* Create the absolute path of the entry.
         * Without it, as mentioned by Shawn below, 
         * stat will look for a file with the entry's name in current working directory 
         * instead of the specified directory. 
         */
        char* entry_absolute_path  = (char *) malloc(sizeof(char) * (strlen(path_to_directory) 
                    + strlen(entry->d_name) + 1));
        strcat(entry_absolute_path, path_to_directory);
        strcat(entry_absolute_path, entry->d_name);       
       if (stat(entry_absolute_path, &entry_info) == -1) {
            fprintf(stderr, "Error in obtaining file information about %s\n", entry->d_name);
       } else {
           // Check if the file is not a directory and 
           // is executable by one of the permission classes (owner, group, others). 
           if (((entry_info.st_mode & S_IFMT) != S_IFDIR) && 
                   ((entry_info.st_mode & S_IXUSR) || (entry_info.st_mode & S_IXGRP) 
                   || (entry_info.st_mode & S_IXOTH))) {
               printf("%s\n", entry->d_name);
           }
       } 
           free(entry_absolute_path);
    }
    //Close directory stream.
    closedir(in_directory_stream);    
    if (modified) free(path_to_directory);
    return 0;


}

编辑:更正了程序以将文件的绝对路径传递给stat。在此编辑之前,stat 仅给出了文件名,导致程序仅搜索当前工作目录。 Shawn 识别的错误

【讨论】:

  • 必须考虑到dirent 结构中的文件名不包含目录。 stat() 也需要这个。
  • dirent 结构中的文件名不包含目录”是什么意思?我的理解是,如果一个目录包含一个子目录,当我们遍历目录流时,我们会得到一个与该子目录对应的dirent struct。
  • 如果你opendir() "/foo/bar/",文件名前面没有/foo/bar/,所以除非你正在扫描你当前的工作目录,否则stat()会失败除非 cwd 中恰好存在同名的文件——在这种情况下,它会查看错误的文件。
  • 更多信息请见this question and answers
  • 感谢您发现该错误。我已经更正了上面的程序。
猜你喜欢
  • 2019-07-13
  • 2017-10-14
  • 2013-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-09
  • 2015-01-01
  • 1970-01-01
相关资源
最近更新 更多