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

Registriert seit: 2. Apr 2004
Ort: Bonn
2.477 Beiträge
 
Delphi 11 Alexandria
 
#1

TZipfile - ModifiedDateTime unter Linux und MAC richtig auslesen

  Alt 12. Dez 2021, 00:40
Um in einem bestehenden Zip-Archiv das Änderungsdatum einer Datei auszulesen mache ich es so:

DatumZeitStr := FormatDateTime ('dd.mm.yyyy hh:nn:ss', FileDateToDateTime (Zipfile.FileInfo[c].ModifiedDateTime)); Unter Windows wird mir das richtige Datum und Zeit zurückgegeben, unter macOS und Linux aber ein um ca. 7 Jahre zu altes Datum.

Könnt Ihr das bestätigen?

Ist das ein Bug, oder muss für diese Plattformen irgend etwas anders gemacht werden?

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

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

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 08:36
Vermutlich hat es damit zu tun:

"The precise format of a time stamp depends on the OS"

Das Zitat stammt aus dem Hilfetext zu System.SysUtils.FileDateToDateTime.
Jetzt dürfte dein Zeitstempel evtl. im Format eines OS in die ZIP Datei gespeichert
worden sein, was aber diese Funktion, wenn sie auf einer anderen Plattform ausgeführt
wird nicht weiß. Die wird einfach vom Format der vorliegenden Plattform ausgehen.

Man bräuchte da sowas wie eine Variante der man per Parameter noch mitgeben kann,
für welche Plattform die Konvertierung durchgeführt werden soll.

=> QP Feature Request und Nummer hier posten, damit wir abstimmen können.
Bis dahin: Quellcode der Funktion anschauen und sich selber eine solche Variante bauen.
Man muss dazu dann aber wissen, ob der Zeitstempel in der ZIP-Datei immer im selben
Format gespeichert ist oder wie man sonst das Format erkennt...

Grüße
TurboMagic
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

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

AW: TZipfile - ModifiedDateTime unter Linux und MAC falsch

  Alt 12. Dez 2021, 09:04
Im Mac die Zip ausgelesen und/oder auch dort erstellt?
Von Delphi erstellt, bzw. von Delphi gelesen, oder durch jemand Anderen?

Wenn im Mac erstellt und dort auch gelsen, dann macht die Genauigkeit keine Jahre aus, sondern eher maximal Sekunden/Minuten.

Aber in einer Zip wird das Datum und die Attribute nicht immer gleich gelspeichert, da die Hauseigenen Zip-Programme für diese Systeme auch die Eigenheiten der Dateisysteme einbeziehen.
In Windows ist es standardmäßig im DOS-Format, aber es gibt optional auch erweiterte Infos, wo das Datum mit höherer Genauigkeit nochmal drin steht.

Falls hier ein Mac-Programm die Zip erstellt hat und die Delphi-Komponente das immer versucht im Windows-Format zu lesen, dann passt das nicht mehr zusammen.
Andersrum sollte es aber stimmen, da die ordentlichen Mac-Programme wissen, wenn die eine Windows-Zip lesen und es dann entsprechend auslesen/umschalten.
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

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

Registriert seit: 2. Apr 2004
Ort: Bonn
2.477 Beiträge
 
Delphi 11 Alexandria
 
#4

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

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
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
my Delphi wish list : BugReports/FeatureRequests

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.477 Beiträge
 
Delphi 11 Alexandria
 
#6

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

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 Harry Stahl
Harry Stahl

Registriert seit: 2. Apr 2004
Ort: Bonn
2.477 Beiträge
 
Delphi 11 Alexandria
 
#8

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...
Miniaturansicht angehängter Grafiken
bild_1_12_dez_2021_1529.jpg   bild_1_12_dez_2021_1531.jpg  

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

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

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

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

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 15:25 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