在unistd.h
中,我有一个C函数readlink
,它跟随一个目标的链接。 coreutil readlink
具有很好的-f
选项,可以递归地跟踪每个sym链接。如何在C ++中获得此行为?一个boost库,一个我不知道的posix函数等等?
**编辑**只是查看realpath
的手册页。这是否给出readlink -f
答案 0 :(得分:2)
是的,realpath
相当于readlink -f
。
有关详细信息,请参阅the man page
答案 1 :(得分:1)
我今天正好需要这样做,但使用 realpath() 的建议失败了,因为符号链接是相对的!如果您使用 glibc,请考虑 canonicalize_file_name (https://man7.org/linux/man-pages/man3/canonicalize_file_name.3.html)。
当然是我写完这段代码后发现的。我不知道这是如何跨平台的。如果 canonicalize_file_name 对您可用,我不会推荐它,但这可能是一个很好的起点:)
char *readlink_f(const char *path) {
struct stat sb;
char *linkname = NULL;
ssize_t r;
int ret = -1;
char *ptmp = NULL;
char *dir; // not allocated
char *relpath = NULL;
char *abspath = NULL;
/* create enough space to read the link into */
if (lstat(path, &sb) == -1) {
fprintf(stderr, "failed to lstat the path\n");
goto error;
}
linkname = malloc(sb.st_size + 1);
if (linkname == NULL) {
fprintf(stderr, "insufficient memory\n");
goto error;
}
r = readlink(path, linkname, sb.st_size + 1);
if (r < 0) {
fprintf(stderr, "failed to readlink the path\n");
goto error;
}
if (r > sb.st_size) {
fprintf(stderr, "symlink increased in size between lstat() and readlink()\n");
goto error;
}
linkname[sb.st_size] = '\0';
if (linkname[0] != '/') {
/* realpath fails with relative symlinks */
ptmp = strdup(path); /* dirname modifies its argument */
dir = dirname(ptmp);
if (asprintf(&relpath, "%s/%s", dir, linkname) == -1) {
fprintf(stderr, "failed to get generate absolute path\n");
goto error;
}
} else {
relpath = strdup(linkname);
}
/* canonicalize the path */
abspath = realpath(relpath, NULL);
if (!abspath) {
fprintf(stderr, "failed to get canonical path\n");
goto error;
}
goto cleanup;
error:
free(abspath);
abspath = NULL;
cleanup:
free(linkname);
free(ptmp);
free(relpath);
return abspath;
}