2015-06-04 6 views
3

Моя программа работает в среде Linux, скомпилированной с gcc версии 4.4.7.Почему realpath() возвращает ошибку EEXIST?

Я использую realpath() для «canonicalize» путей к файлам. Путь каждого каталога и файла, который я кормлю до realpath(), определенно существует, что, конечно же, необходимо для корректной работы realpath().

Однако иногда realpath() сбой кода ошибки 17, имя EEXIST, строка описание «Файл существует».

Это меня озадачивает. Конечно, он существует, я кричу на realpath(). Но realpath() не тронут моим разглагольствованием.

Документация для realpath() по адресу http://pubs.opengroup.org/onlinepubs/009695399/functions/realpath.html содержит ошибки, которые приводят к сбою, но EEXIST не является одним из них.

Почему realpath() терпят неудачу таким образом?

Примеры каталогов и пути к файлам, которые вызывают EEXIST ошибку:

  • Абсолютный путь к каталогу: /alpha/bravo/charlie/delta
  • Абсолютный путь к файлу: /alpha/bravo/charlie/foo.txt
  • относительный путь к файлу : ../../charlie/foo.txt
  • путь к файлу, который имеет дополнительную точку в нем: /alpha/bravo/Charlie/./foo.txt

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

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

Программа сниппет:

#include <string> 
#include <stdio.h> 
#include <stdlib.h> 
#include <errno.h> 
#include <limits.h> // for PATH_MAX 

using std; 

string PathCanonicalize(string const & path) 
{ 
    string result; 

    char szResult[ PATH_MAX ]; 
    ::realpath(path.c_str(), szResult); 
    if (errno == EEXIST) 
    { 
    // Why? 
    cerr << "realpath: error code " << errno << ", " << ::strerror(errno) << ": '" << path << "'. Of course the file exists!" << endl; 

    result = path; 
    } 
    else if (errno) 
    { 
    cerr << "realpath: error code " << errno << ", " << ::strerror(errno) << ": '" << path << "'" << endl; 

    result = path; 
    } 
    else 
    { 
    result = szResult; 
    } 

    return result;  
} 
+3

Это багги код, вы должны * только * проверить 'errno', если функция возвращает NULL. –

ответ

4

Вы никогда не должны, когда-либо проверить errno без определенной причины.

Возможно, какая-либо внутренняя операция realpath произошла в последний раз с EEXIST. Или, может быть, errno оказался EEXIST из предыдущей операции, которая не удалась, и realpath не изменил ее.

Если это не вызвало ошибку realpath, почему вас это волнует?

С собственной ссылке:

Upon successful completion, realpath() shall return a pointer to the resolved name. Otherwise, realpath() shall return a null pointer and set errno to indicate the error, and the contents of the buffer pointed to by resolved_name are undefined.

Обратите внимание, что не говорит, что errno установлен на что-либо, в частности, если realpath успешно. Так почему вы проверяете errno, прежде чем проверять, удалось ли realpath?

+0

Чтобы добавить, не связанные с 'realpath' напрямую, но в целом, несколько редких функций не имеют возвращаемого значения, указывающего на ошибку, и проверка' errno' - единственный способ определить, была ли операция выполнена. Но даже для этих функций 'errno' не устраняется при успешном завершении. Если вы хотите проверить 'errno' для этих функций, вам нужно явно установить' errno' в ноль перед вызовом этих функций. (Поскольку этот ответ справедливо указывает на: не делайте этого, кроме случаев, когда предполагается, что функция используется так. 'Realpath' разрешено устанавливать' errno', даже если единственная ошибка - это некоторая внутренняя ошибка.) – hvd

+0

Хорошая точка. Я проверял несколько изменений в несколько раз назад, но я неправильно исказил его, когда что-то не так. Благодарю. –

Смежные вопросы