如何在Linux下通过编程的方式获取文件的绝对路径而不使用realpath()函数?

5
我知道可以使用realpath()函数获取文件的绝对路径。然而,根据man页面中的BUGS部分,实现中存在一些问题。具体如下:
BUGS
避免使用此函数。由于(除非使用非标准的resolved_path == NULL特性),无法确定适合输出缓冲区resolved_path的大小,因此它的设计有缺陷。根据POSIX,大小为PATH_MAX的缓冲区就足够了,但是PATH_MAX不一定是定义常量,并且可能需要使用pathconf(3)来获取。询问pathconf(3)并不能帮助解决问题,因为一方面,POSIX警告pathconf(3)的结果可能很大且不适合malloc内存;另一方面,pathconf(3)可能返回-1,表示PATH_MAX没有界限。 libc4和libc5实现存在缓冲区溢出(已修复在libc-5.4.13)。因此,像mount(8)这样的set-user-ID程序需要一个私有版本。
那么,问题是获取文件的绝对路径最佳实践是什么?

不,它们不是同一件事。我想知道如何获取普通文件的绝对路径,而不是可执行文件的路径。 - jcadam
3个回答

5

我知道这个问题很久了,但我没有看到任何解决核心问题的答案:OP引用的手册已经过时且错误,原因至少有两个。

一个是POSIX 2008添加/强制支持NULL参数选项,通过此选项,realpath为您分配字符串。使用此功能的程序将可移植到所有相关版本的GNU/Linux、可能是大多数其他现代系统以及符合POSIX 2008的任何内容。

手册错误的第二个原因是反对使用PATH_MAX。这纯粹是GNU对“任意限制”的宗教意识形态。在现实世界中,不设置路径名长度限制会增加各种滥用/DoS的途径,会给本来无法失败的任务增加很多失败情况,并会破坏比realpath更多的接口。

如果您关心最大的可移植性,最好同时使用这两种方法。有关详细信息,请参阅POSIX文档:

http://pubs.opengroup.org/onlinepubs/9699919799/functions/realpath.html

如果定义了PATH_MAX,我会使用固定大小的、由调用者提供的缓冲区,否则传递NULL。这似乎涵盖了所有情况,但您可能还想检查旧版本的POSIX,看看它们是否有任何关于如果未定义PATH_MAX该怎么做的指南。

3

使用getcwd()和readlink()函数,可以给缓冲区分配一个大小来重新实现realpath()函数。请注意,必须从左到右解析符号链接、"."和".."才能正确执行。


2

从shell中,我可以使用readlink -f $FILE获取完整路径。在glibc中有一个readlink()函数,也许这能帮到你。

# man 2 readlink

我已经阅读了coreutils软件包中的readlink命令源代码。有一个简单的解决方案——只需要将PATH_MAX定义为1024!!!-__-!!! - jcadam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接