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
Thema durchsuchen
Ansicht
Themen-Optionen

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
Seite 1 von 2  1 2      
Benutzerbild von Harry Stahl
Harry Stahl

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

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 11:58
Es ist egal, mit welchem Programm oder auf welchem OS-System die ZIP-Datei erstellt wurde, TZIP-File gibt immer das falsche Datum und Uhrzeit zurück.

Zip-Dateien, die mit TZipl-File erstellt werden, werden aber von anderen Programmen richtig anzeigt (aber TZipfile zeigt die selbst erstellten auch falsch an).

Also ist es ein Ausleseproblem. Da kommen einige Ansatzpunkte in Betracht:

ModifiedDateTime ist als UNIT32 im TZipheader definiert:

Delphi-Quellcode:
TZipHeader = packed record
    MadeByVersion: UInt16; // Start of Central Header
    RequiredVersion: UInt16; // Start of Local Header
    Flag: UInt16;
    CompressionMethod: UInt16;
    ModifiedDateTime: UInt32;
    CRC32: UInt32;
Daher war eine erste Annahme, ob es etwas mit Integer-Problemen zu tun haben könnte, da auf den unterschiedlichen Plattformen einige Integertypen unterschiedliche Anzahl Bytes haben.

In der Procedure TZipFile.REadCentralHeader wird es dann so ausgelesen:

VerifyRead(FStream, LHeader.ModifiedDateTime, Sizeof(UInt32));
Ich habe nun festgestellt, dass auf allen Plattformen

Zipfile.FileInfo[c].ModifiedDateTime
den gleichen Wert zurückliefert, nur FileDateToDateTime liefert aber offenbar unterschiedliche Ergebnisse zurück.

Für Linux / MAC ist FileDatetoDateTime wie wolgt definiert:
Delphi-Quellcode:
function FileDateToDateTime(FileDate: LongInt): TDateTime;
var
  TempFileDate: time_t;
  UT: tm;
begin
  TempFileDate := FileDate;
  localtime_r(TempFileDate, UT);
  Result := EncodeDate(UT.tm_year + 1900, UT.tm_mon + 1, UT.tm_mday) +
              EncodeTime(UT.tm_hour, UT.tm_min, UT.tm_sec, 0);
end;

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

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.752 Beiträge
 
Delphi 12 Athens
 
#2

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 13:34
https://pkware.cachefly.net/webdocs/...es/APPNOTE.TXT

4.3.7 Local file header
4.3.12 Central directory structure
4.4.6 date and time fields

B.2 Field Code, Description > 0008, Modification Date

Ja, Original steht das Datum in den beiden Header-Strukturen. (vor jedem Dateistream und als Dateiliste am Ende)

Normal steht im Local-Header und Central-Structure das Selbe,
außer die ZIP wurde sequentiell erstellt und beim Schreiben des LocalHeaders war dessen Inhalt noch nicht bekannt ... hier gilt dann nur das aus dem CentralHeader.

Alternativ kann das Datum auch in den ExtraFields stehen ... dann gilt nur dieser Wert, je nach Format des ExtraFields.

z.B.
4.5.5 -NTFS Extra Field (0x000a) > Mtime, 8 bytes, File last modification time
oder
4.5.7 -UNIX Extra Field (0x000d) > Mtime, 4 bytes, File last modification time
Ein Therapeut entspricht 1024 Gigapeut.

Geändert von himitsu (12. Dez 2021 um 13:37 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von Harry Stahl
Harry Stahl

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

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.104 Beiträge
 
Delphi 12 Athens
 
#4

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.824 Beiträge
 
Delphi 12 Athens
 
#5

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.104 Beiträge
 
Delphi 12 Athens
 
#6

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.561 Beiträge
 
Delphi 12 Athens
 
#7

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.561 Beiträge
 
Delphi 12 Athens
 
#8

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.824 Beiträge
 
Delphi 12 Athens
 
#9

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.104 Beiträge
 
Delphi 12 Athens
 
#10

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
Antwort Antwort
Seite 1 von 2  1 2      


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 03:53 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