c-为什么stat返回错误的结果



我想使用stat检查给定的参数是否为目录。该程序采用两个参数:当第一个参数不是目录或不存在时,代码可以正常工作。

但当第一个参数是一个目录并且存在,而第二个参数不存在时,程序会说它们都存在——这是错误的结果。我想知道为什么它不起作用。

#include <stdio.h>
#include <sys/stat.h>

int main(int n, char **argv)
{
char *dir_1=argv[1], *dir_2=argv[2];

if (is_dir(dir_1) == 0)
printf("Directory %s exists.n", dir_1);
else
printf("Directory %s does not exist.n", dir_1);
if (is_dir(dir_2) == 0)
printf("Directory  %s exists.n", dir_2);
else
printf("Directory  %s does not exist.n", dir_2);
}

int is_dir(char *file)
{
struct stat file_stat;
stat(file, &file_stat);
return( (S_ISDIR(file_stat.st_mode)) ? 0 : -1);
}

如果文件不存在,则stat本身返回-1,并将errno设置为ENOENT。但由于第一个目录存在并且是一个目录,所以struct stat中填充了一个目录的信息;这恰好位于第二次CCD_ 7调用的堆栈中完全相同的位置。第二个staterrnoENOENT一起失败,但随后is_dir解释了第一次调用留下的值。


is_dir更正确的实现方式可能是:

int is_dir(char *file)
{
struct stat file_stat;
// if an error occurs, we return 0 for false
if (stat(file, &file_stat) < 0) {
return 0;
}
// otherwise we return whatever the S_ISDIR returns
return S_ISDIR(file_stat.st_mode);
}

请注意,我也更改了返回值;诸如is_dir之类的函数在函数名称声明真实事实的情况下期望返回truish(非零)的布尔值,否则返回零。

你会像这样使用它:

if (is_dir(dir_1)) {
printf("Directory %s exists.n", dir_1);
}
else {
printf("Directory %s does not exist.n", dir_1);
}
if (is_dir(dir_2)) {
printf("Directory  %s exists.n", dir_2);
}
else {
printf("Directory  %s does not exist.n", dir_2);
}

注意,在这种情况下,返回值0并不意味着一定没有具有该名称的目录;CCD_ 14系统调用也可能由于权限不足等原因而失败;扩展逻辑(解释errno的值)超出了这个答案的范围。

这个答案是在另一个答案被接受之后给出的。MSVC中不存在S_ISDIR,而是存在_S_IFDIR。在替换之后,编译器通知is_dir()不返回值。原因是,_S_IFDIR是一个掩码,而不是一个函数。所以在对代码进行了一些调整之后,我得到了这个有效的代码。

#include <stdio.h>
#include <sys/stat.h>
int is_dir(char *file)
{
struct stat file_stat;
if (stat(file, &file_stat) == 0)                    // check it worked
return file_stat.st_mode & _S_IFDIR;            // it's a status mask
return 0;
}
int main(int argc, char **argv)                         // conventional ids
{
char *dir_1, *dir_2;
if (argc < 3) return 0;                             // check silliness
dir_1=argv[1];
dir_2=argv[2];
if (is_dir(dir_1))                                  // reversed the logic
printf("%s is a Directory.n", dir_1);
else
printf("%s is not a Directory.n", dir_1);      // better text
if (is_dir(dir_2))
printf("%s is a Directory.n", dir_2);
else
printf("%s is not a Directory.n", dir_2);
return 0;
}

程序输出:

>test test.c wtest
test.c is not a Directory.
wtest is a Directory.

反过来:

>test wtest test.c
wtest is a Directory.
test.c is not a Directory.

最新更新