Есть ли какой-либо способ POSIX через fstat (), чтобы проверить, является ли файл символической ссылкой или нет? - PullRequest
2 голосов
/ 16 января 2012

Есть ли способ POSIX через fstat(2) проверить, является ли файл символической ссылкой или нет?

В open(2) есть флаг O_NOFOLLOW, который может это проверить, однако это не POSIX.

В fstat(2) есть S_ISLNK, что сказано в man fstat:

   The S_ISLNK() and S_ISSOCK() macros are not in POSIX.1-1996,
   but both are present in POSIX.1-2001; the former is from SVID
   4, the latter from SUSv2.

и компиляция на моей машине не удастся.

Кроме того, есть еще S_IFLNK в lstat(2), однако он не будет работать с fstat(2) (который будет следовать по ссылке на указанный файл).

1 Ответ

3 голосов
/ 16 января 2012

номер

Это не правда, что fstat следует за символическими ссылками. Вместо этого open следует за символическими ссылками. Как только вы доберетесь до fstat, будет слишком поздно и информация исчезнет.

Скажите нам , почему вы должны знать, и мы можем помочь с этой проблемой. (Откройте другой вопрос.)

Как работают файлы:

Вот код псевдо-C / shell:

system("echo 'Hello, World!' >A.txt");
system("ln A.txt B.txt");
system("ln -s A.txt C.txt");

fdes = open("C.txt");
unlink("A.txt");
unlink("C.txt");
data = read(fdes);
write(stdout, data);

Результат: ваша программа печатает "Hello, world!". Состояние мира выглядит так:

+--Application--+    +--Kernel--+    +-------Disk-------+
|               |    |          |    |                  |
|  fdes --------------> file ---------> inode #973 <-------+
|               |    |          |    |  "Hello World!"  |  |
+---------------+    +----------+    |                  |  |
                                     |  directory ---------+
                                     |  "B.txt"         |
                                     |                  |
                                     +------------------+

Что касается ядра, файл открывается "inode # 973". Структура данных в памяти ядра имеет некоторую дополнительную информацию, такую ​​как текущая позиция, но она НЕ знает путь. Ядро не должно знать эту информацию.

Если вы спросите ядро, каков путь, оно может сказать «у вас открыт B.txt». Но вы никогда не открывали «B.txt», вы открывали «C.txt», который был символической ссылкой на «A.txt», и «A.txt» и «C.txt» были удалены (они были просто именами для начать с).

Простая аналогия:

Вам позвонил старый друг. Он спрашивает: «Я посмотрел твой номер в телефонном справочнике, запомнил ли я, или мне нужно было попросить кого-нибудь узнать твой номер?»

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

Решение: Просто используйте lstat (да, есть условие гонки). Если вы не открыли файл самостоятельно (например, вы получили его из родительского процесса или через сокет), то более или менее невозможно узнать, был ли он открыт по символической ссылке.

...