4

unistd.h中,我有 C 函数readlink,它遵循一个目标的链接。coreutilreadlink有一个很好的-f选项来递归地跟踪每个符号链接。如何在 C++ 中获得这种行为?一个boost库,一个我不知道的posix函数等等?

** 编辑 ** 只是在查看realpath. 这是否给出了相同的“规范”扩展readlink -f

4

3 回答 3

3

realpath的,相当于readlink -f.

有关更多信息,请参见手册页

于 2016-08-08T16:00:56.410 回答
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;
}
于 2021-05-11T07:01:50.760 回答
0

在 C++17 中,您可以使用std::filesystem::canonical(或者weakly_canonical如果文件不必存在)。它也是跨平台的。如果您还不能使用 C++17,您可能仍然可以使用该std::filesystem::experimental版本。

于 2021-11-16T15:35:18.327 回答