`S_ISREG()`是什么,它有什么作用?

26
我在一个检索文件属性的C程序中遇到了宏S_ISREG()。不幸的是,网上没有关于这个宏的基本信息。尽管有一些更高级的讨论,但它们超出了我所需要的范围。 S_ISREG()是什么,它是用来做什么的?在检索文件属性的程序中,它有什么作用?它确切地是做什么的?
谢谢。

你可能需要链接到“高级应用程序”,我仍然很难理解为什么讨论会变得复杂 - 除非你只是指这些讨论涉及的问题更大,而使用S_ISREG只是其中的一小部分。stat()手册中的示例显示了对st_mode的测试 - 这些宏只是将该测试包装成布尔结果。 - Clifford
你不需要联网即可获取文档;在Linux上,man 2 stat运行得非常完美。 - wildplasser
3个回答

34

S_ISREG()是一个宏,用于解释从系统调用stat()返回的stat结构中的值。如果参数(struct stat中的st_mode成员)是一个常规文件,则返回true。

请参见man statman fstatman inode(inode man页链接)了解更多详情。这是man页的相关部分:

   Because tests of the above form are common, additional macros are defined by POSIX to allow the test of the file type in st_mode to be written more concisely:

       S_ISREG(m)  is it a regular file?

       S_ISDIR(m)  directory?

       S_ISCHR(m)  character device?

       S_ISBLK(m)  block device?

       S_ISFIFO(m) FIFO (named pipe)?

       S_ISLNK(m)  symbolic link?  (Not in POSIX.1-1996.)

       S_ISSOCK(m) socket?  (Not in POSIX.1-1996.)

   The preceding code snippet could thus be rewritten as:

       stat(pathname, &sb);
       if (S_ISREG(sb.st_mode)) {
           /* Handle regular file */
       }

10

使用stat()函数检索到的stat结构的st_mode成员被用于测试文件是否为普通文件(即在磁盘或大容量存储器上而不是目录、套接字、符号链接等)。

struct stat sb;
if( stat( file_path, &sb) != -1) // Check the return value of stat
{
    if( S_ISREG( sb.st_mode ) != 0 )
    {
        printf( "%s is a file", file_path ) ;
    }
    else
    {
        printf( "%s is not a file", file_path ) ;
    }
}

st_mode 成员包含被 S_IFMT(0170000)掩码屏蔽的 4 个位。这些位的值为:

       S_IFSOCK   0140000   socket
       S_IFLNK    0120000   symbolic link
       S_IFREG    0100000   regular file
       S_IFBLK    0060000   block device
       S_IFDIR    0040000   directory
       S_IFCHR    0020000   character device
       S_IFIFO    0010000   FIFO

因此,宏S_ISREG可能被定义为:

#define S_ISREG( m ) (((m) & S_IFMT) == S_IFREG)

由于它是一个宏,你可以在头文件sys/stat.h中查看其实际定义。在GNU头文件中,它被定义为:

#define __S_ISTYPE(mode, mask)  (((mode) & __S_IFMT) == (mask))
...
#define S_ISREG(mode)    __S_ISTYPE((mode), __S_IFREG)

这基本上与我简化版本的相同。


你的 if 测试被倒置了。如果 S_ISREG() 是非零值,那么所讨论的对象就是一个常规文件。 - Bjorn A.
https://sourceware.org/git/?p=glibc.git;a=blob;f=io/sys/stat.h;h=762c8538baad367c5e1917d98173166d2d8ed251;hb=HEAD#l128 和 https://sourceware.org/git/?p=glibc.git;a=blob;f=bits/stat.h;h=0330f9ad27b56daccc052e0d37991dea471b71f0;hb=HEAD#l69,供好奇者参考。 - raylu

7
POSIX标准定义了S_ISREG,实际上是在线的。

http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/sys_stat.h.html

引用:

以下宏将提供以测试文件是否为指定类型的功能。提供给宏的值 m 是从 stat 结构中的 st_mode 获得的。如果测试为真,则该宏将评估为非零值;如果测试为假,则为 0。

[...]

S_ISFIFO(m)

   测试管道或 FIFO 特殊文件。

S_ISREG(m)

   测试普通文件。

S_ISLNK(m)

   测试符号链接。

[...]

使用 S_ISREG 的典型方式是首先调用 stat 函数以填充一个 struct stat 对象,该对象包含有关文件的信息。然后,可以使用此宏测试此结构的 st_mode 成员的值,该成员是整数类型。

除了标准文档外,还有来自各种系统的在线手册以及关于使用stat进行编程的教程。维基百科上有一个关于stat的页面,其中包含一个完整的代码示例。虽然它没有包含S_ISREG,但这很容易添加进去。

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