Пользователь
0,0
рейтинг
6 февраля 2009 в 16:51

Непредсказуемые символические (символьные) ссылки в Windows.

Причиной написания была эта статья Ссылки в Windows, символические и не только. Ее и можно почитать для ознакомление с тем, что такое жёсткие и символические ссылки в ntfs.
Я же продолжу и поделюсь некоторыми фактами о не очевидном поведении этих ссылок.

Сразу сделаю замечание. Если с жёсткими ссылками (Hard Links) неоднозначность вроде не наблюдается, то с мягкими или символическими ссылками есть путаница. Так вот я далее буду говорить о тех символических ссылках которые делаются программой Junction ( а также Alax.Info NTFS Links, Link Shell Extension и т.п.)
Подопытными программами были: Total Commander, Far, Frigate3, Servant Salamander, WinDirStat и Explorer в Windows XP.

Рекурсия.



Впервые с проблемами ссылок я столкнулся несколько лет назад, когда пытался написать «супер-пупер» утилиту по поиску и удалению дубликатов. Оказалось, что представляемые ОС механизмы поиска и обхода каталогов впадают в рекурсию при обработке каталогов в которых есть символическая ссылка на себя или родительский каталог. Конечно это можно избежать, если распознавать ссылки и обрабатывать их особым образом, отдельно от каталогов. Но дипломный проект прервал разработку утилиты, а потом я решил не тратить время на создание очередного «чистильщика дубликатов». Сейчас думаю, что зря.
Дело в том, что большинство программ, работающие с файлами не знают про символьные ссылки. И вот к чему это приводит.

Поиск.


Создадим каталог
X:\000
В нем создадим файл text.txt и символическую ссылку 111 на этот же каталог X:\000
Вот что выдадут при поиске файла наши подопытные файл-менеджеры кроме Far-а
X:\000\text.txt
X:\000\111\text.txt
X:\000\111\111\text.txt
X:\000\111\111\111\text.txt
X:\000\111\111\111\111\text.txt
X:\000\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\111\111\111\111\text.txt
X:\000\111\111\111\111\111\111\111\111\111\111\111\111\111\111\111\text.txt

Радует что рекурсия прервалась так рано. Но все равно такое поведение неправильно и может привести к ошибкам. Тут мы нашли один и тот же файл 16 раз. Многие программы для поиска дубликатов предложат удалить этот файл, как дубликат. Хотя на самом деле файл вполне уникален.
А вот Far, оказывается, при поиске вообще не переходит по символическим ссылкам.

Размер каталога


Такое поведение приводит к интересным эффектам при определении размера каталога. Можно сделать так, что этот размер окажется во много раз больше размера диска. Например на моем ноутбуке есть папка размером 300 Тб. Такой же фокус с размерами можно сделать используя жёсткие ссылки.
image
Среди подопытных программ правильно определили размер только WinDirStat и Explorer.
С эксплорером все понятно — он и реализация символических ссылок в windows детище одной и той же фирмы и было бы странно если они неправильно использовали свой же механизм ссылок. А вот WinDirStat так хорошо знаком со ссылками, наверное потому, что родом из Linux.

Копирование символических ссылок


При копировании ссылок подопытные файл-менеджеры вели себя по разному.
* Far — копировал символические ссылки как ссылки. Т.е. делал копию ссылки и не ее содержимого.
* Explorer на каждую ссылку задавал вопрос — копировать ее как каталог или как ссылку. Но я подозреваю что такое умное поведение ему придала установленная утилита Alax.Info NTFS Links. Проверить как ведет себя Explorer на windows xp без всяких расширений я не смог, а на windows 2000 explorer ведет при копировании себя как far.
* Все остальные подопытные копировали ссылки как каталоги.
При копировании ссылок нужно понимать, что это такое. Если ссылки копировать как файлы, то я например не смогу скопировать свою папочку «ИНТЕРНЕТ» в ближайшее время. Если же копировать ссылки как ссылки, то может оказаться, что скопированный на другой hdd в фаре каталог с фильмами у друга не откроется, так как внутри были символьные ссылки. А то куда они ссылались осталось на другом hdd. В общем при копировании наиболее правильно ведет себя Explorer в установленным правильным расширением.

Тут я решил проверить, а поддерживают ли архиваторы символические ссылки. Оказалось что нет. Все архиваторы из моей коллекции (в том числе 7Z, winrar ) не сохраняют символические ссылки. К сожалению в моей коллекции не оказалось портированных архиваторов вроде tar-а. Надеюсь, что программы из линукса опять помогут.

Что касается жёстких ссылок на файл, то все программы копируют, архивируют их как файлы, не распознавая ссылка это или нет. В принципе, это ожидаемо.

Удаление символических ссылок.


При удалении символических ссылок отличились Frigate3 и Servant Salamander. Они не только удалили ссылку, но и заботливо очистили содержимое каталога на который она ссылалась. Остальные подопытные удалили только ссылку.

Параноикам.


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

Выводы.


Наверное потому, что символические ссылки не были популярны в Windows многие программисты про них забывают. А может ссылки потому и не популярны, что программисты про них забывают и их программы работают с ссылками как получится. В общем будьте внимательны при использовании символических и жестких ссылок и проверяйте как ваш файл-менеджер с ними обращается.

ЗЫ. Оказывается не хватает кармы, что бы писать в тематический блог. Ну да ладно. Может и тут кому полезно будет.

UPD: Эксперименты проводились в Microsoft Windows XP Home Edition 32bit SP3
Total Commander 7.04a
Far 1.70
Servant Salamander 2.0
WinDirStat 1.1.2.80 (Unicode)
Frigate 3.21.2.71
Explorer 6.00.2900.5512

Учел замечание Busla и поменял перевод Symbolic link на более распространенный вариант.

UPD2:
Дабы еще раз уточнить о чем речь и убрать разногласия в терминологии посеянные с легкой руки MS.
Полистав msdn я так понял, что в конце концов в MS пришли к единому мнению. Вроде как. И в Windows Vista сделали некие symbolic link которые создаются функцией CreateSymbolicLink .
А те символьные == символические == мягкие ссылки которые были (и есть) в ранних версиях Windows (2000,XP) являются некими reparse point. И создаются примерно так:
memset(reparseInfo, 0, sizeof(*reparseInfo));
reparseInfo->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
reparseInfo->ReparseTargetLength =
_tcslen(targetNativeFileName) * sizeof(WCHAR);
reparseInfo->ReparseTargetMaximumLength =
reparseInfo->ReparseTargetLength + sizeof(WCHAR);
_tcscpy(reparseInfo->ReparseTarget, targetNativeFileName);
reparseInfo->ReparseDataLength = reparseInfo->ReparseTargetLength + 12;

DeviceIoControl(
hFile,
FSCTL_SET_REPARSE_POINT,
reparseInfo,
reparseInfo->ReparseDataLength + REPARSE_MOUNTPOINT_HEADER_SIZE,
NULL,
0,
&returnedLength,
NULL);

Так вот, поскольку у меня не виста, речь идет о reparse point. Хотя я предполагаю, что и symbolic link тоже преподнесут сюрприз неоднозначным поведением в разных программах. Ибо проблема в основном не в ссылках, а в том что некоторые программисты про них забывают.
Владимир @vpbar
карма
29,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое

Комментарии (14)

  • 0
    /* Правда, мне не понятно, почему я не могу удалить одну жесткую ссылку на файл, если он открыт по другой жесткой ссылке. */

    Ну с этим-то просто — это продолжение той же логики что не даёт удалить файл если он открыт другим процессом. В обоих случаях реальный файл один.
    • +1
      Ой, вру… Видимо, особенность реализации. Всё-таки позволить удалять в таком случае мне видится более логичным чем запрещать.
      • 0
        Вот вот. Я понимаю запрет записи. А запрещать удалять другое имя нелогично. Но видимо проще cтавить флаги на id файла (или как оно там называется), а не на каждое имя в отдельности.
      • +2
        А по-моему такое поведение вполне логично и любая другая реализация была бы шизофренией. В Linux — всё просто: открытый файл удалять можно — независимо от того, сколько у него имён. В Windows — тоже просто: нельзя удалять имена, если файл, на который они ссылаются, открыт. А вы что предлагаете? Запоминать имя, которое использовалось для открытия файла? Только для того чтобы устроить такое странное поведение??? Какой в этом смысл???
  • +2
    Вывод прост — авторы некоторых вышеуказанных программ не знают об этой возможности NTFS.

    Ещё есть похожий интересный вопрос. Недавно на Хабре проскакивало, что Windows в приципе в ядре различает регистр символов в именах файлов. (То, что NTFS их различает, известно давно.)
    Так вот, насколько больны программы этим? Насколько они чувствительны к регистру; если я создаю файл большими буквами, может ли программа создать его маленькими?

    Вопрос тем более интересен, что ведь в Windows можно посредством IFS-драйвера подключить ext2/ext3 (и даже разместить там своп-файл). Насколько сильно удивятся программы, когда увидят в одной директории два разных файла: test.txt и Test.txt?
    • 0
      >Насколько сильно удивятся программы, когда увидят в одной директории два разных файла: test.txt и Test.txt?

      Программы не удивятся вообще, поскольку даже не узнают, что этих файлов там 2 — драйвер «выдаст» (или не выдаст) программе необходимый файл. Т.е. если программа попросит у драйвера test.txt — то он ей выдаст именно этот файл, а не Test.txt

      Что касается NTFS — поддержка case-sensetive имён файлов реализуется флагом FILE_FLAG_POSIX_SEMANTICS в функции Create File. Т.е. если этот флаг стоит, то драйвер NTFS будет отдавать этот файл только по его точному имени.
      • 0
        Вы бы попробовали проверить то, что поёте, а? Программы таки получают два файла в списке и с открытием творится бардак. Что там отдаёт драйвер NTFS — одному богу ведомо, а вот что отдаёт Windows — известно: один какой-то файл независимо от того, какой запросили (однако просмотр каталога через FindFirstFile/FindNextFile выдаст две записи, а не одну). Вот если и при создании файла и при открытии задавать флаг FILE_FLAG_POSIX_SEMANTICS — тогда всё честно, а вот если при создании его задать, а при открытии нет… весело будет… А с учётом того, что мало какие программы позволяют этим флагом управлять… Лучше так не делать — вот и всё что на эту тему можно сказать…
        • 0
          Объясняю:

          1) Первый мой абзац касается драйверов ext2 под виндовс, поскольку там наименование файлов происходит «честно», то их содержимое отдаваться просто по имени.

          2) С NTFS всё сложнее — дело в том, что CreateFile отдает один и тот handle на всё файлы с именами различающимися только регистром, поэтому приложение будет получать содержимое одного и того же файла если обращается к нему через OpenFile например. Причем будет возвращаться содержимое того файла, у которого имя в строковом представлении больше чем у других (это моё эмпирическое исследование), например если создано 3 файла TEST > TEst > test — то сначала будет возвращаться содержимое TEST, если удалить какой-то из файлов — то будет возвращаться содержимое TEst и т.д. Поэтому я согласен, что последнее мое предложение было несколько опрометчивым.

          • 0
            У меня под Windows на C:\ сейчас два каталога, «Work» и «work» :) При попытке войти в любой из них входит только в один из них.

            Сделал по ошибки из под Linux, грохнуть лишний всё забываю, когда сижу в Linux и не могу, пока сижу в Windows ;)
  • +1
    Был у меня когда-то пример для работы с символьными ссылками. Скрипт .bat на пару строк.
    Теперь у меня в обной папке есть ссылка…
    Free Image Hosting at www.ImageShack.us

    Видит её только тоталкоммандер или фар, эксплорер не видит.
    И не удаляется ни чем.
  • +1
    Не понимаю, я вас граждане — ни автора этой заметки, ни предыдущей: почему вы сразу начинаете писать исключительно собственные измышления. Ладно — писать, но публиковать-то зачем, если не разу не заглянули в официальную документацию?!
    В MSDN чётко написано, что soft links и symbolic links — разные сущности. Вы же сами таким фразочками:
    с мягкими или символьными ссылками есть путаница. Так вот я далее буду говорить о тех символьных ссылках которые делаются программой Junction
    путаницу только увеличиваете.
    Более того: устоявшийся термин символические ссылки, а не символьные — именно так они упоминаются в справке Windows и огромном количестве литературы по Unix, Linux, Windows.
    Что касается «фактов о не очевидном поведении этих ссылок» — поведение меняется в зависимости от версии Windows — о чём опять же на сайтах MS написано, даже с примерами:
    Under Windows Server 2003, if you copy %systemroot%\SYSVOL, you do not copy the junction points. However, under Windows 2000, if you copy %systemroot%\SYSVOL, you do copy the junction points.
    У вас даже не указано на какой XP вы экспериментировали: 32 или 64, какой SP.
    • +2
      Ладно — писать, но публиковать-то зачем, если не разу не заглянули в официальную документацию?!
      Затем что официальная документация сама себе противоречит. То, на что вы сослались — всего лишь последняя версия сказки о символьных ссылках. То, что Microsoft любит давать одинаковым вещам разные названия и разным вещам одинаковые — ни для кого не секрет (чего стоит одно переименование ISO9660 в «Mastered», а UDF — в «Live File System») и то, что фразы типа directory symbolic links are known as NTFS junctions in Windows до сих пор встречаются на сайте этой замечательной фирмы не делает вещи проще и понятнее...
      Что касается «фактов о не очевидном поведении этих ссылок» — поведение меняется в зависимости от версии Windows.
      Это делает оное поведение более очевидным? Вот в Unix/Linux где символьные ссылки появились не одно десятилетие назад и где поведение не зависит от версии — там всё просто и понятно. А в Windows… тёмный лес и куча дров…
    • +2
      Учел замечания — указал версии программ. Но что касается названий. Воспользуемся сайтом microsoft.com
      от сюда первая цитата
      «Windows 2000 and higher supports directory symbolic links, where a directory serves as a symbolic link to another directory on the computer. For example, if the directory D:\SYMLINK specified C:\WINNT\SYSTEM32 as its target, then an application accessing D:\SYMLINK\DRIVERS would in reality be accessing C:\WINNT\SYSTEM32\DRIVERS. Directory symbolic links are known as NTFS junctions in Windows.» С моим скромным английским я понял так, что символические ссылки на директорию известны так же как junctions.
      Смотрим отсюда " A junction (also called a soft link) differs from a hard link in that the storage objects it references are separate directories, and a junction can link directories located on different local volumes on the same computer."
      junction так же именуемые как мягкие ссылки. Банальная транзитивность предполагаемая в таких случаях приводит к тому что если «символические ссылки==junctions» и «junctions== мягкие ссылки» то «символические ссылки == мягкие ссылки»
    • 0
      Как вы понимаете, если фича реализована по-разному в разных версиях системы, это всё равно, что фичи нет. (А что, даже в разных XP по-разному!? Иначе — зачем указывать, какая именно XP?)

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.