【问题标题】:st_mode not returning expected values for S_IXXX comparisonst_mode 未返回 S_IXXX 比较的预期值
【发布时间】:2021-06-30 09:04:23
【问题描述】:

我有一个函数(理想情况下)只模拟 ls -l 命令的一部分。它旨在返回文件的权限和文件的名称。我真的不关心任何其他信息。它也不是最干净的,因为我一直在使用 VIM 编辑器,而且它的用户友好性明显低于现代 IDE。

代码:

#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <fcntl.h>

void ls_l(const char *path){
        DIR *dir;
        struct dirent *file;
    struct stat fileStat;
        dir = opendir(path);
    if(!dir) {
        printf("opendir failed\n");
        return;
    }
    
    while (((file = readdir(dir)) != NULL)){
        char path2[255];
        sprintf(path2, "%s/%s", path, file->d_name);
        printf("%s\n", path2);
                
        if(lstat(path2, &fileStat)) {
            printf("lstat failed\n");
            return;
        }
        //User permissions
        
        printf( (fileStat.st_mode & S_IRUSR) ? " r" : " -");
        printf( (fileStat.st_mode & S_IWUSR) ? "w" : "-");  
        printf( (fileStat.st_mode & S_IXUSR) ? "x" : "-");
            //Group permissions
        printf( (fileStat.st_mode & S_IRGRP) ? "r" : "-");
        printf( (fileStat.st_mode & S_IWGRP) ? "w" : "-");
        printf( (fileStat.st_mode & S_IXGRP) ? "x" : "-");
            //Other permissions
        printf( (fileStat.st_mode & S_IROTH) ? "r" : "-");
        printf( (fileStat.st_mode & S_IWOTH) ? "w" : "-");
        printf( (fileStat.st_mode & S_IXOTH) ? "x | " : "- | ");

    }
}

void doStep(int stepNum){
    chdir("dir0");
    char cwd[PATH_MAX];
    if(getcwd(cwd, sizeof(cwd)) != NULL){
        printf("CWD: %s\n", cwd);
    }
    else{
        printf("getcwd() error");
    }

    switch (stepNum){
        case 1:
            printf("Display files and permissions for ./dir0\n");   
            ls_l(cwd);
        break;
        
        case 2:
            printf("Change permission for file6.txt to -rwxrwx---\n");
            chmod("./file6.txt", S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP |
                S_IWGRP | S_IXGRP);
        break;
        
        case 3:
            printf("Remove file1.txt and file2.txt from directory dir1\n");
        break;

        case 4:
            printf("Remove dir1 directory\n");
        break;

        case 5:
            printf("Display files and permission for ./dir0\n");

        break;
    }
}

int main(){
    int i;
    for (i = 1; i < 2; i++){
        doStep(i);
    }
    return 0;
}

我只是通过用户和组权限,我已经注意到代码存在严重问题。无论出于何种原因,组权限无法随每个文件更改,因此不会返回正确的值。我之所以知道这一点,是因为更改文件的权限并使用 ls -l 检查返回给我的值与我的代码不同。

我知道这不是一个完整的程序,因为我还没有完成它,但它可以在我学校的 UNIX 服务器上编译和运行,所以它应该足以进行任何测试。

我还希望在我注意到此错误之前,案例 2 从未运行过,所以如果您也想帮助解决这个问题,我将不胜感激。

编辑:我用它来编译: ''' gcc task13prog.c -o task13prog '''

文件结构为/dir0,其中包含目录/dir1 和/dir2,一个名为file6.txt 的常规文件,以及一个名为link5 的符号链接。我或多或少完全关心这个文件结构,而且只关心这个文件结构。

Allan Wind 要求的输出 稍作修改以删除用户名数据

{cslinux1:~/cs3377/project2} pwd
/home/013/t/tm/***/cs3377/project2
{cslinux1:~/cs3377/project2} ./task13prog
CWD: /home/013/t/tm/***/cs3377/project2/dir0
Display files and permissions for ./dir0
/home/013/t/tm/***/cs3377/project2/dir0/.
 rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/..
 rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/link5
 rwxrwxrwx | /home/013/t/tm/***/cs3377/project2/dir0/dir2
 rwx--x--x | /home/013/t/tm/***/cs3377/project2/dir0/file6.txt
 rwxrwxrwx | /home/013/t/tm/***/cs3377/project2/dir0/dir1
 rwx--x--x | {cslinux1:~/cs3377/project2} ls -l dir0
total 112
drwx--x--x 2 *** sn 54 Apr  3 18:38 dir1
drwx--x--x 2 *** sn 54 Apr  3 18:38 dir2
-rwxrwxrwx 1 *** sn  0 Apr  3 18:38 file6.txt
lrwxrwxrwx 1 *** sn 14 Apr  3 18:38 link5 -> dir2/file4.txt
{cslinux1:~/cs3377/project2}

最终编辑: 标记为正确的解决方案实际上是正确的。在新的 linux 系统上进行测试后,该解决方案按预期运行。看来原来的环境有错误,导致我无法对权限进行更改和准确读取权限。

【问题讨论】:

  • 由于某种原因,组权限无法随每个文件更改,因此不会返回正确的值。您调用了多少次 @987654324 的某个版本@ 到 get 那些权限?
  • @AndrewHenle 我知道我在删除旧代码时不小心删除了一行。我用 lstat 函数更新了我的帖子,但它仍然不起作用。 (lstat() 命令仍在我的代码中,只是一个错误的复制/粘贴)
  • `lstat(".", &fileStat);` 没有意义 硬编码的目录结构让你很烦,因为你必须阅读代码然后重新创建目录结构。
  • lstat(file-&gt;d_name, &amp;fileStat) 返回什么?它可能是 -1,因为文件名是相对于 dir0 但那不是你的工作目录。
  • 还需要匹配的 ls -l 输出。另外,使用 PATH_MAX 而不是 255(我的错)。

标签: c unix


【解决方案1】:

我修改了您的程序以传递路径,检查您调用的函数的返回值并实施了@MarkPlotnick 提供的建议,这是您遇到问题的根本原因:

#include <limits.h>

void ls_l(const char *path){
    DIR *dir;
    struct dirent *file;
    struct stat fileStat;

    dir = opendir(path);
    if(!dir) {
        printf("opendir failed\n");
        return;
    }
    while (((file = readdir(dir)) != NULL)){
        char path2[PATH_MAX];
        // if path contains a trailing /, you will end up with //
        // in path2 which is ugly but works fine.  You could special case that,
        // and also special case ./ not being copied into path2
        snprintf(path2, PATH_MAX, "%s/%s", path, file->d_name);
        printf("%s\n", path2);

        if(lstat(path2, &fileStat)) {
            printf("lstat failed\n");
            return;
        }
     ...

至于第2步,它适用于我,所以你只需要确保file6.txtdir0/目录中。

【讨论】:

  • 用您当前的代码更新您的问题。还包括来自相关目录的pwd; ls -l 的输出。它对我有用,因此您没有正确进行这些更改,或者您正在寻找错误的路径。
  • 您的代码对我帮助很大,因为如果路径中有任何错误,我现在会收到错误消息。但是,比较仍然发回不正确的值。例如,在确认目录的权限时(使用 ls -l),我得到了权限 rwx--x--x,但代码返回了 rwxrwxrwx。
  • 按要求更新
  • fstatat(dirfd(dir), file-&gt;d_name, ...代替sprintf+lstat
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-04
  • 2016-02-13
  • 2015-06-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多