2016-01-11 3 views
-1

Этот вопрос задан раньше, но почти все ответы сводятся к функции realpath. Что не работает для путей, которых не существует. Мне нужно решение, которое будет, и я хочу вызвать функцию фреймворка POSIX или OS X, а не строки с ручным анализом.Системная функция для преобразования относительного пути к полному пути, который работает даже для не-exsting путей?

Повторить: мне нужна функция, которая принимает произвольную строку пути и возвращает эквивалентный путь без элементов «./» или «..».

Есть ли такое решение?

+0

Вы должны указать более подробные сведения о том, что вы действительно хотите сделать, и дать * несколько * примеров (например, в том числе и в тех случаях, когда каталогов, указанных в пути, не существует) –

+0

@BasileStarynkevitch: Я вполне четко объяснил, что я хочу сделать, на мой взгляд. Что нужно уточнить? –

+0

Как вы обрабатываете '/ tmp/someinexistentdirectory/foobar' и'/tmp/someinexistentdirectory /../ foobar'? Я отказался от вашего вопроса, так как вы не сказали, как это сделать. –

ответ

1

Вы уверены, что может быть решение? Я считаю, что нет (потому что некоторые каталоги могут быть опечатками или символическими ссылками, которые должны быть созданы).

Что вы ожидаете от своей функции betterrealpath для возврата на /tmp/someinexistentdirectory/foobar? Возможно, намерение пользователя было символической ссылкой от его $HOME до /tmp/someinexistentdirectory? Или, может быть, это опечатка, и пользователь хочет /tmp/someexistentdirectory/foobar ...? А как насчет /tmp/someinexistentdirectory/../foobar? Должен ли он быть канонизирован как /tmp/foobar? Зачем?

Возможно, используя первый dirname(3), а затем сделать realpath(3) на этом, а затем добавить basename(3) аргумента должно быть достаточно? В C-то вроде:

const char*origpath = something(); 
    char*duppath = strdup(origpath); 
    if (!duppath) { perror("strdup"); exit(EXIT_FAILURE); }; 
    char*basepath = basename(duppath); 
    char*dirpath = dirname(duppath); 
    char*realdirpath = realpath(dirpath, NULL); 
    if (!realdirpath) { perror("realpath"); exit(EXIT_FAILURE); }; 
    char* canonpath = NULL; 
    if (asprintf(&canonpath, "%s/%s", realdirpath, basepath) <= 0) 
    { perror("asprintf"); exit(EXIT_FAILURE); }; 
    free (duppath), duppath = NULL; 
    basepath = NULL, dirpath = NULL; 
    /// use canonpath below, don't forget to free it 

Конечно этот пример не будет работать для /tmp/someinexistentdirectory/foobar, но будет работать на /home/violet/missingfile, предполагая, что ваш домашний каталог /home/violet/ и доступен (читаемый & исполняемый файл) ...

Не стесняйтесь улучшать или адаптировать к C++ приведенный выше код. Не забывайте обрабатывать сбои.

Помните, что i-nodes являются центральными для файловых систем POSIX. Файл (включая каталог) может иметь один, нулевой или несколько путей к файлу ... Имя каталога (или файла) может быть rename -d другим ходом процесса ...

Возможно, вы хотите использовать каркас, такой как Qt или POCO; они могли бы обеспечить что-то достаточно хорошее для вас ...

На самом деле, я предлагаю вам код вашей betterrealpath функции полностью самостоятельно, используя толькоsyscalls(2) на Linux. Затем вы должны думать обо всех странных случаях ... Кроме того, использование strace(1) на realpath(1), чтобы понять, что он делает ...

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

+0

Должно быть решение. Например, в Windows есть один. Если система не знает лучшего (например, путь не существует), он должен хотя бы развернуть «.». и ".." правильно. –

+0

Это * очень плохой * рассуждение. Файловые системы Windows имеют семантику, которая вообще не является POSIX. POSIX имеет жесткие ссылки, возможно, даже в каталогах ... –

+0

У Windows есть ссылки. Кроме того, я не ожидаю, что система что-нибудь угадает. Мне просто нужно очистить существующие пути и преобразовать несуществующие в абсолютную форму. –

Смежные вопросы