Вот странное поведение, с которым я столкнулся, и 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 Suite), либо с помощью 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
и раскрыть свою методологию.
Моя рабочая теория на данный момент такова:
mklink
создает «файл»F:\1:bar
и успешно (предположительно черезCreateFile()
).mklink
устанавливаетREPARSE_DATA_BUFFER
на созданном "файле", который не может работать, поскольку это ADS на каталоге. Так что внутри происходит то, что драйвер файловой системы устанавливает буфер данных повторной обработки на каталоге.
Результат — это то, что мы видим. Что меня здесь беспокоит, так это то, что обычно вы не можете получить доступ к каталогу, не указав конкретный флаг. Так что мы не только заставили mklink
создать символическую ссылкув каталогев файл, мы также избежали необходимости указывать FILE_FLAG_BACKUP_SEMANTICS
.
Документация FILE_FLAG_BACKUP_SEMANTICS
поCreateFile
читает:
Вы должны установить этот флаг, чтобы получить дескриптор каталога. Дескриптор каталога может быть передан некоторым функциям вместо дескриптора файла. Для получения дополнительной информации см. раздел «Примечания».
Для воспроизведения я настоятельно советую вамнетпопробуйте сделать это на существующем диске NTFS, но вместо этого создайте новый с помощьюИмДискДрайвер RAM-диска и сопутствующий imdisk
инструмент командной строки (через привилегированное приглашение):
imdisk -a -t vm -p "/fs:ntfs /q /y /v:TEST" -s 4G -m F:
(измените параметры по своему усмотрению. -m
обозначает букву диска и -s
размер RAM-диска.)