stat 与带有 EEXIST 的 mkdir

发布于 2024-11-15 02:31:06 字数 634 浏览 3 评论 0 原文

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

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。 它能带来真正的好处吗?

I need to create folder if it does not exists, so I use:

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;
 }

The folder is created only during first run of program - after that it is just a check.
There is a suggestion to skipping the stat call and call mkdir and check errno against EEXIST.
Does it give real benefits?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

慕巷 2024-11-22 02:31:06

更重要的是,使用 stat + mkdir 方法时,存在竞争条件:在 statmkdir 之间> 另一个程序可以执行 mkdir,因此您的 mkdir 仍可能因 EEXIST 而失败。

More important, with the stat + mkdir approach, there is a race condition: in between the stat and the mkdir another program could do the mkdir, so your mkdir could still fail with EEXIST.

爱格式化 2024-11-22 02:31:06

有一个小小的好处。查找“LBYL 与 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 实际上是一个目录 - 它只是假设如果它存在,那么它就是一个目录。正确处理这些变化是比较棘手的。

There's a slight benefit. Look up 'LBYL vs EAFP' or 'Look Before You Leap' vs 'Easier to Ask Forgiveness than Permission'.

The slight benefit is that the stat() system call has to parse the directory name and get to the inode - or the missing inode in this case - and then mkdir() has to do the same. Granted, the data needed by mkdir() is already in the kernel buffer pool, but it still involves two traversals of the path specified instead of one. So, in this case, it is slightly more efficient to use EAFP than to use LBYL as you do.

However, whether that is really a measurable effect in the average program is highly debatable. If you are doing nothing but create directories all over the place, then you might detect a benefit. But it is definitely a small effect, essentially unmeasurable, if you create a single directory at the start of a program.

You might need to deal with the case where strcmp(dir, "/some/where/or/another") == 0 but although "/some/where" exists, neither "/some/where/or" nor (of necessity) "/some/where/or/another" exist. Your current code does not handle missing directories in the middle of the path. It just reports the ENOENT that mkdir() would report. Your code that looks does not check that dir actually is a directory, either - it just assumes that if it exists, it is a directory. Handling these variations properly is trickier.

柏拉图鍀咏恒 2024-11-22 02:31:06

类似于 按顺序使用 stat 和 mkdir 的竞争条件,您的解决方案不正确,不仅因为竞争条件(正如这里的其他答案已经指出的那样),而且因为您从不检查现有文件是否是目录 或不。

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

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

Similar to Race condition with stat and mkdir in sequence, your solution is incorrect not only due to the race condition (as already pointed out by the other answers over here), but also because you never check whether the existing file is a directory or not.

When re-implementing functionality that's already widely available in existing command-line tools in UNIX, it always helps to see how it was implemented in those tools in the first place.

For example, take a look at how mkdir(1) -p option is implemented across the BSDs (bin/mkdir/mkdir.c#mkpath in OpenBSD and NetBSD), all of which, on mkdir(2)'s error, appear to immediately call stat(2) to subsequently run the S_ISDIR macro to ensure that the existing file is a directory, and not just any other type of a file.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文