stat系统调用的st_mode的标志

时间:2011-06-30 02:10:02

标签: c unix filesystems stat

我正在尝试理解该stat命令的stat结构的st_mode字段的标志,但是我有这么难的时间!我找到了这个例子here,但我真的不明白这个代码片段:

if ( mode & S_IRUSR ) str[1] = 'r';    /* 3 bits for user  */
if ( mode & S_IWUSR ) str[2] = 'w';
if ( mode & S_IXUSR ) str[3] = 'x';

if ( mode & S_IRGRP ) str[4] = 'r';    /* 3 bits for group */
if ( mode & S_IWGRP ) str[5] = 'w';
if ( mode & S_IXGRP ) str[6] = 'x';

if ( mode & S_IROTH ) str[7] = 'r';    /* 3 bits for other */
if ( mode & S_IWOTH ) str[8] = 'w';
if ( mode & S_IXOTH ) str[9] = 'x';

我知道“&”是按位AND运算符,但没有别的。我甚至不知道该问什么。

PD:对我之前提出的问题感到抱歉。我不知道如何标记回答的问题或类似的问题:(

4 个答案:

答案 0 :(得分:3)

模式是bitfield,这是打包数据的常用方法。将该字段中的每个位视为切换开关,可将其设置为关闭或打开。要检查切换是否打开,请检查是否已使用&设置了相应的位。运营商。您可以使用|设置位并使用〜bitwise operations清除它们。

答案 1 :(得分:2)

好吧,POSIX spec for <sys/stat.h>列举了您可以从struct stat的st_mode字段中学到的所有内容。

您的问题是“这个字段可以告诉我什么”,或者是“我如何提取信息”,或两者兼而有之?

答案 2 :(得分:2)

在操作系统编程中,通常使用无符号整数来保存描述某些内容的一系列位。在这种情况下,模式有9位感兴趣。一位告知所有者是否可以读取,一个用于所有者写入,一个用于所有者执行,以及用于该组和其他的类似位。诀窍是提取是否设置了一个位。

这是一个例子。 S_IRUSR是位掩码的名称,用于描述“所有者读取”位。它在the specs中定义为0400(八进制),转换为二进制的100000000。当您使用掩码获取二进制和此值时,如果设置了掩码的第9位,则获得值100000000(二进制)。否则你会得到0。

如果返回大值,则if语句的计算结果为true,否则返回false。这样,如果该位置位,则将'r'写入字符串到位置1.同样的技术也适用于所有其他位。

答案 3 :(得分:0)

作为一个“新手”,我遇到了这个问题。

我的第一步是'man 2 stat'。(在此之前)

在那里你会找到这段内容丰富的示例代码

    EXAMPLE from 'man 2 stat'

    The following program calls lstat() and displays selected fields in the returned stat 
    structure.

    #include <sys/types.h>
    #include <sys/stat.h>
    #include <time.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/sysmacros.h>

    int
    main(int argc, char *argv[])
    {
    struct stat sb;

    if (argc != 2) {
        fprintf(stderr, "Usage: %s <pathname>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    if (lstat(argv[1], &sb) == -1) {
        perror("lstat");
        exit(EXIT_FAILURE);
    }

    printf("ID of containing device:  [%lx,%lx]\n",
            (long) major(sb.st_dev), (long) minor(sb.st_dev));
    printf("File type:                ");

    switch (sb.st_mode & S_IFMT) {
       case S_IFBLK:  printf("block device\n");            break;
       case S_IFCHR:  printf("character device\n");        break;
       case S_IFDIR:  printf("directory\n");               break;
       case S_IFIFO:  printf("FIFO/pipe\n");               break;
       case S_IFLNK:  printf("symlink\n");                 break;
       case S_IFREG:  printf("regular file\n");            break;
       case S_IFSOCK: printf("socket\n");                  break;
       default:       printf("unknown?\n");                break;
    }
    printf("I-node number:            %ld\n", (long) sb.st_ino);
    printf("Mode:                     %lo (octal)\n",
           (unsigned long) sb.st_mode);
    printf("Link count:               %ld\n", (long) sb.st_nlink);
    printf("Ownership:                UID=%ld   GID=%ld\n",
           (long) sb.st_uid, (long) sb.st_gid);

    printf("Preferred I/O block size: %ld bytes\n",
           (long) sb.st_blksize);
    printf("File size:                %lld bytes\n",
           (long long) sb.st_size);
    printf("Blocks allocated:         %lld\n",
            (long long) sb.st_blocks);
    printf("Last status change:       %s", ctime(&sb.st_ctime));
    printf("Last file access:         %s", ctime(&sb.st_atime));
    printf("Last file modification:   %s", ctime(&sb.st_mtime));

    exit(EXIT_SUCCESS);
   }

正如上面其他人所说,这在“switch (sb.st_mode & S_IFMT)”中使用了位掩码。 看来,大部分的管道工作已经为我们完成了。但是,我确实发现在“gcc”下编译时,这些位掩码定义了使用的前导下划线。

我,例如。 '切换(sb.st_mode & __S_IFMT)'

不是很有经验,我猜这个细节可能因版本而异。

我发现这是一个很好的起点(以及 stat 的其他内容) (对于那些在 Linux 的 Windows 子系统上尝试此操作的人的额外观察。您有时可能会得到奇怪的结果!;-))