Как проверить, ведет ли путь за пределы каталога в c?

Я пытаюсь проверить, ведет ли путь к «верхнему», чем текущий каталог. Пример :

Я внутри "./"

Допустим, текущий каталог содержит папку с именем «папка».

Я хочу проверить, выведет ли cd "./folder/../../" меня за пределы "./". В этом случае он ответил бы мне Верно.

Это должно связать мою программу с ее папкой выполнения (я хочу, чтобы она выполняла ls, но никогда снаружи).

В C нет стандартной функции для этого. Вам нужно подсчитать количество «../» и количество «text/», и на основе этих подсчетов вы должны выяснить, находится ли путь за пределами каталога.

MayurK 10.04.2019 15:06

Вы можете посмотреть, как readlink реализует опцию -f.

Simon Doppler 10.04.2019 15:11

См. здесь

Simon Doppler 10.04.2019 15:19
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
291
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Псевдокод:


Get the current full path (pwd)
cd to the new path
get the new full path
if new full path starts with old full path, it's in*
  • вам может понадобиться сканировать возможность символических ссылок и т. д., Но если это не проблема, это должно справиться с этим.

Давненько не делал 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 of PATH_MAX bytes, in the buffer pointed to by resolved_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 ссылается на несуществующие объекты пути.

Andrew Henle 10.04.2019 15:47

Вы можете подсчитать количество компонентов, которые соответствуют "..", ".", :

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

Сбежал фиксирует, пытался ли путь покинуть дерево в текущем рабочем каталоге. Вероятно, стоит использовать специальный корпус с ведущей «/» в качестве побега.

Существуют и другие подходы, которые декодируют абсолютное пространство путей, но могут привести к чрезмерному охвату (имхо, общий режим сбоя системы). Я, как владелец, мог бы захотеть, чтобы ваша программа принимала имена путей, выходящие за пределы вашего пространства имен, по крайней мере, ограниченным образом. Для этого хорошо подходят символические ссылки, они не требуют особого административного контроля и т. д. Если ваша программа не допускает такой конфигурации, ее полезность снижается.

Другие вопросы по теме