Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Win32/Win64 API (native code) (https://www.delphipraxis.net/17-win32-win64-api-native-code/)
-   -   Delphi 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks! (https://www.delphipraxis.net/132962-2-verzeichnisse-physikalisch-identisch-ntfs-hardlinks.html)

blackdrake 22. Apr 2009 21:16


2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Hallo.

Ich möchte gerne herausfinden, ob zwei Verzeichnisse physikalisch identisch sind.

Bis jetzt habe ich folgenden Code:

Delphi-Quellcode:
{$DEFINE CHECK_UNC}

function ExpandFilePath(AFileName: string): string;
begin
  {$IFDEF CHECK_UNC}
  result := ExpandUNCFileName(AFileName);
  {$ELSE}
  result := ExpandFileName(AFileName);
  {$ENDIF}
end;

function AreFilesOrDirectoriesIdentical(A, B: string): boolean;
begin
  A := ExpandFilePath(A);
  B := ExpandFilePath(B);

  // Damit C:\Windows und C:\Windows\ als gleich gekennzeichnet
  // werden, fügen wir beiden einen Backslash hinzu - auch wenn es sich
  // um Dateien handelt.
  // Grund: Sowohl für ExpandUNCFileName() als auch für SameFileName()
  // ist es nicht von Bedeutung, ob die Datei / das Verzeichnis existiert
  // oder nicht.
  // Außerdem teilen sich Dateien und Ordner in allen Betriebssystemen
  // den selben Namensraum.

  A := IncludeTrailingPathDelimiter(A);
  B := IncludeTrailingPathDelimiter(B);

  result := SameFileName(A, B);
end;
Ich kann in diese Funktion Dateien und Ordner reinschrieben und es gibt kein Problem, wenn Pfadangaben durch .. oder . Angaben abgeändert wurden.

Bei NTFS-Dateisystemen gibt es aber jetzt folgende Probleme:

1. Gleiche Verzeichnisse durch NTFS-HardLinks

Die Verzeichnisse
C:\Ordner\Symlink\
und
C:\AndererOrdner\
könnten gleich sein, wenn C:\AndererOrdner\ ein Hardlink von C:\Ordner\Symlink\ ist.

Ebenfalls könnten aber auch
C:\Ordner\Symlink\X\
und
C:\AndererOrdner\X\
gleich sein, obwohl C:\AndererOrdner\X\ kein Hardlink von C:\Ordner\Symlink\X\ ist (denn der Hardlink ist eine Stufe tiefer).

Ich befürchte, dass man eventuell beliebig komplizierte Szenarios hinbekommen kann, bei denen ein eventueller Algorithmus, der den Verzeichnisbaum abläuft, fehlschlagen könnte. Ich bin mir da aber nicht ganz sicher.

1b. Gleiche Verzeichnisse durch Linux-Symlinks

Ich möchte nach Möglichkeit portablen Code schreiben. Deswegen soll Problem #1 auch für Linux' SymLinks funktionieren (durch Compiler-Flag-Variante).
(Leider habe ich derzeit hierfür überhaupt keine Testmöglichkeit.)

2. Gleiche Verzeichnisse durch NTFS-MountPoints

Sei z.B. eine externe Festplatte sowohl auf X:\ als auch in C:\ExterneHDD\ gemounted (letzteres mittels NTFS-MountPoints).

Dann sind X:\ und C:\ExterneHDD\ physikalisch identisch, obwohl (möglichweise) kein echter HardLink vorliegt.

...

Ob es andere Szenarios gibt, bei denen man physikalisch identische Verzeichnisse hinbekommt, bin ich mir nicht ganz sicher.

Könnt ihr mir bitte Tipps oder Codebeispiele geben, wie ich eine Funktion hinbekommen kann, die auch bei NTFS-Hardlinks/Symlinks/NTFS-MountPoints (zuverlässig) funktioniert?

Triviale Lösung: Ich könnte zwar in das Verzeichnis einfach eine Zufallsdatei erstellen und schauen, ob diese im anderen Verzeichnis plötzlich auch erschienen ist ... aber ich erachte das als schlechten Programmierstil, da ich die Datenverzeichnisse der Endanwender nicht mit Temp-Dateien zumüllen möchte.

Gruß
blackdrake

Satty67 22. Apr 2009 22:34

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Vielleicht reicht GetFileInformationByHandle, das ja auch für Directories funktioniert.

Das gibt auch einen FileIndex zurück, der pro Volume eindeutig ist. (Gleiche Volume Number kann ja sowieso vorab getestet werden).

Kommt halt darauf an, ob so ein Hardlink einen eigenen Index bekommt... oder nicht.

Reinhard Kern 22. Apr 2009 23:33

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Zitat:

Zitat von blackdrake
Ich befürchte, dass man eventuell beliebig komplizierte Szenarios hinbekommen kann, bei denen ein eventueller Algorithmus, der den Verzeichnisbaum abläuft, fehlschlagen könnte. Ich bin mir da aber nicht ganz sicher.

Hallo,

soweit ich mich erinnern kann, ist es unter Unix durchaus zu schaffen, einen geschlossenen Kreis von Hardlinks zu konstruieren, in dem das System endlos den Links folgen müsste - tut es glaube ich nicht, da gibt es wohl eine obere Grenze.

Von Unix aus betrachtet kann ich mir nur eine Lösung vorstellen: Backup-Programme u.ä. arbeiten den realen Baum ohne Symlinks ab und speichern die Symlinks als speziellen Dateieintrag, beim Restore werden sie wieder aktiviert. Sonst würde ein Vielfaches an Dateien gespeichert, denn unter Unix werden Symlinks ganz massiv zur Versionskontrolle benutzt: das Programm sucht unter MeinProgramm/Einstellungen, tatsächlich stehen die Daten aber unter MeinProgramm/Version 3.1.56/Einstellungen. Das kann man nur herausbekommen, wenn man sich den Baum ansieht, OHNE den Symlinks zu folgen.

Gruss Reinhard

blackdrake 23. Apr 2009 00:55

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Hallo.

Danke für eure Antworten.

Zu GetFileInformationByHandle habe ich in der MSDN folgendes gefunden:

Zitat:

You can compare the VolumeSerialNumber and FileIndex members returned in the BY_HANDLE_FILE_INFORMATION structure to determine if two paths map to the same target; for example, you can compare two file paths and determine if they map to the same directory.
( http://msdn.microsoft.com/en-us/library/aa364952(VS.85).aspx )

Mir ist dort der Begriff "VolumeSerialNumber" aufgefallen... war das nicht die unaussagekräftige 4-Byte "Seriennummer" des Datenträgers? Wenn ja, wird es Grenzfälle geben, bei denen die Seriennummern gleich, die Datenträger aber unterschiedlich sind. Ein einfaches Beispiel wäre, wenn ich eine Diskette kopiere, dann wäre danach VolumeSerialNumber[A:] == VolumeSerialNumber[B:] und damit würde der Algorithmus zu dem Ergebnis DirIdentical('A:\x\', 'B:\x\') == true kommen, wenn zusätzlich beide Verzeichnisse x auf den Disketten durch Zufall die selbe interne Nummer haben.

Problem 2: Die Funktion kann bei Netzwerklaufwerken fehlschlagen. Was ist dann zu tun? Es kann ja auch ein Netzlaufwerk geben, bei dem der Samba-Daemon den Symlinks folgt.

Ich befürchte, mir bleibt nichts anderes übrig, als wirklich eine Datei in Verzeichnis A zu schreiben und zu schauen, ob sie in Verzeichnis B existiert, wenn ich größtmöglichste Kompatibilität haben möchte.

Gruß
blackdrake

Codewalker 23. Apr 2009 06:52

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Zitat:

Zitat von Reinhard Kern
soweit ich mich erinnern kann, ist es unter Unix durchaus zu schaffen, einen geschlossenen Kreis von Hardlinks zu konstruieren, in dem das System endlos den Links folgen müsste - tut es glaube ich nicht, da gibt es wohl eine obere Grenze.

Das geht relativ einfach: In einem Verzeichnis einen SymLink auf das übergeordnete Verzeichnis anlegen (geht auch unter Windows). Ist das Programm schlecht (z.B. Backup-Tools) wird es eine endlose Verzeichnisfolge auflisten, ist es gut erkennt es den Hardlink und sichert wirklich nur das eine existierende Verzeichnis

DevilsCamp 23. Apr 2009 08:10

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Liste der Anhänge anzeigen (Anzahl: 1)
Unter Linux kann man doch prüfen bei zwei Dateien
1. prüfen ob sie im selben MOUNT hängen
Code:
> df -k .
Sollte die Ausgabe gleich sein bzgl. des Mount-Pointes, so kann man einen Schritt weitergehen und
2. prüfen ob es sich um die selbe INODE handelt (zumindest bei ext2/3/4 Dateisystemen).

Sollten 1 und 2 zutreffen handelt es sich um die selbe Datei/das selbe Verzeichnis.

Möglicherweise ist Schritt 2 bei anderen Dateisystem (native Linux-Dateisysteme) gleich.


Auf NTFS/FAT bin ich mir nicht sicher ob und wie man da an eindeutige Dateiinformationen kommt.

Bzgl. Code für NTFS:
Ich habe da Funktionen mit denen man Hardlinks/Junctions usw. anlegen kann und auch das Ziel eines Hardlinks/Junction bestimmen kann.
Ich weiß nicht mehr, wo ich ihn gefunden habe, kann also den ursprünglichen Autor nicht nennen (ich war es jedenfalls nicht).
Dateien im Anhang.

blackdrake 27. Apr 2009 03:03

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Hallo.

Danke, ich werde mir die Units mal ansehen.

Besonders wichtig ist mir eine Funktion der Form:

Delphi-Quellcode:
function IsSymlink(A, B: string): boolean; // A und B vertauschbar
begin
  {$IFDEF WINDOWS}
  if NTFSAvailable then
    result := NTFS_IsHardLink(A, B)...
  else
    result := false;
  {$ELSE}
  result := Linux_IsSymlink(A, B)... // <-- Problem
  {$ENDIF}
end;
Jetzt suche ich noch eine Funktion, die mit Linux arbeitet und dort den Compilerschalterfall mit sinnvollem Code für die Linux-Dateisysteme belegt. Von den Linux Dateisystem-Interna weiß ich leider recht wenig.

Gruß
blackdrake

DevilsCamp 27. Apr 2009 07:47

Re: 2 Verzeichnisse physikalisch identisch? NTFS-Hardlinks!
 
Für Unix:
Stichworte: fpStat, fpLStat, fpReadLink

Zitat:

FpStat
Retrieve file information about a file descriptor. (Folgt einem Symlink)
Zitat:

fpLstat
Return information about symbolic link. Do not follow the link
Zitat:

fpReadLink
Read destination of symbolic link
Bei einer echten Datei (und bei Hardlinks) sind die Informationen von FpStat und fpLstat identisch, bei Symlinks unterscheiden sie sich. => Sollte recht zuverlässig einen Symlink erkennen. Zur Sicherheit fpReadLink verwenden.

Sollten die Informationen identisch sein, kann es sich um entweder um eine Datei mit Hardlink handeln (falls der Wert für st_nlink aus dem Stat-Record größer 1) oder um die selbe Datei, falls man beim zweiten Pfad per Symlink/hardlink eines Verzeichnisses zu der Datei gelangt (hier kann st_nlink aus dem Stat-Record größer oder gleich 1 sein).
Ist der Wert für st_nlink aus dem Stat-Record gleich 1 so hast du definitiv die selbe Datei betrachtet.


Alle Zeitangaben in WEZ +1. Es ist jetzt 15:55 Uhr.

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz