Hier ist ein seltsames Verhalten, mklink
das mir seit Vista in Windows aufgefallen ist. Ich vermute, dass es sich um einen Defekt im mklink
NTFS-Dateisystemtreiber oder sogar um einen so schwerwiegenden Defekt handelt, aber das Verhalten bedarf einer Erklärung. Dieses Verhalten trat unter Windows 7 bzw. 10 auf.
Angenommen, wir haben ein Verzeichnis auf einem NTFS-Volume (NICHTVersuchen Sie dies auf allem außer einem Datenträger, den Sie ausschließlich zu diesem Zweck erstellen!) und einer bar.txt
darin benannten Datei.
md F:\1
echo foo > F:\1\bar.txt
Geben Sie nun den folgenden Befehl ein (über die privilegierte Eingabeaufforderung):
mklink F:\1:bar F:\1\bar.txt
... das sollte Ihnen Folgendes geben:
symbolic link created for F:\1:bar <<===>> F:\1\bar.txt
Keine Sorge, ichwissendas istdumm. Aber es war das Ergebnis eines Tests, ob ein Alternate Data Stream (ADS) ein Reparse Point werden könnte. Ich war der Meinung, dass dies nicht möglich sei, da ein Alternate Data Stream nur einen Namen, eine Größe und - nun ja - die darin enthaltenen Daten hat. Im Gegensatz zu einer Datei oder einem Verzeichnis hat er keine Dateiattribute oder eigene Zeitstempel, und daher gäbe es kein Attribut, um den ADS als Reparse Point zu kennzeichnen (was sonst durch die Dateiattribute geschieht). Oder anders ausgedrückt: Reparse Points können nur verweisenZuVerzeichniseinträge (über $Extend\$Reparse
), während ADS an Verzeichniseinträge gebunden sind.
Das Ergebnis des obigen Befehls ist folgendes:
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
Wenig überraschend funktioniert der Versuch, in dieses Verzeichnis zu wechseln, nicht und führt zuThe directory name is invalid.
Ebenso schlägt der Versuch, den Analysepunkt entweder mit junction -d
(aus der Sysinternals Suite) oder mit zu löschen fsutil reparsepoint delete
, mit demselben Fehler fehl. Nur die Überprüfung der Analysepunktdaten gibt mir etwas, an dem ich mich festhalten kann:
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.
Meine Frage ist nun, was hier passiert ist und wie ich mit integrierten Windows-Tools (oder ggf. externen) einen solchen Reparse Point wieder loswerde?Bonuspunkte gibt es, wenn Sie die Frage beantworten können, was mit der Datei im Ordner passiert ist, 1
und Ihre Methodik offenlegen.
Meine bisherige Arbeitstheorie ist wie folgt:
mklink
erstellt die „Datei“F:\1:bar
und ist erfolgreich (vermutlich überCreateFile()
).mklink
setzt dieREPARSE_DATA_BUFFER
auf die erstellte „Datei“, was nicht funktionieren kann, da es sich um ein ADS auf einem Verzeichnis handelt. Intern passiert also Folgendes: Der Dateisystemtreiber setzt den Reparse-Datenpuffer auf dem Verzeichnis.
Das Ergebnis ist das, was wir sehen. Was mich hier stört, ist, dass man normalerweise keinen Zugriff auf ein Verzeichnis erhält, ohne ein bestimmtes Flag anzugeben. Wir haben also nicht nur mklink
einen symbolischen Link erstelltin einem Verzeichniszu einer Datei haben wir auch die Notwendigkeit umgangen, anzugeben FILE_FLAG_BACKUP_SEMANTICS
.
Die Dokumentation von FILE_FLAG_BACKUP_SEMANTICS
unterCreateFile
lautet:
Sie müssen dieses Flag festlegen, um einen Handle für ein Verzeichnis zu erhalten. An einige Funktionen kann anstelle eines Dateihandles ein Verzeichnishandle übergeben werden. Weitere Informationen finden Sie im Abschnitt „Hinweise“.
Zur Reproduktion empfehle ich Ihnen dringend,nichtVersuchen Sie dies auf einem vorhandenen NTFS-Laufwerk, sondern erstellen Sie stattdessen ein neues mit demImDiskRAM-Disk-Treiber und das zugehörige imdisk
Befehlszeilentool (über privilegierte Eingabeaufforderung):
imdisk -a -t vm -p "/fs:ntfs /q /y /v:TEST" -s 4G -m F:
(Ändern Sie die Parameter nach Belieben. -m
bezeichnet einen Laufwerksbuchstaben und -s
die Größe der RAM-Disk.)