Wir haben ein sehr altes, nicht unterstütztes Programm, das Dateien über SMB-Freigaben kopiert. Es verfügt über einen Prüfsummenalgorithmus, um festzustellen, ob sich der Dateiinhalt vor dem Kopieren geändert hat. Der Algorithmus scheint leicht zu täuschen - wir haben gerade ein Beispiel gefunden, bei dem zwei Dateien, die bis auf eine einzige "1" identisch sind und zu einer "2" wechseln, dieselbe Prüfsumme zurückgeben. Hier ist der Algorithmus:Kann dieser Prüfsummenalgorithmus verbessert werden?
unsigned long GetFileCheckSum(CString PathFilename)
{
FILE* File;
unsigned long CheckSum = 0;
unsigned long Data = 0;
unsigned long Count = 0;
if ((File = fopen(PathFilename, "rb")) != NULL)
{
while (fread(&Data, 1, sizeof(unsigned long), File) != FALSE)
{
CheckSum ^= Data + ++Count;
Data = 0;
}
fclose(File);
}
return CheckSum;
}
Ich bin nicht viel von einem Programmierer (Ich bin ein Sysadmin), aber ich weiß, eine XOR-basierte Prüfsumme ziemlich roh sein wird. Wie hoch ist die Wahrscheinlichkeit, dass dieser Algorithmus dieselbe Prüfsumme für zwei Dateien derselben Größe mit unterschiedlichem Inhalt zurückgibt? (Ich erwarte keine genaue Antwort, "remote" oder "ziemlich wahrscheinlich" ist in Ordnung.)
Wie könnte es verbessert werden, ohne einen enormen Leistungseinbruch?
Zuletzt, was ist los mit der fread()
? Ich hatte einen kurzen Scan der Dokumentation, aber ich konnte es nicht herausfinden. Wird Data
der Reihe nach auf jedes Byte der Datei gesetzt? Edit: Okay, so liest es die Datei in unsigned long
(nehmen wir ein 32-Bit-Betriebssystem hier) Chunks. Was enthält jeder Chunk? Wenn der Inhalt der Datei abcd
ist, was ist der Wert von Data
im ersten Durchgang? Ist es (in Perl):
Checksum = (Checksum * a + Data * b) + c;
Wenn a, b und c sind große Primzahlen, diese sollten gute Ergebnisse zurück:
(ord('a') << 24) & (ord('b') << 16) & (ord('c') << 8) & ord('d')
fread liest ein Element an die Adresse von Data. Die Größe des Elements, das gelesen wird, ist die Größe eines vorzeichenlosen langen Bytes (8 Bytes, glaube ich). –
Die Größe eines unsigned long ist abhängig von der Prozessorarchitektur (32/64 bit), deshalb wird sizeof verwendet. – schnaader
Korrigieren Sie das Perl-Beispiel. –