AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein GUI-Design mit VCL / FireMonkey / Common Controls TZipfile - ModifiedDateTime unter Linux und MAC richtig auslesen

TZipfile - ModifiedDateTime unter Linux und MAC richtig auslesen

Ein Thema von Harry Stahl · begonnen am 12. Dez 2021 · letzter Beitrag vom 12. Dez 2021
Antwort Antwort
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.560 Beiträge
 
Delphi 12 Athens
 
#1

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 13:46
OK, wie vermutet mal wieder diese schönen Integer-Spielchen:

Unter 32-Bit Plattformen und Windows 64 Bit Plattform ist Longint ein 4 Byte Typ, unter Linux 64 bit und mac 64 aber ein 8 Byte Typ.

Da ich gerade nicht wüsste, wie ich in der System.Sysutils das anpassen könnte (wohl per IFDEF auch den Header der Funktion ändern), habe ich es als temporäre Lösung so gemacht, so funktioniert es dann auch unter allen Plattformen:
Delphi-Quellcode:
{$IFNDEF MSWindows}
function FileDateToDateTime(FileDate: UInt32): TDateTime;
begin
  Result :=
    EncodeDate(
      LongRec(FileDate).Hi shr 9 + 1980,
      LongRec(FileDate).Hi shr 5 and 15,
      LongRec(FileDate).Hi and 31) +
    EncodeTime(
      LongRec(FileDate).Lo shr 11,
      LongRec(FileDate).Lo shr 5 and 63,
      LongRec(FileDate).Lo and 31 shl 1, 0);
end;
{$ENDIF}
UInt32 ist immer ein 4 Byte-Type.

Daher sollte man diese Änderung nur da verwenden, wo man ModifiedDateTime (=UINT32) verwendet, denn FileDateToDateTime (searchrec.time =LongInt) funktioniert unter Linux 64 und MacOS 64.

Geändert von Harry Stahl (12. Dez 2021 um 14:01 Uhr)
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.048 Beiträge
 
Delphi 12 Athens
 
#2

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 14:20
Hallo,

schön, dass du die Ursache und für dich einen Workaround gefunden hast.
Da das so, wie du schreibst, nach einem Bug in TZipFile klingt solltest du den bitte aber
auch in QP erfassen, damit alle eine Chance auf einen Fix haben.
Die QP Nummer dann wie sicher schon bekannt hier posten...

Grüße

TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.645 Beiträge
 
Delphi 12 Athens
 
#3

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:20
Wieso soll das ein Fehler von TZipFile sein? Das Feld ModifiedDateTime steht als UInt32 im ZipHeader. Das Problem ist die Umwandlung über FileDateToDateTime und das hat gar nichts mit TZipFile zu tun.

Die Zip-Specs beschreiben diese vier Bytes folgendermaßen:
Zitat:
4.4.6 date and time fields: (2 bytes each)

The date and time are encoded in standard MS-DOS format.
If input came from standard input, the date and time are
those at which compression was started for this data.
If encrypting the central directory and general purpose bit
flag 13 is set indicating masking, the value stored in the
Local Header will be zero. MS-DOS time format is different
from more commonly used computer time formats such as
UTC. For example, MS-DOS uses year values relative to 1980
and 2 second precision.
Zufälligerweise (na ja, nicht ganz zufällig) macht FileDateToDateTime das unter Windows richtig, aber sonst eben nicht, da dort ein FileDate halt anders codiert ist. TZipFile schreibt aber das DOS-Format vor und das ist immerhin auch das, was Zipper unter Mac oder Linux da reinschreiben. Das Problem ist also nicht, dass TZipFile da was falsch macht, vielmehr muss der Programmierer eine geeignete, plattformunabhängige Umwandlungsmethode verwenden.

Der beschriebene Workaround ist zwar funktionsfähig, sollte aber m.E. anders heißen und ohne damit IFNDEF Windows auskommen:
Delphi-Quellcode:
function ZipFileDateToDateTime(FileDate: UInt32): TDateTime;
begin
  Result :=
    EncodeDate(
      LongRec(FileDate).Hi shr 9 + 1980,
      LongRec(FileDate).Hi shr 5 and 15,
      LongRec(FileDate).Hi and 31) +
    EncodeTime(
      LongRec(FileDate).Lo shr 11,
      LongRec(FileDate).Lo shr 5 and 63,
      LongRec(FileDate).Lo and 31 shl 1, 0);
end;
Ich glaube auch nicht, dass hier die unterschiedlichen Längen eines Longint die Ursache sind. Vielmehr wird bei Unix die Anzahl der Sekunden seit 1. Januar 1970, 00:00 Uhr UTC in dem Wert gespeichert, während bei der MS-DOS Version die einzelnen Datums- und Zeitanteile als Bits abgelegt sind (siehe DosDateTimeToFileTime). Daraus wird klar, dass die Umwandlung eines MS-DOS Zeitstempels mit Unix-Methoden nicht das erwartete Ergebnis bringen kann.
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.048 Beiträge
 
Delphi 12 Athens
 
#4

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:25
Hallo Uwe,

du hast da natürlich recht.
Die frage ist nur, ob so eine Umwandlungsroutine nicht irgendwo mitgeliefert werden sollte?
Dann würden evtl. nicht noch andere in das Fettnäpfchen, dass die vom OP benutzte Routine
zufällig unter Windows funktioniert tappen...

Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.560 Beiträge
 
Delphi 12 Athens
 
#5

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:29
Wieso soll das ein Fehler von TZipFile sein? Das Feld ModifiedDateTime steht als UInt32 im ZipHeader. Das Problem ist die Umwandlung über FileDateToDateTime und das hat gar nichts mit TZipFile zu tun.
Da stimme ich Dir zu, Uwe, das war auch letztlich meine abschließende Schlussfolgerung in Beitrag #8.

Am Anfang sah es aber erstmal so aus, daher ja meine Frage und der Post des verwendeten Beispiels...
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.560 Beiträge
 
Delphi 12 Athens
 
#6

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:37

Ich glaube auch nicht, dass hier die unterschiedlichen Längen eines Longint die Ursache sind. Vielmehr wird bei Unix die Anzahl der Sekunden seit 1. Januar 1970, 00:00 Uhr UTC in dem Wert gespeichert, während bei der MS-DOS Version die einzelnen Datums- und Zeitanteile als Bits abgelegt sind (siehe DosDateTimeToFileTime). Daraus wird klar, dass die Umwandlung eines MS-DOS Zeitstempels mit Unix-Methoden nicht das erwartete Ergebnis bringen kann.
Aber warum funktioniert FileTimeToDateTime dann unter Linux, wenn als Parameter ein LongInt verwendet wird (mein og. Beispiel mit Searchrec.time), aber nicht, wenn als Parameter ein UINT32 verwendet wird (wie hier in Modifieddate)?
  Mit Zitat antworten Zitat
Benutzerbild von Uwe Raabe
Uwe Raabe

Registriert seit: 20. Jan 2006
Ort: Lübbecke
11.645 Beiträge
 
Delphi 12 Athens
 
#7

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:46
Aber warum funktioniert FileTimeToDateTime dann unter Linux, wenn als Parameter ein LongInt verwendet wird (mein og. Beispiel mit Searchrec.time)
Weil das Searchrec unter Linux das Datum und die Uhrzeit natürlich schon korrekt codiert enthält. Das kommt ja vom Betriebssystem und nicht aus der ZIP-Datei.

.
Die frage ist nur, ob so eine Umwandlungsroutine nicht irgendwo mitgeliefert werden sollte?
Interessanterweise wird sie das in System.Zip bereits - leider nur private:
Delphi-Quellcode:

function WinFileDateToDateTime(FileDate: UInt32; out DateTime: TDateTime): Boolean;
Uwe Raabe
Certified Delphi Master Developer
Embarcadero MVP
Blog: The Art of Delphi Programming
  Mit Zitat antworten Zitat
TurboMagic

Registriert seit: 28. Feb 2016
Ort: Nordost Baden-Württemberg
3.048 Beiträge
 
Delphi 12 Athens
 
#8

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 15:53
Aber warum funktioniert FileTimeToDateTime dann unter Linux, wenn als Parameter ein LongInt verwendet wird (mein og. Beispiel mit Searchrec.time)
Weil das Searchrec unter Linux das Datum und die Uhrzeit natürlich schon korrekt codiert enthält. Das kommt ja vom Betriebssystem und nicht aus der ZIP-Datei.

.
Die frage ist nur, ob so eine Umwandlungsroutine nicht irgendwo mitgeliefert werden sollte?
Interessanterweise wird sie das in System.Zip bereits - leider nur private:
Delphi-Quellcode:

function WinFileDateToDateTime(FileDate: UInt32; out DateTime: TDateTime): Boolean;
Na dann ist ja klar, was man sich wünschen sollte
Lasst es public werden...
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.560 Beiträge
 
Delphi 12 Athens
 
#9

AW: TZipfile - ModifiedDateTime unter Linux und MAC richtig auslesen

  Alt 12. Dez 2021, 16:49
Aber warum funktioniert FileTimeToDateTime dann unter Linux, wenn als Parameter ein LongInt verwendet wird (mein og. Beispiel mit Searchrec.time)
Weil das Searchrec unter Linux das Datum und die Uhrzeit natürlich schon korrekt codiert enthält. Das kommt ja vom Betriebssystem und nicht aus der ZIP-Datei.
Wobei das "Zipfile.FileInfo[c].ModifiedDateTime" auf allen Plattformen denselben Wert enthält.

FileDateToDateTime, das als Parameter ein LongInt erwartet - macht daher unter Windows den richtigen Wert draus, da UINT32 auch unter Windows ein 4 Byte Wert ist, wie eben auch LongInt.

Unter Linux 64 Bit ist LongInt aber ein 8 Byte Wert, daher kann man letztlich nicht den UINT32-4-Byte Wert an eine Funktion übergeben, die unter Linux (anders als unter Windows) einen 8 Byte-Wert erwartet.

"searchrec.Time" ist unter Windows ein Integer (ist unter Windows übrigens als "platform deprecated" gekennzeichnet), unter posix als time_t platform und als LongInt deklariert. Da Integer und LongInt unter Windows beides mal 4 Byte haben, macht es nichts, dass der Paramenter von FileTimeToDateTime "LongInt" ist. Aber unter Linux-64 ist LongInt eben 8 Byte. Searchrec hat es mit der oben beschriebenen Weise dann für Linux angepasst, so dass die Werte für "time" stimmen. UINT32 bleibt aber immer 4 Byte.

Die Werte in Zipfile.FileInfo[c].ModifiedDateTime sind daher auch nicht falsch, sondern müssen eben je nach Plattform nur anders ausgewertet werden. Aber da muss man erst mal drauf kommen...

Ich habe daher auch mal den Titel des Threads geändert in "...richtig auslesen", damit man hier nicht einen falschen Eindruck bekommt.

Geändert von Harry Stahl (12. Dez 2021 um 16:56 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.560 Beiträge
 
Delphi 12 Athens
 
#10

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 14:35
Ich würde das mal also eher nicht als BUG bezeichnen, sondern man muss halt diese Umstände kennen und entsprechend auf den Plattformen anders reagieren. Ich werde aber noch mal überlegen, ob das nicht irgendwie eleganter geht, durch einen intelligenten Typecast oder so.

Jedenfalls bin ich froh, dass es nun funktioniert, hatte mich schon über die Erweiterung "TZipFile.delete" in Delphi 11 gefreut, welches somit das entfernen und aktualisieren von Dateien im Zip-Archiv nun sehr viel einfacher macht. Nur brauche ich dafür natürlich das richtige Datum, um zu vergleichen, ob etwas aktualisiert werden muss.

Gerade unter Linux war mir das wichtig, denn da vertreibe ich meine Programme immer als ZIP-Datei, das war bislang aber immer ein recht umständliches Management, da ich geänderte Programmdateien dann mit dem Linux-Zip-Programm ("Archivverwaltung") manuell in die speziell präparierte ZIP-Datei (mit Basis Verzeichnis "hastasoft") verschieben musste. Jetzt habe ich in mein Linux-Dateimanager-Programm File-IO einen Aktualisierungs-Dialog eingebaut (siehe Anlage), wo ich einfach die Zip-Datei auswähle und dann den Entwicklungsordner auf dem PC und mit einem Klick werden neue oder geänderte Dateien in das ZIP-Archiv übernommen...
Angehängte Grafiken
Dateityp: jpg Bild_1_12_Dez_2021_1529.jpg (156,0 KB, 10x aufgerufen)
Dateityp: jpg Bild_1_12_Dez_2021_1531.jpg (213,8 KB, 7x aufgerufen)

Geändert von Harry Stahl (12. Dez 2021 um 15:04 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:31 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz