18

我正在寻找如何在 C 程序中使用 realpath 函数的示例。我似乎在网上或我的任何 C 编程书籍中都找不到。

4

3 回答 3

27
  • 笔记

  • 示例代码

#include <limits.h> /* PATH_MAX */
#include <stdio.h>
#include <stdlib.h>

int main(void) {
    char buf[PATH_MAX]; /* PATH_MAX incudes the \0 so +1 is not required */
    char *res = realpath("this_source.c", buf);
    if (res) { // or: if (res != NULL)
        printf("This source is at %s.\n", buf);
    } else {
        char* errStr = strerror(errno);
        printf("error string: %s\n", errStr);

        perror("realpath");
        exit(EXIT_FAILURE);
    }
    return 0;
}
于 2009-10-13T22:11:02.037 回答
4

单行构建命令行

极简主义,但它的工作!

建造

gcc -o realpath -x c - <<< $'#include<stdlib.h>\n#include<stdio.h>\nint main(int c,char**v){puts(realpath(v[1],0));}'

测试

$> ./realpath  ~/../../../usr/./bin/./awk
/bin/gawk 

$> readlink -f ~/../../../usr/./bin/./awk
/bin/gawk

要求

  • 用于编译和链接
  • <<<和_$' ... \n ... '

碰撞

我的极简主义单行命令行构建了一个可执行文件,当路径不存在时realpath会生成一个。我没有在我的答案Segmentation fault中编写if/ blocs 来处理该问题,而是在下面添加了一些链接,让您查看and的 Busybox 实现。elserealpathreadlink


Busybox 实现

如需更完整的源代码,请查看这个简单的实现。

官方 Git 仓库

GitHub镜像仓库

于 2013-10-24T09:46:26.393 回答
3

realpath()函数的作用是在解析所有符号链接后告诉您文件的路径名。如果您提供的值是相对名称,则不一定是绝对路径名,但这部分取决于您是否遍历任何具有绝对名称的符号链接作为链接值 - 如果您这样做,那么输出毕竟是绝对名称. 此外,如果相对名称遍历到根目录(或“超越”,如“../../../../../..”,当目录层次结构只有三层深度时)。

您的机器上可能已经有一个“realpath”程序。这是我写的(非标准)版本。

/*
@(#)File:           $RCSfile: realpath.c,v $
@(#)Version:        $Revision: 1.3 $
@(#)Last changed:   $Date: 2007/10/23 20:23:44 $
@(#)Purpose:        Command to evaluate realpath(3) on given arguments.
@(#)Author:         J Leffler
@(#)Copyright:      (C) JLSS 2007
@(#)Product:        :PRODUCT:
*/

/*TABSTOP=4*/

#if __STDC_VERSION__ >= 199901L
#define _XOPEN_SOURCE 600
#else
#define _XOPEN_SOURCE 500
#endif /* __STDC_VERSION__ */

#include <unistd.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
#include "stderr.h"

static const char optstr[] = "hlsV";
static const char usestr[] = "[-hslV] given-path [...]";
static const char hlpstr[] =
    "  -h   Print this help message\n"
    "  -l   Long format: print given-path and real-path\n"
    "  -s   Short format: print just real-path\n"
    "  -V   Print version and exit\n"
    ;

enum { FMT_LONG, FMT_SHORT };
static int format_type = FMT_LONG;

#ifndef lint
/* Prevent over-aggressive optimizers from eliminating ID string */
extern const char jlss_id_realpath_c[];
const char jlss_id_realpath_c[] = "@(#)$Id: realpath.c,v 1.3 2007/10/23 20:23:44 jleffler Exp $";
#endif /* lint */

static int eval_realpath(const char *given)
{
    char realname[_POSIX_PATH_MAX];
    int rc = 0;

    if (realpath(given, realname) == 0)
    {
        rc = -1;
        err_sysrem("failed to resolve real path name for %s\n", given);
    }
    else if (format_type == FMT_SHORT)
        printf("%s\n", realname);
    else
        printf("%s %s\n", given, realname);
    return(rc);
}

int main(int argc, char **argv)
{
    int i;
    int rc = EXIT_SUCCESS;
    int opt;

    err_setarg0(argv[0]);
    while ((opt = getopt(argc, argv, optstr)) != -1)
    {
        switch (opt)
        {
        case 'V':
            err_version("REALPATH", &"@(#)$Revision: 1.3 $ ($Date: 2007/10/23 20:23:44 $)"[4]);
            break;
        case 'h':
            err_help(usestr, hlpstr);
            break;
        case 'l':
            format_type = FMT_LONG;
            break;
        case 's':
            format_type = FMT_SHORT;
            break;
        default:
            err_usage(usestr);
            break;
        }
    }

    for (i = optind; i < argc; i++)
    {
        if (eval_realpath(argv[i]) != 0)
            rc = EXIT_FAILURE;
    }

    return(rc);
}

我需要它来测试一些评估路径安全性的软件,并且需要确保我的代码正在评估给定路径到相同的解析位置realpath()。使用“-a”选项扩展它可能是明智的,以确保名称映射到绝对名称(通过将结果作为getcwd()相对路径名的前缀)。

(stderr.c 和 stderr.h 的来源,如果您知道在哪里可以找到。或者联系我 - 查看我的个人资料。)

于 2009-10-13T22:50:54.817 回答