Вот странное поведение, с которым я столкнулся mklink который поставляется в Windows с Vista. Я подозреваю, может ли быть дефект в mklink или даже так глубоко, как драйвер файловой системы NTFS, но поведение может использовать некоторые объяснения. Такое поведение встречалось в Windows 7 и 10 соответственно.

Предположим, у нас есть каталог на томе NTFS (сделать НЕ попробуйте это на чем угодно, кроме тома, который вы создаете для этой единственной цели!) и файла с именем bar.txt внутри него.

md F:\1
echo foo > F:\1\bar.txt

Теперь введите следующую команду (через привилегированное приглашение):

mklink F:\1:bar F:\1\bar.txt

... который должен дать вам:

symbolic link created for F:\1:bar <<===>> F:\1\bar.txt

Не беспокойся я знать это глупый , Но это был результат теста, может ли альтернативный поток данных (ADS) стать точкой повторной обработки. Я считал, что это невозможно, потому что альтернативный поток данных имеет только имя, размер и - ну, - данные внутри него. В отличие от файла или каталога, он не имеет атрибутов файла или собственных меток времени, и поэтому не было бы атрибута для обозначения ADS в качестве точки повторной обработки (что в противном случае происходит через атрибуты файла). Или по-другому: точки повторного анализа могут относиться только к в записи каталога (через $Extend\$Reparse ), тогда как ADS привязаны к записям каталога.

Результат приведенной выше команды таков:

F:\>dir /r
 Volume in drive F is TEST
 Volume Serial Number is 24F3-8A7D

 Directory of F:\

2018-04-03  20:47    <SYMLINKD>     1 [F:\1\bar.txt]
                                  0 1:bar:$DATA
               0 File(s)              0 bytes
               1 Dir(s)   4,244,283,392 bytes free

Неудивительно, что попытка перейти в этот каталог не работает и дает The directory name is invalid.

Точно так же попытка удалить точку повторной обработки, либо используя junction -d (из сюиты Sysinternals) или используя fsutil reparsepoint delete терпит неудачу с той же самой ошибкой. Только проверка данных точки повторной обработки дает мне возможность цепляться за:

 F:\>fsutil reparsepoint query F:\1
Reparse Tag Value : 0xa000000c
Tag value: Microsoft
Tag value: Name Surrogate
Tag value: Symbolic Link

Reparse Data Length: 0x00000044
Reparse Data:
0000:  18 00 20 00 00 00 18 00  00 00 00 00 46 00 3a 00  .. .........F.:.
0010:  5c 00 31 00 5c 00 62 00  61 00 72 00 2e 00 74 00  \.1.\.b.a.r...t.
0020:  78 00 74 00 5c 00 3f 00  3f 00 5c 00 46 00 3a 00  x.t.\.?.?.\.F.:.
0030:  5c 00 31 00 5c 00 62 00  61 00 72 00 2e 00 74 00  \.1.\.b.a.r...t.
0040:  78 00 74 00                                       x.t.

Теперь мой вопрос: что здесь произошло, и как мне снова избавиться от такой точки повторной обработки с помощью встроенных инструментов Windows (или, в случае неудачи, внешних)? Бонусные баллы за возможность ответить на то, что случилось с файлом внутри папки 1 и раскрытие вашей методологии.

Моя рабочая теория до сих пор выглядит следующим образом:

  1. mklink создает "файл" F:\1:bar и успешно (предположительно через CreateFile() ).
  2. mklink устанавливает REPARSE_DATA_BUFFER на созданный «файл», который не может работать, поскольку это ADS для каталога. Так что внутренне происходит то, что драйвер файловой системы устанавливает буфер повторных данных в каталоге.

Результат - это то, что мы видим. Что меня беспокоит, так это то, что обычно вы не можете получить указатель на каталог без указания определенного флага. Так что мы не только вызвали mklink создать символическую ссылку в каталоге в файл, мы также избежали необходимости указывать FILE_FLAG_BACKUP_SEMANTICS,

Документация FILE_FLAG_BACKUP_SEMANTICS под CreateFile гласит:

Вы должны установить этот флаг, чтобы получить указатель на каталог. Каталог   handle может быть передан некоторым функциям вместо дескриптора файла. За   более подробную информацию смотрите в разделе «Замечания».


Для воспроизведения я настоятельно советую вам не попробуйте это на существующем диске NTFS, но вместо этого создайте новый, используя ImDisk Драйвер RAM-диска и сопутствующий imdisk инструмент командной строки (через привилегированное приглашение):

imdisk -a -t vm -p "/fs:ntfs /q /y /v:TEST" -s 4G -m F:

(измените параметры так, как считаете нужным. -m обозначает букву диска и -s размер оперативной памяти.)

0xC0000022L
источник