系统调用stat()的使用方法
我们在checkDataDir()函数中看到如下代码:
void checkDataDir(void)
{
struct stat stat_buf;
if (stat(DataDir, &stat_buf) != 0) /// DataDir就是数据库集群的目录,譬如/home/postgres/pg175/data1
{
if (errno == ENOENT)
ereport(FATAL,
(errcode_for_file_access(),
errmsg("data directory \"%s\" does not exist",
DataDir)));
else
ereport(FATAL,
(errcode_for_file_access(),
errmsg("could not read permissions of directory \"%s\": %m",
DataDir)));
}
/* eventual chdir would fail anyway, but let's test ... */
if (!S_ISDIR(stat_buf.st_mode)) /// 检查这个字符串是否是目录
ereport(FATAL,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("specified data directory \"%s\" is not a directory",
DataDir)));
变量DataDir的类型是char *,即指向一个字符串,表明数据库集群的目录。上述代码片段的逻辑非常简单,第一步先检查这个字符串是不是一个文件,注意,目录和普通文件都是文件。第二步再检查这个文件是否是一个目录。
在《The Linux Programming Interface》这本书上有这么一段话:
File types
Within the file system, each file is marked with a type, indicating what kind of file it is. One of these file types denotes ordinary data files, which are usually called regular or plain files to distinguish them from other file types. These other file types include devices, pipes, sockets, directories, and symbolic links. The term file is commonly used to denote a file of any type, not just a regular file.
在Linux/Unix的世界中,万物皆文件。但是我们在PG中最常见的需求是判断这个文件是目录还是普通文件(regular file)。
我们通过自己编写的一个小例子学习上述两个用法:
#include <stdio.h>
#include <sys/stat.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m) & S_IFMT) == S_IFDIR)
#endif
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
int main(int argc, const char* argv[])
{
if(argc > 1)
{
struct stat stat_buf;
if(stat(argv[1], &stat_buf) == 0)
{
if(S_ISDIR(stat_buf.st_mode))
printf("%s is a directory.\n", argv[1]);
else if(S_ISREG(stat_buf.st_mode))
printf("%s is a regular file.\n", argv[1]);
else
printf("%s is a strange file.\n", argv[1]);
}
else
printf("%s is not a file!\n", argv[1]);
}
return 0;
}
假设这个源代码的文件名是stat.c,那么编译这个小程序就用如下命令。当然前提是你的Linux系统中gcc已经安装好了。下面这条命令会在当前目录下产生一个a.out的可执行文件:
gcc -Wall stat.c
执行这个a.out程序的方法非常简单,就是后面跟上一个字符串。该程序会判断这个文件是否是目录,普通文件,还是你瞎写的字符串,然后根据判断结果输出相应的提示。下面是我测试的输出结果。
postgres@ip-172-31-29-179:$ ./a.out config
config is a directory.
postgres@ip-172-31-29-179:$ ./a.out configx
configx is not a file!
postgres@ip-172-31-29-179:$ ./a.out stat.c
stat.c is a regular file.
这个小程序不难理解,百分百可编译,希望你能动手实验一下,体会stat()这个系统调用的用法。