为什么 realpath() return 错误 EEXIST?
Why does realpath() return error EEXIST?
我的程序是运行在Linux环境下,用gcc 4.4.7版编译。
我正在使用 realpath()
到 "canonicalize" 文件路径。我给realpath()
的每个目录和文件的路径肯定存在,这当然是realpath()
正常工作所必需的。
但是,有时 realpath()
会失败,错误代码为 17,名称 EEXIST
,字符串描述 "File exists"。
这让我很困惑。当然存在,我尖叫着 realpath()
。但是realpath()
对我的咆哮不为所动
http://pubs.opengroup.org/onlinepubs/009695399/functions/realpath.html 的 realpath()
文档列出了导致其失败的错误,但 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;
}
如果没有特定原因,您永远不应该检查 errno
。
也许 realpath
发生的任何内部操作最后都失败了 EEXIST
。或者可能 errno
恰好是 EEXIST
来自之前的一些失败的操作并且 realpath
没有改变它。
如果这不会导致 realpath
失败,您为什么要关心?
来自你自己的 link:
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.
请注意,如果 realpath
成功,它并没有说 errno
被设置为任何特定值。那么,为什么在检查 realpath
是否成功之前先检查 errno
?
也就是说,您不应该通过检查 'errno' 值来认为 realpath() 是 failed/succeeded,您应该根据 NULL 检查它的返回值。如果返回 NULL,那么您可以检查 'errno' 以找出根本原因。
换句话说,如果 realpath() 成功,它可能不会 change/reset/clear 'errno' 值 - 为它分配 0。只有失败时,才会设置'errno'作为错误码。
我的程序是运行在Linux环境下,用gcc 4.4.7版编译。
我正在使用 realpath()
到 "canonicalize" 文件路径。我给realpath()
的每个目录和文件的路径肯定存在,这当然是realpath()
正常工作所必需的。
但是,有时 realpath()
会失败,错误代码为 17,名称 EEXIST
,字符串描述 "File exists"。
这让我很困惑。当然存在,我尖叫着 realpath()
。但是realpath()
对我的咆哮不为所动
http://pubs.opengroup.org/onlinepubs/009695399/functions/realpath.html 的 realpath()
文档列出了导致其失败的错误,但 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;
}
如果没有特定原因,您永远不应该检查 errno
。
也许 realpath
发生的任何内部操作最后都失败了 EEXIST
。或者可能 errno
恰好是 EEXIST
来自之前的一些失败的操作并且 realpath
没有改变它。
如果这不会导致 realpath
失败,您为什么要关心?
来自你自己的 link:
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.
请注意,如果 realpath
成功,它并没有说 errno
被设置为任何特定值。那么,为什么在检查 realpath
是否成功之前先检查 errno
?
也就是说,您不应该通过检查 'errno' 值来认为 realpath() 是 failed/succeeded,您应该根据 NULL 检查它的返回值。如果返回 NULL,那么您可以检查 'errno' 以找出根本原因。 换句话说,如果 realpath() 成功,它可能不会 change/reset/clear 'errno' 值 - 为它分配 0。只有失败时,才会设置'errno'作为错误码。