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_path 的指针。
从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。如果这让你感到惊讶,那么值得思考一下为什么。