如何检查路径是否在c中的目录之外?

时间:2019-04-10 13:03:30

标签: c linux bash path directory

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

我在"./"

比方说,当前目录包含一个名为“文件夹”的文件夹

我想检查cd "./folder/../../"是否将我引到“ ./”之外。 在这种情况下,它会回答我对。

这是将我的程序绑定到其执行文件夹(我希望它执行ls,但永远不在外面)。

3 个答案:

答案 0 :(得分:4)

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

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

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

realpath()扩展所有符号链接并解析对以path命名的以空字符结尾的字符串中的/.//../和其他'/'字符的引用,以产生规范化的绝对​​路径名。结果路径名以空终止的字符串形式存储,最多PATH_MAX个字节,存储在resolved_path指向的缓冲区中。结果路径将没有符号链接,/.//../组件。

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

#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;
}

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

答案 1 :(得分:0)

伪代码:


获取当前的完整路径(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

答案 2 :(得分:0)

您可以计算出与“ ..”,“。” 、:相匹配的组件数:

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]);
}

转义捕获路径是否尝试从当前工作目录下的树中转义。可能值得用特殊的大小写将“ /”作为转义符。

还有其他一些方法可以解码绝对路径空间,但是可能导致超范围(imho,一种常见的系统故障模式)。我以所有者的身份,可能希望您的程序至少以有限的方式接受逃避名称空间的路径名。符号链接对此非常有效,不需要特殊的管理控制等。如果您的程序阻止这种配置,那么它的实用程序就会减少。