Oto kilka dziwnych zachowań, z którymi się spotkałem mklink który jest dostarczany w systemie Windows od wersji Vista. Podejrzewam, że może to być wada mklink lub nawet tak głęboki jak sterownik systemu plików NTFS, ale zachowanie może wykorzystywać pewne wyjaśnienia. To zachowanie wystąpiło odpowiednio w systemach Windows 7 i 10.

Załóżmy, że mamy katalog na woluminie NTFS (zrób NIE spróbuj tego na cokolwiek innego niż wolumin, który tworzysz tylko w tym celu!) i plik o nazwie bar.txt wewnątrz tego.

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

Teraz wykonaj następujące polecenie (za pomocą uprzywilejowanego monitu):

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

... co powinno ci dać:

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

Nie martw się, ja wiedzieć to jest głupi . Ale był to wynik testu, czy alternatywny strumień danych (ADS) może stać się punktem ponownej analizy. Uznałem, że nie może, ponieważ alternatywny strumień danych ma tylko nazwę, rozmiar i - cóż - dane wewnątrz niego. W przeciwieństwie do pliku lub katalogu nie ma atrybutów plików ani własnych znaczników czasu, a więc nie byłoby atrybutu oznaczającego ADS jako punkt ponownej analizy (co w innym przypadku odbywa się za pomocą atrybutów pliku). Lub inaczej: punkty ponownej analizy mogą się odnosić tylko do wpisy do katalogu (przez $Extend\$Reparse ), podczas gdy ADS są powiązane z wpisami do katalogu.

Wynikiem powyższego polecenia jest:

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

Nic dziwnego, że próba zmiany w tym katalogu nie działa i przynosi efekty The directory name is invalid.

Podobnie próba usunięcia punktu ponownej analizy przez użycie junction -d (z pakietu Sysinternals) lub za pomocą fsutil reparsepoint delete kończy się niepowodzeniem z tym samym błędem. Tylko sprawdzanie danych punktu ponownej analizy daje mi coś do trzymania się:

 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.

Teraz moje pytanie brzmi: co się tu stało i jak ponownie pozbyć się takiego punktu ponownej analizy za pomocą narzędzi Windows na pokładzie (lub, jeśli to niemożliwe, zewnętrznych)? Dodatkowe punkty za to, że potrafisz odpowiedzieć na to, co stało się z plikiem w folderze 1 i ujawniając twoją metodologię.

Moja dotychczasowa teoria pracy wygląda następująco:

  1. mklink tworzy „plik” F:\1:bar i odnosi sukces (prawdopodobnie przez CreateFile() ).
  2. mklink ustawia REPARSE_DATA_BUFFER na utworzonym „pliku”, który nie może działać, ponieważ jest ADS w katalogu. Tak więc wewnętrznie sterownik systemu plików ustawia bufor danych do ponownej analizy w katalogu.

Rezultat jest tym, co widzimy. Martwi mnie to, że normalnie nie można uzyskać uchwytu w katalogu bez określenia konkretnej flagi. Więc nie tylko spowodowaliśmy mklink aby utworzyć dowiązanie symboliczne w katalogu do pliku uniknęliśmy również konieczności określania FILE_FLAG_BACKUP_SEMANTICS.

Dokumentacja FILE_FLAG_BACKUP_SEMANTICS pod CreateFile brzmi:

Musisz ustawić tę flagę, aby uzyskać uchwyt do katalogu. Katalog   uchwyt może zostać przekazany do niektórych funkcji zamiast uchwytu pliku. Dla   więcej informacji, patrz sekcja Uwagi.


Aby się reprodukować, zdecydowanie radzę nie spróbuj tego na istniejącym dysku NTFS, ale zamiast tego utwórz nowy za pomocą ImDisk Sterownik dysku RAM i towarzyszące mu imdisk narzędzie wiersza poleceń (za pośrednictwem uprzywilejowanego monitu):

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

(zmień parametry według własnego uznania). -m oznacza literę dysku i -s rozmiar dysku RAM.)

0xC0000022L
źródło