1

如果文件夹不存在,我需要创建它,所以我使用:

bool mkdir_if_not_exist(const char *dir)
{
  bool ret = false;
  if (dir) {
     // first check if folder exists
     struct stat folder_info;
     if (stat(dir, &folder_info) != 0) {
    if (errno == ENOENT) { // create folder
        if (mkdir(dir, S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH) ?!= 0) // 755
        perror("mkdir");
        else
        ret = true;
    } else
         perror("stat");
    } else
         ret = true; ?// dir exists
     }
     return ret;
 }

该文件夹仅在程序第一次运行时创建 - 之后它只是一个检查。有一个建议是跳过 stat 调用并调用 mkdir 并根据 EEXIST 检查 errno。它会带来真正的好处吗?

4

3 回答 3

1

有一点好处。查找“LBYL vs EAFP”或“在你跳跃之前先看看”与“请求宽恕比许可更容易”。

轻微的好处是stat()系统调用必须解析目录名称并到达 inode - 或者在这种情况下丢失的 inode - 然后mkdir()必须做同样的事情。当然,所需的数据mkdir()已经在内核缓冲池中,但它仍然涉及对指定路径的两次遍历,而不是一次。因此,在这种情况下,使用 EAFP 比使用 LBYL 更有效。

然而,这是否真的是普通程序中可测量的效果是非常有争议的。如果您只是在各处创建目录,那么您可能会发现一个好处。但是,如果您在程序开始时创建单个目录,这绝对是一个很小的影响,基本上无法衡量。

您可能需要处理strcmp(dir, "/some/where/or/another") == 0但虽然"/some/where"存在,但"/some/where/or"(必然)"/some/where/or/another"不存在的情况。您当前的代码不处理路径中间缺少的目录。它只报告mkdir()将报告的 ENOENT。您看起来的代码也不会检查它dir实际上是一个目录 - 它只是假设如果它存在,它就是一个目录。正确处理这些变化比较棘手。

于 2011-06-11T04:29:41.857 回答
1

更重要的是,使用stat+mkdir方法,有一个竞争条件:在statmkdir另一个程序之间可以做mkdir,所以你mkdir仍然可能失败EEXIST

于 2011-06-11T04:38:28.703 回答
0

与 stat 和 mkdir in sequence的竞争条件类似,您的解决方案不正确不仅是因为竞争条件(正如这里的其他答案已经指出的那样),还因为您从不检查现有文件是否是目录.

在重新实现 UNIX 现有命令行工具中已经广泛使用的功能时,首先了解这些工具是如何实现的总是有帮助的。

例如,看看mkdir(1) -p选项是如何在 BSD 中实现的(bin/mkdir/mkdir.c#mkpath在 OpenBSDNetBSD中),所有这些,在mkdir(2)出现错误时,似乎立即调用stat(2)以随后运行S_ISDIR宏以确保现有文件是一个目录,并且不仅仅是任何其他类型的文件。

于 2016-06-20T21:35:07.530 回答