在最新的 Ubuntu 21.04 和其他最新的 Linux 版本上,realpath API 返回错误 22(无效参数)或 38(函数未实现)

在最新的 Ubuntu 21.04 和其他最新的 Linux 版本上,realpath API 返回错误 22(无效参数)或 38(函数未实现)
sachin@sachin:~$ cat 1.c
#include <limits.h> /* PATH_MAX */
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
void main(void) {
    char *buf=NULL; 
    
    char *res = realpath("./new-CDM/dummy.c", buf);
    
    printf("result = %s",res);
    printf("\nerrno = %d\n",errno);
    printf("\nBuf = %s\n",buf);
}
sachin@sachin:~$ gcc 1.c
sachin@sachin:~$ ./a.out 
result = /home/sachin/new-CDM/dummy.c
errno = 22

Buf = (null)

同一程序在 Ubuntu 18.04 或 20.04 上运行时没有出现任何错误。

答案1

man 3 realpath

如果没有错误,realpath() 将返回指向 solved_pa​​th 的指针。

man 3 errno

仅当调用的返回值指示错误时,errno 中的值才有意义(即,大多数系统调用的返回值为 -1;大多数库函数的返回值为 -1 或 NULL);成功执行的函数可以更改 errno。

因此没有错误,并且的值errno正式不明确的


返回的实际值是内部细节,过去实现方式不同。目前(21.10),是内部尝试跟踪路径组件上的符号链接的errno遗留realpath问题,以防万一。

dummy.c您可以通过创建一个指向文件的符号链接target.c,然后运行strace ./a.out来跟踪 Linux 内核调用,特别是以下几行来最好地看到这一点:

readlink("/home/sachin/new-CDM", 0x7ffee6b57960, 1023) = -1 EINVAL (Invalid argument)
readlink("/home/sachin/new-CDM/dummy.c", "target.c", 1023) = 8
readlink("/home/sachin/new-CDM/target.c", 0x7ffee6b57960, 1023) = -1 EINVAL (Invalid argument)

readlink对非符号路径组件的调用失败,并更改errno为“EINVAL(无效参数)”。

在过去(20.04),readlink只有在额外检查组件是否与 链接后才会调用lstat,因此保留 的值errno

lstat("/home/sachin/new-CDM", {st_mode=S_IFDIR|0775, st_size=20, ...}) = 0
lstat("/home/sachin/new-CDM/dummy.c", {st_mode=S_IFLNK|0777, st_size=8, ...}) = 0
readlink("/home/sachin/new-CDM/dummy.c", "target.c", 4095) = 8
lstat("/home/sachin/new-CDM/target.c", {st_mode=S_IFREG|0664, st_size=0, ...}) = 0

因此,这种变化很可能是一种优化,仅在您应该忽略它的情况下才会对值产生副作用。


顺便说一句,你在这里打印buf是没有意义的,因为它显然仍然是 NULL。如果这让你感到惊讶,那么值得思考一下为什么。

相关内容