C / Unix:如何从st_mode中提取位?

时间:2016-02-13 01:41:45

标签: c linux file unix directory

我是Unix编程和C的初学者,我对struct stat及其字段st_mode有两个问题:

  1. 如下所示访问st_mode字段时,会返回什么类型的数字(八进制,十进制等)?

    struct stat file;
    stat( someFilePath, &file);
    printf("%d", file.st_mode );
    
  2. 我认为数字是八进制的,但是当我运行此代码时,我得到了值33188。什么是基础?

    1. 我发现st_mode编码一个16位二进制数,表示文件类型和文件权限。如何从上面的输出中获取16位数字(特别是当它看起来不是八进制时)。 16位数字的哪些部分对哪些信息进行编码?
    2. 感谢您的帮助。

3 个答案:

答案 0 :(得分:5)

我认为你在这里混合概念。

在内存中,整数值始终为二进制,我们称之为原生格式st_mode的类型为mode_t,该类型是未指定的整数类型,可能为int

base 的概念,即十进制,八进制或十六进制,仅在将本机格式的内存中的数字转换为文本表示(或从文本转换为本机)时才有用。

例如:

int x = 42;

将数字42指定给整数变量。由于源代码是文本,42作为文本输入,我们知道它是十进制值(无前缀)。但请注意我们如何不为变量指定基数:它没有一个。 这个其他代码:

int x = 0x2A;

完全相同。它使用十六进制常量42而不是十进制常量0x2A,但这是相同的,并且x在两种情况下都具有相同的值。同样地:

int x = 052;

也是等价的,但是具有八进制常量。

现在你的代码。当你这样做时:

printf("%d", file.st_mode);
33188

告诉程序将该变量的值输出为十进制数。请记住printf将数字从原生格式转换为文本,因此该文本的基础很重要。如果您希望将值视为八进制,请写下:

printf("%o", file.st_mode);
100644

或以十六进制:

printf("%x", file.st_mode);
81A4

关于八进制的好处是它每个八进制数字恰好代表3位(十六进制每位数为4位),所以通过一些练习,你可以看到没有计算的位。

例如,您的st_mode为十进制33188或八进制为0100644。小数告诉我什么,但是八进制确实意味着什么,因为我记得最后9位(3个八进制数字)是权限:所有者为3位,组为3位,其他为3位。所以:

* Owner: 6 that is rw-
* Group: 4 that is r--
* Other: 4 that is r--
顺便说一句,最后一个是这个常数:

#define S_IFREG 0100000

这只意味着它是一个普通文件。

答案 1 :(得分:0)

  1. 该数字是一个值。在printf()中,您可以使用"%d"以十进制格式打印(如您所做),或使用"%o"(或"%lo")代替,以八进制形式打印

  2. 检查man 2 stat有关每种信息的表示方式。然后,您可以使用位掩码来提取所需的信息。有一个例子在手册页中展示了它。

答案 2 :(得分:0)

您将其打印为十进制,因此您获得了小数。如果你把它打印成八进制,你就得到了八进制;同上十六进制。

以八进制打印时,st_mode字段最容易被理解。

printf("mode = %07o\n", file.st_mode);

最后三位是chmod等熟悉的权限(例如644)。右边的第四位通常为0,但对于set-UID,set-GID或sticky,它将为非零位文件或目录。其余数字标识文件的类型。

您可以使用<sys/stat.h>中的宏来剖析信息。