Skip to content

Commit

Permalink
another pass on PasZip for Win64 compatibility
Browse files Browse the repository at this point in the history
- see #458
  • Loading branch information
Arnaud Bouchez committed Dec 9, 2024
1 parent f7372b8 commit 4fe8e8d
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 40 deletions.
90 changes: 51 additions & 39 deletions PasZip.pas
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@
- .zip reading from file, resource or direct memory - Windows only
- .zip write into a file (new .zip creation, not update) - Windows only
This unit is a cut-down stand-alone zip reader/writer, to be used e.g.
in installers or size-critical projects. Consider mormot.core.zip.pas from
mORMot 2 for more features, and better performance (thanks to libdeflate).
}

{$WARNINGS OFF}
Expand Down Expand Up @@ -334,6 +338,7 @@ implementation
{$ifndef FPC}
type
PtrUInt = {$ifdef CPU64}NativeUInt{$else}cardinal{$endif};
PtrInt = {$ifdef CPU64}NativeInt {$else}integer {$endif};
{$endif FPC}

// special tuned Move() routine, including data overlap bug correction
Expand Down Expand Up @@ -3810,9 +3815,13 @@ procedure CreateVoidZip(const aFileName: TFileName);
FileClose(H);
end;


{$ifdef MSWINDOWS}

function ValidHandle(Handle: THandle): boolean; {$ifdef HASINLINE}inline;{$endif}
begin
result := PtrInt(Handle) > 0;
end;

type
splitInt64 = packed record
loCard, hiCard: cardinal
Expand All @@ -3831,10 +3840,10 @@ function CompressFile(const srcFile, dstFile: TFileName; failIfGrow: boolean): b
try
sf := CreateFile(pointer(srcFile), GENERIC_READ, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if sf <> INVALID_HANDLE_VALUE then begin
if ValidHandle(sf) then begin
df := CreateFile(pointer(dstFile), GENERIC_READ or GENERIC_WRITE, 0, nil,
CREATE_ALWAYS, 0, 0);
if df <> INVALID_HANDLE_VALUE then begin
if ValidHandle(df) then begin
sm := CreateFileMapping(sf, nil, PAGE_READONLY, 0, 0, nil);
if sm <> 0 then begin
splitInt64(sl).loCard := GetFileSize(sf, @splitInt64(sl).hiCard);
Expand Down Expand Up @@ -3907,10 +3916,10 @@ function UncompressFile(const srcFile, dstFile: TFileName; lastWriteTime: int64;
sf := CreateFile(pointer(srcFile), GENERIC_READ, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL or
FILE_FLAG_SEQUENTIAL_SCAN, 0);
if sf <> INVALID_HANDLE_VALUE then begin
if ValidHandle(sf) then begin
df := CreateFile(pointer(dstFile), GENERIC_READ or GENERIC_WRITE, 0, nil,
CREATE_ALWAYS, attr or FILE_FLAG_SEQUENTIAL_SCAN, 0);
if df <> INVALID_HANDLE_VALUE then begin
if ValidHandle(df) then begin
sm := CreateFileMapping(sf, nil, PAGE_READONLY, 0, 0, nil);
if sm <> 0 then begin
sb := MapViewOfFile(sm, FILE_MAP_READ, 0, 0, 0);
Expand Down Expand Up @@ -3991,7 +4000,7 @@ function GetCompressedFileInfo(const comprFile: TFileName; var size: int64;
crc32 := 0;
file_ := CreateFile(pointer(comprFile), GENERIC_READ, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if file_ <> INVALID_HANDLE_VALUE then begin
if ValidHandle(file_) then begin
result := ReadFile(file_, size, 8, c1, nil) and (c1 = 8) and ReadFile(file_,
crc32, 4, c1, nil) and (c1 = 4);
CloseHandle(file_);
Expand All @@ -4007,7 +4016,7 @@ function GetUncompressedFileInfo(const uncomprFile: TFileName; var size: int64;
result := false;
file_ := CreateFile(pointer(uncomprFile), GENERIC_READ, FILE_SHARE_READ or
FILE_SHARE_WRITE, nil, OPEN_EXISTING, 0, 0);
if file_ <> INVALID_HANDLE_VALUE then begin
if ValidHandle(file_) then begin
splitInt64(size).loCard := GetFileSize(file_, @splitInt64(size).hiCard);
map := CreateFileMapping(file_, nil, PAGE_READONLY, 0, 0, nil);
if map <> 0 then begin
Expand Down Expand Up @@ -4069,22 +4078,19 @@ function Zip(const zip: TFileName; const files, zipAs: array of TFileName;
NoSubDirectories: boolean = false): boolean;
var
i1, i2, i3: integer;
dstFh: THandle;
srcFh: THandle;
dstFh, srcFh: THandle;
ft: TFileTime;
c1: dword;
c1, size: dword;
lfhr: TLocalFileHeader;
srcBuf: pointer;
dstBuf: pointer;
size: dword;
srcBuf, dstBuf: pointer;
zipRec: array of record
name: TZipName;
fhr: TFileHeader;
end;
lhr: TLastHeader;
begin
dstFh := CreateFile(pointer(zip), GENERIC_WRITE, 0, nil, CREATE_ALWAYS, 0, 0);
result := dstFh <> INVALID_HANDLE_VALUE;
result := ValidHandle(dstFh);
if result then begin
SetLength(zipRec, Length(files));
i2 := 0;
Expand All @@ -4103,7 +4109,7 @@ function Zip(const zip: TFileName; const files, zipAs: array of TFileName;
name := TZipName(zipAs[i1]);
srcFh := CreateFile(pointer(files[i1]), GENERIC_READ, FILE_SHARE_READ,
nil, OPEN_EXISTING, 0, 0);
if srcFh <> INVALID_HANDLE_VALUE then begin
if ValidHandle(srcFh) then begin
size := GetFileSize(srcFh, nil);
srcBuf := pointer(LocalAlloc(LPTR, size));
if srcBuf <> nil then begin
Expand Down Expand Up @@ -4230,6 +4236,7 @@ procedure InitCrc32Tab;
end;
{$endif}


{$ifdef MSWINDOWS}

{ TZipRead }
Expand Down Expand Up @@ -4314,7 +4321,7 @@ constructor TZipRead.Create(const aFileName: TFileName; ZipStartOffset, Size:
fShowMessageBoxOnError := ShowMessageBoxOnError;
file_ := CreateFile(pointer(aFileName), GENERIC_READ, FILE_SHARE_READ, nil,
OPEN_EXISTING, 0, 0);
if file_ = INVALID_HANDLE_VALUE then
if not ValidHandle(file_) then
exit; // file doesn't exist -> leave no Entry[] (Count=0)
if Size = 0 then
Size := GetFileSize(file_, nil);
Expand Down Expand Up @@ -4345,13 +4352,13 @@ constructor TZipRead.Create(const aFileName: TFileName; ZipStartOffset, Size:
procedure TZipRead.UnMap;
begin
Count := 0;
if file_ <> INVALID_HANDLE_VALUE then begin
if ValidHandle(file_) then begin
if map <> 0 then begin
UnmapViewOfFile(Buf);
CloseHandle(map);
end;
CloseHandle(file_);
file_ := INVALID_HANDLE_VALUE;
file_ := 0;
end;
Buf := nil;
end;
Expand Down Expand Up @@ -4453,7 +4460,7 @@ function TZipRead.CheckFile(aIndex: integer; DestPath: TFileName): boolean;
DestPath := DestPath + '\';
F := CreateFile(pointer(DestPath + Entry[aIndex].Name), GENERIC_READ,
FILE_SHARE_READ, nil, OPEN_EXISTING, 0, 0);
if F <> INVALID_HANDLE_VALUE then
if ValidHandle(F) then
with Entry[aIndex] do
try
Size := GetFileSize(F, nil);
Expand Down Expand Up @@ -4508,7 +4515,7 @@ function TZipRead.UnZipFile(aIndex: integer; DestPath: TFileName;
{$endif}
f := DestPath + n;
H := FileOpen(f, fmOpenRead);
if H <> INVALID_HANDLE_VALUE then begin
if ValidHandle(H) then begin
GetFileTime(H, nil, nil, @fFileTime);
FileTimeToLocalFileTime(fFileTime, fFileTime);
fFileSize := GetFileSize(H, nil);
Expand All @@ -4524,7 +4531,7 @@ function TZipRead.UnZipFile(aIndex: integer; DestPath: TFileName;
end;
ForceDirectories(ExtractFileDir(f));
H := FileCreate(f);
if H <> INVALID_HANDLE_VALUE then
if ValidHandle(H) then
try
if info^.zZipMethod = 0 then begin // stored method
if info^.zcrc32 <> not UpdateCrc32(dword(-1), data, info^.zfullSize) then
Expand Down Expand Up @@ -4612,26 +4619,31 @@ procedure TZipWrite.AddDeflated(const aFileName: TFileName; RemovePath: boolean;
FileTime: LongRec;
begin
H := FileOpen(aFileName, fmOpenRead or fmShareDenyNone);
if H = INVALID_HANDLE_VALUE then
exit;
if RemovePath then
ZipName := TZipName(ExtractFileName(aFileName))
else
ZipName := TZipName(aFileName);
GetFileTime(H, nil, nil, @Time);
FileTimeToLocalFileTime(Time, Time);
FileTimeToDosDateTime(Time, FileTime.Hi, FileTime.Lo);
Size := GetFileSize(H, nil);
getmem(buf, Size);
FileRead(H, buf^, Size);
AddDeflated(ZipName, buf, size, CompressLevel, integer(FileTime));
freemem(buf);
FileClose(H);
if ValidHandle(H) then
try
if RemovePath then
ZipName := TZipName(ExtractFileName(aFileName))
else
ZipName := TZipName(aFileName);
GetFileTime(H, nil, nil, @Time);
FileTimeToLocalFileTime(Time, Time);
FileTimeToDosDateTime(Time, FileTime.Hi, FileTime.Lo);
Size := GetFileSize(H, nil);
getmem(buf, Size);
try
FileRead(H, buf^, Size);
AddDeflated(ZipName, buf, size, CompressLevel, integer(FileTime));
finally
freemem(buf);
end;
finally
FileClose(H);
end;
end;

procedure TZipWrite.AddFromZip(const ZipEntry: TZipEntry);
begin
if (self = nil) or (Handle = 0) or (Handle = integer(INVALID_HANDLE_VALUE)) then
if (self = nil) or not ValidHandle(Handle) then
exit;
if Count >= length(Entry) then
SetLength(Entry, length(Entry) + 20);
Expand All @@ -4656,7 +4668,7 @@ procedure TZipWrite.AddFromZip(const ZipEntry: TZipEntry);
procedure TZipWrite.AddStored(const aZipName: TZipName; Buf: pointer; Size,
FileAge: integer);
begin
if (self = nil) or (Handle = 0) or (Handle = integer(INVALID_HANDLE_VALUE)) then
if (self = nil) or not ValidHandle(Handle) then
exit;
if Count >= length(Entry) then
SetLength(Entry, length(Entry) + 20);
Expand Down Expand Up @@ -4684,7 +4696,7 @@ procedure TZipWrite.AddStored(const aZipName: TZipName; Buf: pointer; Size,

procedure TZipWrite.Append(const Content: RawByteZip);
begin
if (self = nil) or (Handle = 0) or (Handle = integer(INVALID_HANDLE_VALUE)) or
if (self = nil) or not ValidHandle(Handle) or
(fAppendOffset <> 0) then
exit;
fAppendOffset := length(Content);
Expand Down
2 changes: 1 addition & 1 deletion SynopseCommit.inc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
'1.18.7657'
'1.18.7658'

0 comments on commit 4fe8e8d

Please sign in to comment.