Я пытаюсь проверить, ведет ли путь к «верхнему», чем текущий каталог. Пример :
Я внутри "./"
Допустим, текущий каталог содержит папку с именем «папка».
Я хочу проверить, выведет ли cd "./folder/../../" меня за пределы "./".
В этом случае он ответил бы мне Верно.
Это должно связать мою программу с ее папкой выполнения (я хочу, чтобы она выполняла ls, но никогда снаружи).
Вы можете посмотреть, как readlink реализует опцию -f.
См. здесь





Псевдокод:
pwd)Давненько не делал 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
POSIX.1-2001 определяет реальный путь(3):
#include <limits.h> #include <stdlib.h> char *realpath(const char *path, char *resolved_path);
realpath()expands all symbolic links and resolves references to/./,/../and extra'/'characters in the null-terminated string named by path to produce a canonicalized absolute pathname. The resulting pathname is stored as a null-terminated string, up to a maximum ofPATH_MAXbytes, in the buffer pointed to byresolved_path. The resulting path will have no symbolic link,/./or/../components.
Вы можете сравнить канонизированный путь с текущим каталогом и посмотреть, является ли первый потомком второго.
#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;
}
Обратите внимание, что это работает, только если пути существуют.
Обратите внимание, что realpath() не будет работать, если path ссылается на несуществующие объекты пути.
Вы можете подсчитать количество компонентов, которые соответствуют "..", ".", :
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]);
}
Сбежал фиксирует, пытался ли путь покинуть дерево в текущем рабочем каталоге. Вероятно, стоит использовать специальный корпус с ведущей «/» в качестве побега.
Существуют и другие подходы, которые декодируют абсолютное пространство путей, но могут привести к чрезмерному охвату (имхо, общий режим сбоя системы). Я, как владелец, мог бы захотеть, чтобы ваша программа принимала имена путей, выходящие за пределы вашего пространства имен, по крайней мере, ограниченным образом. Для этого хорошо подходят символические ссылки, они не требуют особого административного контроля и т. д. Если ваша программа не допускает такой конфигурации, ее полезность снижается.
В C нет стандартной функции для этого. Вам нужно подсчитать количество «../» и количество «text/», и на основе этих подсчетов вы должны выяснить, находится ли путь за пределами каталога.