C++相当于'readlink -f'

C++ equivalent of 'readlink -f'

本文关键字:readlink 相当于 C++      更新时间:2023-10-16

unistd.h中,我有C函数readlink,它遵循一个链接下一个目标。COREUTIL readlink具有出色的-f选项,可以递归地遵循每个SYM链接。如何在C 中获得这种行为?我不知道的Boost库,POSIX函数等?

**编辑**只是在查看realpath的人页面。这是否给出了readlink -f的相同"规范"扩展?

是的, realpath等于 readlink -f

有关更多信息,请参见"人"页面

我今天需要做到这一点,并且使用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 pathn");
        goto error;
    }
    linkname = malloc(sb.st_size + 1);
    if (linkname == NULL) {
        fprintf(stderr, "insufficient memoryn");
        goto error;
    }
    r = readlink(path, linkname, sb.st_size + 1);
    if (r < 0) {
        fprintf(stderr, "failed to readlink the pathn");
        goto error;
    }
    if (r > sb.st_size) {
        fprintf(stderr, "symlink increased in size between lstat() and readlink()n");
        goto error;
    }
    linkname[sb.st_size] = '';
    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 pathn");
            goto error;
        }
    } else {
        relpath = strdup(linkname);
    }
    /* canonicalize the path */
    abspath = realpath(relpath, NULL);
    if (!abspath) {
        fprintf(stderr, "failed to get canonical pathn");
        goto error;
    }
    goto cleanup;
error:
    free(abspath);
    abspath = NULL;
cleanup:
    free(linkname);
    free(ptmp);
    free(relpath);
    return abspath;
}

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