From 34be62d93dd44c9a6eb36d1f52583b2ad0d82f27 Mon Sep 17 00:00:00 2001 From: Nil Admirari <50202386+nihil-admirari@users.noreply.github.com> Date: Sun, 11 Sep 2022 09:25:53 +0000 Subject: [PATCH] Initial commit --- .github/workflows/build.yaml | 38 ++++++++++++++++++ Invoke-CheckExitCode.ps1 | 16 ++++++++ LICENSE | 24 ++++++++++++ README.rst | 58 ++++++++++++++++++++++++++++ build.ps1 | 59 ++++++++++++++++++++++++++++ downloadAndPatch.ps1 | 73 +++++++++++++++++++++++++++++++++++ patches/no-compile-date.patch | 13 +++++++ patches/no-win98.patch | 13 +++++++ patches/rename-cr.patch | 44 +++++++++++++++++++++ patches/x64-makefile.patch | 50 ++++++++++++++++++++++++ 10 files changed, 388 insertions(+) create mode 100644 .github/workflows/build.yaml create mode 100644 Invoke-CheckExitCode.ps1 create mode 100644 LICENSE create mode 100644 README.rst create mode 100644 build.ps1 create mode 100644 downloadAndPatch.ps1 create mode 100644 patches/no-compile-date.patch create mode 100644 patches/no-win98.patch create mode 100644 patches/rename-cr.patch create mode 100644 patches/x64-makefile.patch diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml new file mode 100644 index 0000000..06f4161 --- /dev/null +++ b/.github/workflows/build.yaml @@ -0,0 +1,38 @@ +name: Build Info-ZIP +on: workflow_dispatch + +jobs: + build: + name: Build Info-ZIP for Windows + runs-on: windows-latest + steps: + - uses: actions/checkout@v3 + + - name: Download and patch sources + shell: pwsh + run: .\downloadAndPatch.ps1 + + - name: Build for x64 + shell: pwsh + run: | + .\build.ps1 x64 zip30 artefacts + + - name: Build for x86 + shell: pwsh + run: | + .\build.ps1 x86 zip30 artefacts + + - name: Build for arm64 + shell: pwsh + run: | + .\build.ps1 arm64 zip30 artefacts + + - name: Release + shell: pwsh + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + $date = Get-Date + hub.exe release create (Get-ChildItem artefacts\*.zip | % { '-a', $_.FullName }) ` + -m "Release $(Get-Date -Date $date -Format 'yyyy-MM-dd HH:mm')" ` + -t master (Get-Date -Date $date -Format 'yyyy-MM-dd-HH-mm') diff --git a/Invoke-CheckExitCode.ps1 b/Invoke-CheckExitCode.ps1 new file mode 100644 index 0000000..8c1c196 --- /dev/null +++ b/Invoke-CheckExitCode.ps1 @@ -0,0 +1,16 @@ +# [CmdletBinding()] and [Parameter()] are omitted to make sure +# "-i" is not interpreted as "-InformationAction" etc. +$eap = $ErrorActionPreference +try { + # Don't throw immediately on stderr output. + $ErrorActionPreference = [Management.Automation.ActionPreference]::Continue + + $command, $arguments = $args + & $command $arguments +} finally { + $ErrorActionPreference = $eap +} + +if ($LASTEXITCODE) { + throw [Exception]::new("$command exited with code $LASTEXITCODE") +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..fdddb29 --- /dev/null +++ b/LICENSE @@ -0,0 +1,24 @@ +This is free and unencumbered software released into the public domain. + +Anyone is free to copy, modify, publish, use, compile, sell, or +distribute this software, either in source code form or as a compiled +binary, for any purpose, commercial or non-commercial, and by any +means. + +In jurisdictions that recognize copyright laws, the author or authors +of this software dedicate any and all copyright interest in the +software to the public domain. We make this dedication for the benefit +of the public at large and to the detriment of our heirs and +successors. We intend this dedication to be an overt act of +relinquishment in perpetuity of all present and future rights to this +software under copyright law. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +OTHER DEALINGS IN THE SOFTWARE. + +For more information, please refer to diff --git a/README.rst b/README.rst new file mode 100644 index 0000000..945746e --- /dev/null +++ b/README.rst @@ -0,0 +1,58 @@ +Info-ZIP builds for Windows +=========================== + +Why? +---- + +There is no shortage of ZIP archivers out there, but none seem to be able to repack +Firefox's ``omni.ja``. Instructions__ are provided only for Info-ZIP's ``zip``: + +.. __: http://www.devdoc.net/web/developer.mozilla.org/en-US/docs/About_omni.jar.html + +:: + + zip -qr9XD omni.ja * + +``-XD`` is necessary for the creation of ``omni.ja``-like archives: + +-X Do not save extra file attributes. +-D Do not create entries in the zip archive for directories. + +Official builds at ftp://ftp.info-zip.org/pub/infozip/win32/ date back to 2008/2009 (x86/x64), +and do not include security patches that modern Linux builds have. + +Also there are no official ARM64 builds. (Please note, however, that ARM64 builds provided here +are completely untested.) + +Applied Patches +--------------- + +The following Fedora patches are downloaded along with Info-ZIP sources +(other Fedora patches are not relevant on Windows): + +- `zip-3.0-currdir.patch`__ + + .. __: https://src.fedoraproject.org/rpms/zip/blob/rawhide/f/zip-3.0-currdir.patch + +- `zip-3.0-format-security.patch`__ + + .. __: https://src.fedoraproject.org/rpms/zip/blob/rawhide/f/zip-3.0-format-security.patch + +- `zipnote.patch`__ + + .. __: https://src.fedoraproject.org/rpms/zip/blob/rawhide/f/zipnote.patch + +Additional Windows-specific patches can be found in the ``_ directory: + +- `no-compile-date.patch `_ is equivalent to Debian's + `10-remove-build-date.patch`__, but patches Windows rather than Unix sources. + + .. __: https://sources.debian.org/patches/zip/3.0-12/10-remove-build-date.patch/ + +- `no-win98.patch `_ and `rename-cr.patch `_ + fix compilation errors on Windows. + +- Info-ZIP's x64 makefile ``makefile.a64`` mentions neither large file support nor a resource file. + To fix this, `x64-makefile.patch `_ moves x64 assembly stuff + to ``makefile.w32``, turning it into a universal makefile that can be used + to build x86, x64 or ARM64 targets. diff --git a/build.ps1 b/build.ps1 new file mode 100644 index 0000000..c44589a --- /dev/null +++ b/build.ps1 @@ -0,0 +1,59 @@ +[CmdletBinding()] +param( + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [ValidateSet('x64', 'x86', 'arm64')] + [string] $Arch, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $SourceDir, + + [Parameter(Mandatory)] + [ValidateNotNullOrEmpty()] + [string] $ArtefactsDir +) +$ErrorActionPreference = [Management.Automation.ActionPreference]::Stop +Set-StrictMode -Version Latest + +$ArtefactsDir = [IO.Path]::GetFullPath($ArtefactsDir, $PWD) + +$clFlags = '/utf-8 /MP /GA /GL /Gw /guard:cf /guard:ehcont /Qspectre' +$ld = 'link.exe /NOLOGO /LTCG /GUARD:CF' + +if ($Arch -eq 'x64' -or $Arch -eq 'x86') { + $clFlags += ' /QIntel-jcc-erratum' + $ld += ' /CETCOMPAT' +} + +$asm = switch -exact ($Arch) { + 'x64' { 'X64ASM=1' } + 'x86' { '' } + default { 'NOASM=1' } +} + +$vs = & "$PSScriptRoot\Invoke-CheckExitCode" vswhere.exe -latest -property installationPath +Import-Module (Join-Path $vs 'Common7\Tools\Microsoft.VisualStudio.DevShell.dll') +Enter-VsDevShell -VsInstallPath $vs -SkipAutomaticLocation -HostArch amd64 ` + -Arch ($Arch -eq 'x64' ? 'amd64' : $Arch) ` + -DevCmdArguments '-vcvars_spectre_libs=spectre' + +Push-Location $SourceDir +try { + & "$PSScriptRoot\Invoke-CheckExitCode" nmake.exe /NOLOGO /F win32\makefile.w32 ` + LOC=$clFlags LD=$ld CRTLIB=/MD $asm + + $artefacts = "$([IO.Path]::GetFileNameWithoutExtension($PWD.Path))-$Arch" + New-Item -Type Directory "$artefacts" + Move-Item *.exe "$artefacts" + + if (-not (Test-Path $ArtefactsDir)) { + New-Item -Type Directory $ArtefactsDir + } + Compress-Archive "$artefacts" (Join-Path $ArtefactsDir "$artefacts.zip") + + Remove-Item -Recurse "$artefacts" + & "$PSScriptRoot\Invoke-CheckExitCode" nmake.exe /NOLOGO /F win32\makefile.w32 clean +} finally { + Pop-Location +} diff --git a/downloadAndPatch.ps1 b/downloadAndPatch.ps1 new file mode 100644 index 0000000..a758dd4 --- /dev/null +++ b/downloadAndPatch.ps1 @@ -0,0 +1,73 @@ +[CmdletBinding()] +$ErrorActionPreference = [Management.Automation.ActionPreference]::Stop +Set-StrictMode -Version Latest + +class RemoteFile { + [ValidateNotNullOrEmpty()] + [string] $Uri + + [ValidateNotNullOrEmpty()] + [string] $OutFile + + [ValidateNotNullOrEmpty()] + [string] $Sha512 + + RemoteFile([string] $uri, [string] $outFile, [string] $sha512) { + $this.Uri = $uri + $this.OutFile = $outFile + $this.Sha512 = $sha512 + } +} + +$patchDir = Join-Path $PSScriptRoot patches + +$uris = ( + [RemoteFile]::new( + 'https://sourceforge.net/projects/infozip/files/Zip%203.x%20%28latest%29/3.0/zip30.zip/download', + (Join-Path $PSScriptRoot zip30.zip), + '642ea6768d79adc1499251a3fb7bfc7ddc8d708699cbf9e0cfe849deda94165cb93e21dc2606bea1166ae5d8531e1e2cb056a7246bf2ab86ea7587bd4712d8d8' + ), + + [RemoteFile]::new( + 'https://src.fedoraproject.org/rpms/zip/raw/rawhide/f/zip-3.0-currdir.patch', + "$patchDir\zip-3.0-currdir.patch", + 'ffc5d2905cffb1f39ffb219511898dd3e17eb465f371a43b64f0ca9a293d518d64c753d9bc392db54b7ba7fd6ae0c13da3aeb38960465e99b45ceac3f0495b23' + ), + + [RemoteFile]::new( + 'https://src.fedoraproject.org/rpms/zip/raw/rawhide/f/zip-3.0-format-security.patch', + "$patchDir\zip-3.0-format-security.patch", + 'ce600d1a3565581fa094c7d7d6c280c06422cd7e96581e22daea3361b8f1e90b6956c268268d71259484d4cc900afc42a2ba17046cbc23c2bceacc2f14a3ea2d' + ), + + [RemoteFile]::new( + 'https://src.fedoraproject.org/rpms/zip/raw/rawhide/f/zipnote.patch', + "$patchDir\zipnote.patch", + 'f1608eb54cc60d42fe413bfb566a568de2d3fd1c7e494f1658444b2d6e12c9f818ef6f437392f5d49f5f1f30f023ad9eded69c3878bae998d28c53157a5d0583' + ) +) + +$uris | ForEach-Object -Parallel { + Invoke-WebRequest -UserAgent wget -Uri $_.Uri -OutFile $_.OutFile + Unblock-File $_.OutFile + if ((Get-FileHash -Algorithm SHA512 $_.OutFile).Hash -ine $_.Sha512) { + throw [Exception]::new("$($_.OutFile): incorrect SHA512") + } +} -AsJob | Receive-Job -Wait -Force + +Expand-Archive zip30.zip . + +Push-Location zip30 +try { + # Git applies patches from the root of the repository, + # i.e. from the folder that contains this script; + # thus it must be forced to stay inside zip30. + & "$PSScriptRoot\Invoke-CheckExitCode" git.exe init + + Get-ChildItem $patchDir\* | % { + & "$PSScriptRoot\Invoke-CheckExitCode" ` + git.exe apply --verbose --ignore-whitespace $_.FullName + } +} finally { + Pop-Location +} diff --git a/patches/no-compile-date.patch b/patches/no-compile-date.patch new file mode 100644 index 0000000..ca3c114 --- /dev/null +++ b/patches/no-compile-date.patch @@ -0,0 +1,13 @@ +diff --git a/win32/win32.c b/win32/win32.c +index 5798053..9d851cb 100644 +--- a/win32/win32.c ++++ b/win32/win32.c +@@ -1248,7 +1248,7 @@ void version_local() + #endif + + /* Define the compile date string */ +-#ifdef __DATE__ ++#if 0 + # define COMPILE_DATE " on " __DATE__ + #else + # define COMPILE_DATE "" diff --git a/patches/no-win98.patch b/patches/no-win98.patch new file mode 100644 index 0000000..ab8a3cb --- /dev/null +++ b/patches/no-win98.patch @@ -0,0 +1,13 @@ +diff --git a/win32/makefile.w32 b/win32/makefile.w32 +index 7afbf0e..0608146 100644 +--- a/win32/makefile.w32 ++++ b/win32/makefile.w32 +@@ -92,7 +92,7 @@ RC=rc + # by passing the -stub switch to the 32-bit linker to specify the 16-bit part. + + LD=link -nologo +-LDFLAGS=user32.lib advapi32.lib /OPT:NOWIN98 /INCREMENTAL:NO /PDB:$*.pdb $(EXTLIB) ++LDFLAGS=user32.lib advapi32.lib /INCREMENTAL:NO /PDB:$*.pdb $(EXTLIB) + SYMS=/DEBUG:full /DEBUGTYPE:CV + !IFDEF debug + LDFLAGS=$(LDFLAGS) $(SYMS) diff --git a/patches/rename-cr.patch b/patches/rename-cr.patch new file mode 100644 index 0000000..3efaf68 --- /dev/null +++ b/patches/rename-cr.patch @@ -0,0 +1,44 @@ +diff --git a/zip.h b/zip.h +index ba03160..438d976 100644 +--- a/zip.h ++++ b/zip.h +@@ -262,7 +262,7 @@ struct plist { + + /* ASCII definitions for line terminators in text files: */ + #define LF 10 /* '\n' on ASCII machines; must be 10 due to EBCDIC */ +-#define CR 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */ ++#define MAC_EOL 13 /* '\r' on ASCII machines; must be 13 due to EBCDIC */ + #define CTRLZ 26 /* DOS & OS/2 EOF marker (used in fileio.c, vms.c) */ + + /* return codes of password fetches (negative: user abort; positive: error) */ +diff --git a/zipup.c b/zipup.c +index 39f7d9c..0142f51 100644 +--- a/zipup.c ++++ b/zipup.c +@@ -1207,7 +1207,7 @@ local unsigned file_read(buf, size) + char c; + + if ((c = *b++) == '\n') { +- *buf++ = CR; *buf++ = LF; len++; ++ *buf++ = MAC_EOL; *buf++ = LF; len++; + } else { + *buf++ = (char)ascii[(uch)c]; + } +@@ -1217,7 +1217,7 @@ local unsigned file_read(buf, size) + #endif /* EBCDIC */ + { + do { +- if ((*buf++ = *b++) == '\n') *(buf-1) = CR, *buf++ = LF, len++; ++ if ((*buf++ = *b++) == '\n') *(buf-1) = MAC_EOL, *buf++ = LF, len++; + } while (--size != 0); + } + buf -= len; +@@ -1257,7 +1257,7 @@ local unsigned file_read(buf, size) + #endif /* EBCDIC */ + { + do { +- if (( *buf++ = *b++) == CR && *b == LF) buf--, len--; ++ if (( *buf++ = *b++) == MAC_EOL && *b == LF) buf--, len--; + } while (--size != 0); + } + if (len == 0) { diff --git a/patches/x64-makefile.patch b/patches/x64-makefile.patch new file mode 100644 index 0000000..f5f76f0 --- /dev/null +++ b/patches/x64-makefile.patch @@ -0,0 +1,50 @@ +diff --git a/win32/makefile.w32 b/win32/makefile.w32 +index 0608146..df670f7 100644 +--- a/win32/makefile.w32 ++++ b/win32/makefile.w32 +@@ -17,6 +17,15 @@ NODEBUG=1 + + # Uncomment the following macro to use the optimized assembler + # routines in Zip: ++!IFDEF X64ASM ++AS=ml64 -nologo ++ASFLAGS= /c /Zi /DINFOZIP ++ASMOBJS = gvmat64.obj ++CRCA_O = ++CFLG_ASM = -DNO_ASM_CRC -DASMV ++!ELSE ++AS=ml -nologo ++ASFLAGS=-c -coff -Cx + !IFDEF NOASM + ASMOBJS = + CRCA_O = +@@ -26,6 +35,7 @@ ASMOBJS = match32.obj + CRCA_O = crci386c.obj + CFLG_ASM = -DASM_CRC + !ENDIF ++!ENDIF + + !IFDEF USEBZ2 + LOC=$(LOC) -DBZIP2_SUPPORT +@@ -80,11 +90,6 @@ CC=cl -nologo + CFLAGS=-W3 $(cdebug) -DWIN32 $(CFLG_ASM) $(CRTLIB) $(LOC) + UTILFLAGS=$(CFLAGS) -DUTIL -Fo$@ + +-# Remove "-coff" from ASFLAGS if you do not have MASM 6.11. +- +-AS=ml -nologo +-ASFLAGS=-c -coff -Cx +- + RC=rc + + # If you build 16-bit executables with MS Visual C++ v1.0/1.5 and link them +@@ -204,6 +209,9 @@ crc_i386.obj: win32/crc_i386.asm + match32.obj: win32/match32.asm + $(AS) $(ASFLAGS) win32\match32.asm + ++gvmat64.obj: win32/gvmat64.asm ++ $(AS) $(ASFLAGS) win32\gvmat64.asm ++ + zip.res: win32/zip.rc revision.h + $(RC) /l 0x409 /fo$@ /i win32 /d WIN32 win32/zip.rc +