【问题标题】:How to check if a path leads outside of a directory in c?如何检查路径是否在c中的目录之外?
【发布时间】:2019-08-31 22:56:57
【问题描述】:

我正在尝试检查路径是否通向当前目录的“上层”。 示例:

我在里面"./"

假设当前目录包含一个名为“文件夹”的文件夹

我想检查cd "./folder/../../" 是否会引导我离开“./”。 在这种情况下,它会回答我 True。

这是为了将我的程序绑定到它的执行文件夹(我希望它执行 ls 但从不在外面)。

【问题讨论】:

  • C 中没有标准函数。您需要计算“../”的数量和“text/”的数量,并根据这些计数,您应该找出路径是否在外面目录。
  • here

标签: c linux bash path directory


【解决方案1】:

POSIX.1-2001 定义realpath(3):

#include <limits.h>
#include <stdlib.h>

char *realpath(const char *path, char *resolved_path);

realpath() 扩展所有符号链接并解析对/.//../ 和额外'/' 字符的引用,以生成规范化的绝对​​路径名。生成的路径名作为空终止字符串存储在resolved_path 指向的缓冲区中,最大为PATH_MAX 字节。生成的路径将没有符号链接,/.//../ 组件。

您可以将规范化路径与当前目录进行比较,看看前者是否是后者的后代。

#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

bool is_inside(const char *parent, const char *child) {
    char *abs_parent = realpath(parent, NULL);
    if (!abs_parent) { perror(parent); exit(EXIT_FAILURE); }

    char *abs_child  = realpath(child,  NULL);
    if (!abs_child)  { perror(child);  exit(EXIT_FAILURE); }

    size_t parent_len = strlen(abs_parent);
    size_t child_len  = strlen(abs_child);

    bool result = strncmp(abs_parent, abs_child, parent_len) == 0 &&
        (child_len == parent_len || abs_child[parent_len] == '/');

    free(abs_parent);
    free(abs_child);

    return result;
}

int main(int argc, char **argv) {
    if (argc != 3) {
        fprintf(stderr, "usage: %s <parent> <child>\n", argv[0]);
        return 1;
    }

    printf("%s\n", is_inside(argv[1], argv[2]) ? "yes" : "no");
    return 0;
}

请注意,这仅在路径存在时才有效。

【讨论】:

  • 请注意,如果path 引用不存在的路径对象,realpath() 将不起作用。
【解决方案2】:

您可以计算匹配“..”、“.”、:

的组件数量
for (p = strtok(path, "/"); p; p = strtok(NULL, "/")) {
        if (strcmp(p, "..") == 0) {
                counters[Back]++;
        } else if (strcmp(p, ".") == 0) {
                counters[Self]++;
        } else if (*p) {  /* ignore /// runs */
                counters[Forw]++;
        }
        escaped |= (counters[Back] > counters[Forw]);
}

Escaped 捕获路径是否试图从当前工作目录下的树中逃逸。可能值得将前导的“/”特殊套管作为转义。

还有其他方法可以解码绝对路径空间,但可能会导致超出范围(恕我直言,这是一种常见的系统故障模式)。我,作为所有者,可能希望您的程序至少以有限的方式接受逃离您的命名空间的路径名。符号链接可以很好地解决这个问题,不需要特殊的管理控制等...如果您的程序阻止了这种配置,那么它的实用性就会降低。

【讨论】:

    【解决方案3】:

    伪代码:


    获取当前完整路径 (pwd)
    cd 到新路径
    获取新的完整路径
    如果新的完整路径以旧的完整路径开头,它在*
    • 您可能需要扫描符号链接 &c 的可能性,但如果这不是问题,则应该处理它。

    有一段时间没有完成C,但这里是bash 中相同逻辑的快速破解

    $: pwd
    /tmp/sandbox
    $: cur=$(pwd)
    $: cd ./folder/../../
    $: pwd
    /tmp
    $: pwd|grep "^$cur" && echo in || echo out
    out
    
    $: cd -
    /tmp/sandbox
    $: pwd|grep "^$cur" && echo in || echo out
    /tmp/sandbox
    in
    
    $: cd ./folder/
    $: pwd|grep "^$cur" && echo in || echo out
    /tmp/sandbox/folder
    in
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-02
      • 2011-04-24
      • 2016-09-10
      相关资源
      最近更新 更多