为什么realpath()返回错误EEXIST

Why does realpath() return error EEXIST?

本文关键字:错误 EEXIST 返回 realpath 为什么      更新时间:2023-10-16

我的程序在Linux环境下运行,用gcc版本4.4.7编译。

我使用realpath()来"规范化"文件路径。我提供给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;      
}

如果没有特别的原因,你永远不应该检查errno

也许realpath的内部操作在EEXIST上失败了。或者errno碰巧是之前操作失败的EEXIST, realpath没有改变它。

如果这不会导致realpath失败,为什么你要关心?

从你自己的链接:

在成功完成后,realpath()将返回一个指向解析名称的指针。否则, realpath()将返回一个空指针并设置errno表示错误,并且resolved_name所指向的缓冲区的内容是未定义的。

注意,如果realpath成功,它没有说errno被设置为任何特别的东西。那么为什么在检查realpath是否成功之前先检查errno呢?

也就是说,您不应该通过检查'errno'值来认为realpath()失败/成功,您应该检查其返回值是否为NULL。如果返回NULL,则可以检查'errno'以查找根本原因。换句话说,如果realpath()成功,它可能不会更改/重置/清除'errno'值-为其分配0。只有当失败时,它才会设置'errno'作为错误码。