stat против Mkdir с EEXIST - PullRequest
       4

stat против Mkdir с EEXIST

1 голос
/ 11 июня 2011

Мне нужно создать папку, если она не существует, поэтому я использую:

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

Папка создается только при первом запуске программы - после этого это просто проверка. Есть предложение пропустить статистический вызов, вызвать mkdir и проверить errno на EEXIST. Это дает реальные преимущества?

Ответы [ 3 ]

1 голос
/ 11 июня 2011

Что еще более важно, с подходом stat + mkdir возникает условие состязания: между stat и mkdir другая программа может выполнить mkdir, поэтому ваш mkdir может все еще ошибка с EEXIST.

1 голос
/ 11 июня 2011

Есть небольшое преимущество.Посмотрите 'LBYL против EAFP' или 'Посмотрите, прежде чем вы прыгните' против 'Проще просить прощения, чем разрешения'.

Небольшое преимущество заключается в том, что системный вызов stat() должен анализироватьимя каталога и получить к inode - или к отсутствующему inode в этом случае - и затем mkdir() должен сделать то же самое.Конечно, данные, необходимые для mkdir(), уже находятся в пуле буферов ядра, но они все же включают два обхода указанного пути вместо одного.Таким образом, в данном случае, это немного более эффективно использовать ЭСПЦ, чем использовать LBYL, как вы делаете.

1009 * Тем не менее, независимо от того, что действительно измеримый эффект в средней программе весьма спорно.Если вы не делаете ничего, кроме создания каталогов повсюду, то вы можете обнаружить выгоду.Но это определенно небольшой эффект, по сути неизмеримый, если вы создаете один каталог в начале программы.

Возможно, вам придется иметь дело со случаем, когда strcmp(dir, "/some/where/or/another") == 0, но, хотя "/some/where" существует, ни"/some/where/or" ни (по необходимости) "/some/where/or/another" не существует.Ваш текущий код не обрабатывает недостающие каталоги в середине пути.Он просто сообщает ENOENT, что mkdir() сообщит.Ваш код, который выглядит, не проверяет, что dir на самом деле является каталогом, - он просто предполагает, что если он существует, то это каталог.Правильная обработка этих вариаций сложнее.

0 голосов
/ 21 июня 2016

Аналогично Условие гонки с stat и mkdir в последовательности , ваше решение неверно не только из-за состояния гонки (как уже было указано в других ответах здесь), но и потому, что вы никогда не проверяете является ли существующий файл каталогом или нет.

При повторной реализации функциональности, которая уже широко доступна в существующих инструментах командной строки в UNIX, всегда помогает увидеть, как она была реализована в этих инструментах.

Например, посмотрите, как опция mkdir(1) -p реализована в BSD (bin/mkdir/mkdir.c#mkpath в OpenBSD и NetBSD ) все из которых, при ошибке mkdir(2) , по-видимому, немедленно вызывают stat(2), чтобы впоследствии запустить макрос S_ISDIR, чтобы гарантировать, что Существующий файл является каталогом, а не просто любым другим типом файла.

...