source upload
This commit is contained in:
26
contrib/bdiff/BDiffDecoder.pas
Normal file
26
contrib/bdiff/BDiffDecoder.pas
Normal file
@@ -0,0 +1,26 @@
|
||||
unit BDiffDecoder;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UPatcher;
|
||||
|
||||
procedure MakePatch(Data1, Data2, Data3: Pointer; const Size1, Size2: Integer;
|
||||
var Size3: Integer);
|
||||
|
||||
implementation
|
||||
|
||||
procedure MakePatch(Data1, Data2, Data3: Pointer; const Size1, Size2: Integer;
|
||||
var Size3: Integer);
|
||||
var
|
||||
Patcher: TPatcher;
|
||||
begin
|
||||
Patcher := TPatcher.Create;
|
||||
try
|
||||
Patcher.Apply(Data1, Data2, Data3, Size1, Size2, Size3);
|
||||
finally
|
||||
Patcher.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
33
contrib/bdiff/BDiffEncoder.pas
Normal file
33
contrib/bdiff/BDiffEncoder.pas
Normal file
@@ -0,0 +1,33 @@
|
||||
unit BDiffEncoder;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UDiffer, ULogger, UBDiffTypes;
|
||||
|
||||
procedure MakeDiff(Data1, Data2, Data3: Pointer; const Size1, Size2: Integer;
|
||||
var Size3: Integer);
|
||||
|
||||
implementation
|
||||
|
||||
procedure MakeDiff(Data1, Data2, Data3: Pointer; const Size1, Size2: Integer;
|
||||
var Size3: Integer);
|
||||
var
|
||||
Differ: TDiffer;
|
||||
Logger: TLogger;
|
||||
begin
|
||||
Logger := TLoggerFactory.Instance(False);
|
||||
try
|
||||
Differ := TDiffer.Create;
|
||||
try
|
||||
Differ.Format := TFormat.FMT_BINARY;
|
||||
Differ.MakeDiff(Data1, Data2, Data3, Size1, Size2, Size3, Logger);
|
||||
finally
|
||||
Differ.Free;
|
||||
end;
|
||||
finally
|
||||
Logger.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
225
contrib/bdiff/Build.txt
Normal file
225
contrib/bdiff/Build.txt
Normal file
@@ -0,0 +1,225 @@
|
||||
================================================================================
|
||||
|
||||
BDiff / BPatch Build Instructions
|
||||
|
||||
================================================================================
|
||||
|
||||
|
||||
Introduction
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
BDiff / BPatch is written in Object Pascal and is targeted at Delphi XE. The
|
||||
Delphi IDE can be used to modify the source and to perform test builds. Final
|
||||
builds should be built using the provided makefile, but you can get away with
|
||||
using the IDE if you don't change any resources.
|
||||
|
||||
These instructions only apply to building the current release of BDiff / BPatch.
|
||||
Earlier releases back to v0.2.6a will have their own versions of this file.
|
||||
|
||||
|
||||
Requirements
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
You need the following tools to perform a full build and release of BDiff /
|
||||
BPatch:
|
||||
|
||||
Delphi Command Line compiler (DCC32)
|
||||
------------------------------------
|
||||
|
||||
The preferred version is Delphi XE. If you have this compiler please use it. The
|
||||
DELPHIROOT environment variable must be set to the install path of the version
|
||||
Delphi you are using. DCC32.exe must be present in the Bin sub-directory of the
|
||||
path specified by DELPHIROOT. If DELPHIROOT is not set then Make will fail.
|
||||
|
||||
Alternatives:
|
||||
|
||||
+ Unicode versions of Delphi other than XE may work, but haven't been tested.
|
||||
Non Unicode compilers will fail to compile the code.
|
||||
|
||||
+ Only versions of Delphi that ship with the DCC32 command line compiler can
|
||||
be used with the make files.
|
||||
|
||||
+ As noted above you can compile Pascal code from the Delphi IDE instead of
|
||||
running DCC32.
|
||||
|
||||
BRCC32 resource compiler (BRCC32)
|
||||
---------------------------------
|
||||
|
||||
BRCC32 is distributed with Delphi. It is needed to compile resource files. The
|
||||
Makefile expects to find BRCC32 in the same directory as DCC32.
|
||||
|
||||
Borland MAKE
|
||||
------------
|
||||
|
||||
This is the make tool that ships with Delphi. You can use any version that
|
||||
works. I've tested only the version that ships with Delphi XE. The makefile
|
||||
calls Make recursively: it uses the same command line that you used to call it,
|
||||
so there are no requirements as to the location of Make.
|
||||
|
||||
DelphiDabbler Version Information Editor (VIEd)
|
||||
-----------------------------------------------
|
||||
|
||||
This program is required to convert the .vi files that specify version
|
||||
information into an intermediate .rc file that is compiled by BRCC32. VIEd is
|
||||
expected to be on the system path unless the VIEDROOT environment variable is
|
||||
set to indicate VIEd's installation directory. You can get VIEd here:
|
||||
http://delphidabbler.com/software/vied
|
||||
|
||||
Zip.exe
|
||||
-------
|
||||
|
||||
This program is required to create the release exe file. Again it is assumed to
|
||||
be on the path unless the ZIPROOT environment variable is set to its install
|
||||
directory. You can get a Windows version at:
|
||||
http://stahlforce.com/dev/index.php?tool=zipunzip
|
||||
|
||||
|
||||
Dependencies
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
The source depends only on the Delphi VCL, so provided you have Delphi
|
||||
installed, the source should compile without building any other libraries.
|
||||
|
||||
|
||||
Preparations
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
Get the source code
|
||||
-------------------
|
||||
|
||||
The source code of BDiff / BPatch is maintained in the delphidabbler/bdiff Git
|
||||
repository on GitHub at https://github.com/delphidabbler/bdiff
|
||||
|
||||
Each release from v0.2.5 onwards is available from GitHub. You can download an
|
||||
archive containing the required release. Note that releases prior to v0.2.7 were
|
||||
originally maintained in a Subversion repository and therefore their
|
||||
documentation will refer to Subversion rather than Git.
|
||||
|
||||
Once the source is cloned or forked you should end up with a folder structure
|
||||
like this:
|
||||
|
||||
+--+ { root: .gitignore, this file, and some documentation}
|
||||
|
|
||||
+-- Docs { documentation files }
|
||||
|
|
||||
+-- Src { project group and master make files }
|
||||
| |
|
||||
| +-- BDiff { source and makefile for BDiff }
|
||||
| |
|
||||
| +-- BPatch { source and makefile for BPatch }
|
||||
| |
|
||||
| +-- Common { code common to both programs }
|
||||
|
|
||||
+-- Test { test scripts }
|
||||
|
||||
If, by chance you also have a Build directory and sub-directories don't worry.
|
||||
Git users will also see the usual .git hidden directory.
|
||||
|
||||
Configure the source tree
|
||||
-------------------------
|
||||
|
||||
Before you can get hacking, you need to prepare the code. Open a command
|
||||
console, navigate into the Src sub-folder and do:
|
||||
|
||||
> Make config
|
||||
|
||||
You may need to replace "Make" above with the full path to Make if it isn't on
|
||||
the path, or if the Make that runs isn't the Borland / CodeGear version.
|
||||
|
||||
Once "Make config" has completed your folder structure should have changed to:
|
||||
|
||||
+--+
|
||||
|
|
||||
+-- Build { contains files created in build process }
|
||||
| |
|
||||
| +-- Bin { parent of binary folders }
|
||||
| | |
|
||||
| | +-- BDiff { receives binary files for BDiff (.dcu and .res) }
|
||||
| | |
|
||||
| | +-- BPatch { receives binary files for BPatch (.dcu and .res) }
|
||||
| |
|
||||
| +-- Exe { receives executable files }
|
||||
| |
|
||||
| +-- Release { receives release zip file }
|
||||
|
|
||||
+-- Docs
|
||||
|
|
||||
+-- Src
|
||||
| |
|
||||
| +-- BDiff
|
||||
| |
|
||||
| +-- BPatch
|
||||
|
|
||||
+-- Test
|
||||
|
||||
Git has been configured to ignore the Build folder and its contents. In addition
|
||||
Make will have created .cfg files from templates. These files are needed for
|
||||
DCC32 to run correctly. The .cfg files will be ignored by Git.
|
||||
|
||||
If you are intending to use the Delphi IDE to compile code, you should also do:
|
||||
|
||||
> Make res
|
||||
|
||||
This compiles the resource files that the IDE needs to link into compiled
|
||||
executables.
|
||||
|
||||
Modify the source
|
||||
-----------------
|
||||
|
||||
If you plan to modify the source, you can do it now.
|
||||
|
||||
If you are using the Delphi IDE you should load the BDiff.groupproj project
|
||||
group file from the Src folder into the IDE - this contains both the BDiff and
|
||||
BPatch targets.
|
||||
|
||||
Compile
|
||||
-------
|
||||
|
||||
Compile the code by doing
|
||||
|
||||
> Make exe
|
||||
|
||||
This builds the resources then builds the whole of the Pascal source using the
|
||||
DCC32 command line compiler.
|
||||
|
||||
Even if you have built the code in the IDE you advised to run "Make exe".
|
||||
|
||||
At any time you can rebuild the resources using "Make res" or rebuild the pascal
|
||||
code without also building resources by using "Make pascal".
|
||||
|
||||
Testing
|
||||
-------
|
||||
|
||||
Some simple tests can be run to check that BDiff and BPatch are working
|
||||
correctly. For details see ReadMe.txt in the Test folder.
|
||||
|
||||
Prepare the executable release file
|
||||
-----------------------------------
|
||||
|
||||
If you want to create a zip file containing the executable programs and required
|
||||
documentation do:
|
||||
|
||||
> Make release
|
||||
|
||||
This deletes any temporary files then creates the required zip file. You can
|
||||
change the default name of the zip file by defining the RELEASEFILENAME
|
||||
environment variable with the required name (excluding extension). For example,
|
||||
to generate a release file named my-file.zip define RELEASEFILENAME as 'my-file'
|
||||
or do:
|
||||
|
||||
> Make -DRELEASEFILENAME=myfile release
|
||||
|
||||
If you issue a Make with no target it will re-run config, build the executable
|
||||
code and create the release.
|
||||
|
||||
Tidy up
|
||||
-------
|
||||
|
||||
At any time you can tidy up temporary files by doing:
|
||||
|
||||
> Make clean
|
||||
|
||||
If you also want to remove the .cfg files generated from .cfg.tplt files along
|
||||
with the entire Build directory you can do:
|
||||
|
||||
> Make deepclean
|
84
contrib/bdiff/CHANGELOG.txt
Normal file
84
contrib/bdiff/CHANGELOG.txt
Normal file
@@ -0,0 +1,84 @@
|
||||
v0.2.8 - released 19 Sep 2016
|
||||
BDiff.exe v0.2.8 (build 9)
|
||||
BPatch.exe v0.2.8 (build 9)
|
||||
+ Converted to support Unicode file names and use of Unicode strings internally.
|
||||
+ Switched to Delphi XE compiler from Delphi 7.
|
||||
+ Added new test to test script.
|
||||
+ Significant overhaul and updates to documentation.
|
||||
|
||||
v0.2.7 - released 19 Jul 2014
|
||||
BDiff.exe v0.2.7 (build 8)
|
||||
BPatch.exe v0.2.7 (build 8)
|
||||
+ Bug fixes in BDiff:
|
||||
- "New" and "old" file names for a diff cannot now be the same.
|
||||
- Patch file name specified in --output or -o switches must now have a different name from other file names specified on command line.
|
||||
+ Major refactoring:
|
||||
- Big change from procedural to modularised, mainly OOP code split into several units.
|
||||
- Pascalified code in terms of variable names, camel casing etc.
|
||||
- Revised logic of some methods.
|
||||
- Reduced usage of some pointers, including replacing use characters pointers with Pascal strings.
|
||||
+ Revised and reformatted documentation: license and read-me files converted to markdown format.
|
||||
+ Minor changes to the license.
|
||||
|
||||
v0.2.6a - released 06 Aug 2009
|
||||
BDiff.exe v0.2.6 (build 7)
|
||||
BPatch.exe v0.2.6 (build 7)
|
||||
+ Removed source code from distribution.
|
||||
+ Documentation updated re changes.
|
||||
+ No changes to executable code other than to update build numbers.
|
||||
|
||||
v0.2.6 - released 02 Aug 2009
|
||||
BDiff.exe v0.2.6 (build 6)
|
||||
BPatch.exe v0.2.6 (build 6)
|
||||
+ Changed to use sytem temporary folder for temporary files instead of current directory.
|
||||
+ Typo in BDiff help screen fixed.
|
||||
+ Some refactoring:
|
||||
- Code rationalised to have only one exit point in each application rather than multiple halt points.
|
||||
- Fatal errors now handled by exceptions rather than by calling Halt().
|
||||
- Some duplicated code pulled into units shared between BDiff and BPatch.
|
||||
- Ensured code that depends on single byte characters uses fixed size types instead of Char, which changes size in later compilers.
|
||||
+ Replaced build scripts with make files.
|
||||
+ Tests rewritten and extended:
|
||||
- Three different tests are now provided in place of one: all three patch formats are now tested.
|
||||
- Option added to display program version information.
|
||||
- Option added to clear temporary files generated by running the tests.
|
||||
- Location of BDiff and BPatch programs being tested can now be specified.
|
||||
+ Documentation overhauled.
|
||||
|
||||
v0.2.5 - released 14 Aug 2008
|
||||
BDiff.exe v0.2.5 (build 5) [v0.2.4 skipped]
|
||||
BPatch.exe v0.2.5 (build 5)
|
||||
+ Renamed BPtch back to BPatch.
|
||||
+ Added manifests to resources of both BPatch and BDiff to inform Windows Vista to run them as invoked. This prevents Vista from elevating BPatch because of the word "patch" in its name.
|
||||
|
||||
v0.2.4 - released 07 Apr 2008
|
||||
BDiff.exe v0.2.3 (build 4)
|
||||
BPtch.exe v0.2.4 (build 4)
|
||||
+ Renamed BPatch as BPtch to prevent Windows Vista from flagging the program as requiring elevation.
|
||||
+ Also altered BPtch's version information to remove the word "patch" for same reason!
|
||||
+ BDiff was not changed except for incrementing build number.
|
||||
|
||||
v0.2.3 - released 18 Sep 2007
|
||||
BDiff.exe v0.2.3 (build 3)
|
||||
BPatch.exe v0.2.3 (build 3) [v0.2.2 skipped]
|
||||
+ Fixed bug where BPatch could not overwrite existing files.
|
||||
+ Fixed small bug in -h and -v switches in both programs.
|
||||
+ Fixed memory leaks in BDiff.
|
||||
+ Switched to Delphi 7 compiler from Delphi 4.
|
||||
+ Prevented compiler warnings in both programs.
|
||||
+ Added batch files to build projects.
|
||||
+ Updated help screens.
|
||||
+ Made some minor refactorings.
|
||||
+ Removed conditional compilation for non-Windows targets.
|
||||
+ Added test batch file a sample files.
|
||||
+ Changed to new binary and source license.
|
||||
|
||||
v0.2.2(pas) - released 21 Dec 2003
|
||||
BDiff.exe v0.2.2 (build 2)
|
||||
BPatch.exe v0.2.1 (build 2)
|
||||
+ Fixed bug in BDiff by translating revised C code provided by Stefan Reuther. BDiff.exe is affected by the change while BPatch.exe remains unchanged.
|
||||
|
||||
v0.2.1(pas) - released 29 Nov 2003
|
||||
BDiff.exe v0.2.1 (build 1)
|
||||
BPatch.exe v0.2.1 (build 1)
|
||||
+ First Pascal version. This is a direct translation of v0.2 of Stefan Reuther's C code published in 1999.
|
124
contrib/bdiff/Docs/BDiff.txt
Normal file
124
contrib/bdiff/Docs/BDiff.txt
Normal file
@@ -0,0 +1,124 @@
|
||||
NAME
|
||||
|
||||
bdiff - difference of binary files
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
bdiff [options] old-file new-file [>patch-file]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
bdiff computes differences between two binary files. Output can be either a
|
||||
somewhat human-readable protocol, or a binary file readable by bpatch. Output is
|
||||
sent to standard output unless the --output option is used to specify an output
|
||||
file.
|
||||
|
||||
bdiff handles insertion and deletion of data as well as changed bytes.
|
||||
|
||||
|
||||
OPTIONS
|
||||
|
||||
-q - Use QUOTED format (default);
|
||||
|
||||
-f - Use FILTERED format;
|
||||
|
||||
-b - Use BINARY format;
|
||||
|
||||
--format=FMT - Select format by name: (binary, filtered, quoted)
|
||||
|
||||
-m N, - Two chunks of data are recognized as being identical if
|
||||
--min-equal=N they are at least N bytes long, the default is 24.
|
||||
|
||||
-o FILENAME, - Write diff to specified file instead of standard output.
|
||||
--output=FILENAME Specifying --output=- does nothing. Use as an alternative
|
||||
to shell redirection.
|
||||
|
||||
-V, - Print status messages while processing input;
|
||||
--verbose
|
||||
|
||||
-h, - Show help screen and exit;
|
||||
--help
|
||||
|
||||
-v, - Show version number and exit.
|
||||
--version
|
||||
|
||||
|
||||
ALGORITHM
|
||||
|
||||
bdiff tries to locate maximum-length substrings of the new file in the old data.
|
||||
Substrings shorter than N (argument to the -m option) are not considered
|
||||
acceptable matches. Everything covered by such a substring is transmitted as a
|
||||
position, length pair, everything else as literal data.
|
||||
|
||||
bdiff uses the block-sort technique to allow O(lgN) searches in the file, giving
|
||||
an estimated O(NlgN) algorithm on average.
|
||||
|
||||
The program requires about five times as much memory as the old file, plus
|
||||
storage for the new file. This should be real memory, bdiff accesses all of it
|
||||
very often.
|
||||
|
||||
|
||||
OUTPUT FORMATS
|
||||
|
||||
The quoted format (default) is similar to diff output in unified format: '+'
|
||||
means added data, and a space means data kept from the old file. Lines prefixed
|
||||
with '@' inform you about the position of the next 'space' line in the source
|
||||
file (byte offset).
|
||||
|
||||
Unlike in diff, there's no implicit line feed after each line of output.
|
||||
Non-printable characters (see isprint(3)[1]) and the backslash character are
|
||||
represented by a \ followed by the octal three-digit character code.
|
||||
|
||||
The filtered format is like the quoted format, but non-printable characters are
|
||||
replaced by dots (.).
|
||||
|
||||
The binary format is machine-readable, and omits details for common blocks. All
|
||||
words are in little-endian format (low byte first). The format is:
|
||||
|
||||
8 bytes - Signature "bdiff02\x1A", where 02 is kind-of a version number. An
|
||||
earlier version (with an O(n^3) algorithm) used the number 01. \x1A
|
||||
is ASCII 26 (Control-Z, an MS-DOS end-of-file marker).
|
||||
4 bytes - Length of old file in bytes.
|
||||
4 bytes - Length of new file in bytes.
|
||||
n bytes - The patch itself, a sequence of the following records:
|
||||
|
||||
literally added data:
|
||||
1 byte - ASCII 43 ('+');
|
||||
4 bytes - number of bytes;
|
||||
n bytes - data.
|
||||
|
||||
common block:
|
||||
1 byte - ASCII 64 ('@');
|
||||
4 bytes - file position in old file;
|
||||
4 bytes - number of bytes;
|
||||
4 bytes - checksum.
|
||||
|
||||
The checksum is computed using the following algorithm:
|
||||
long checksum(char* data, size_t len)
|
||||
{
|
||||
long l = 0;
|
||||
while(len--) {
|
||||
l = ((l >> 30) & 3) | (l << 2);
|
||||
l ^= *data++;
|
||||
}
|
||||
return l;
|
||||
}
|
||||
(rotate current checksum left by two and xor in the current byte)
|
||||
|
||||
|
||||
ADMINISTRATIVIA
|
||||
|
||||
This manual page is for version 0.2.6 or later of bdiff.
|
||||
|
||||
See the file LICENSE.md for details of licensing and copyright.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN
|
||||
NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
|
||||
FOOTNOTES
|
||||
|
||||
[1] http://www.openbsd.org/cgi-bin/man.cgi?query=isprint&sektion=3
|
49
contrib/bdiff/Docs/BPatch.txt
Normal file
49
contrib/bdiff/Docs/BPatch.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
NAME
|
||||
|
||||
bpatch - apply binary batch
|
||||
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
bpatch [options] old-file [ new-file ] [<patch-file]
|
||||
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
bpatch applies a binary patch generated by bdiff. Patches are read from standard
|
||||
input unless the --input option is used to specify an input file.
|
||||
|
||||
old-file is the same file as used as the first argument to bdiff. bpatch will
|
||||
create a copy of the file given as second argument to bdiff in new-file by using
|
||||
the information from old-file and patch-file.
|
||||
|
||||
If new-file is omitted, the old file is replaced with the new file.
|
||||
|
||||
bpatch will detect if the patch does not match old-file, or if the patch has
|
||||
been garbled. Remember to transmit binary patches as binary files!
|
||||
|
||||
In case of an error, new-file will not be touched.
|
||||
|
||||
|
||||
OPTIONS
|
||||
|
||||
-i PATCH-FILE, - Read patch from specified file instead of standard input.
|
||||
--input=PATCH-FILE Specifying --input=- does nothing. Use as an alternative
|
||||
to shell redirection.
|
||||
|
||||
-h, - Show help screen.
|
||||
--help
|
||||
|
||||
-v, - Show version number.
|
||||
--version
|
||||
|
||||
|
||||
ADMINISTRATIVIA
|
||||
|
||||
This manual page is for version 0.2.6 or later of bpatch.
|
||||
|
||||
See the file LICENSE.md for details of licensing and copyright.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN
|
||||
NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF
|
||||
THIS SOFTWARE.
|
94
contrib/bdiff/Docs/EmailsReLicence.txt
Normal file
94
contrib/bdiff/Docs/EmailsReLicence.txt
Normal file
@@ -0,0 +1,94 @@
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
This file contains copies of emails exchanged between Peter Johnson and Stefan
|
||||
Reuther that relate to licensing of Peter's Pascal translation of Stefan's
|
||||
original source code.
|
||||
|
||||
**NOTE:** Email addresses have been partially obscured.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
From: xxxxx@delphidabbler.com
|
||||
To: Streu@xxxxx.de
|
||||
Date: 04/12/2003 01:59
|
||||
|
||||
Hi Stefan
|
||||
|
||||
I found v0.2 of your BDiff/BPatch files on the net and the programs meet my
|
||||
needs quite well. However I would like to modify the code to strip out the
|
||||
core functions and place that in a DLL to be accessed by one of my Windows
|
||||
programs. Since I program in mainly in Object Pascal, I've created a literal
|
||||
translation of your code in Pascal (to run on Windows platforms) as a first
|
||||
step.
|
||||
|
||||
I've published the Pascal version on my website (see
|
||||
http://www.delphidabbler.com/software.php?id=bdiff) and have tried to comply
|
||||
with the terms published with v0.2 of your code. The new version is made
|
||||
available under the same terms as your original code and the C code is
|
||||
included in the download. You've been given full credit for the additional
|
||||
code and your copyright is acknowledged.
|
||||
|
||||
I hope you are happy for your code to be used in this way and for me to
|
||||
develop it to meet my needs and to publish the result. Please let me know if
|
||||
you have any problems with this.
|
||||
|
||||
Thanks for making your code available. Please do get in touch if you have
|
||||
any comments.
|
||||
|
||||
Regards
|
||||
Peter Johnson
|
||||
xxxxx@openlink.org
|
||||
http://www.delphidabbler.com/
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
||||
From: Streu@xxxxx.de
|
||||
To: xxxxx@delphidabbler.com
|
||||
Date: 04/12/2003 12:06
|
||||
|
||||
Hello,
|
||||
|
||||
On Thu, Dec 04, 2003 at 01:59:05AM -0000, Peter David Johnson wrote:
|
||||
> > I found v0.2 of your BDiff/BPatch files on the net and the programs meet my
|
||||
> > needs quite well. However I would like to modify the code to strip out the
|
||||
> > core functions and place that in a DLL to be accessed by one of my Windows
|
||||
> > programs.
|
||||
|
||||
Go ahead and do what you want with it.
|
||||
|
||||
> > I've published the Pascal version on my website (see
|
||||
> > http://www.delphidabbler.com/software.php?id=bdiff) and have tried to comply
|
||||
> > with the terms published with v0.2 of your code. The new version is made
|
||||
> > available under the same terms as your original code and the C code is
|
||||
> > included in the download. You've been given full credit for the additional
|
||||
> > code and your copyright is acknowledged.
|
||||
|
||||
Nice. (Don't worry about those "copyright terms" too much.
|
||||
Everything's fine with me unless you claim 'I invented it and
|
||||
now I patent it').
|
||||
|
||||
I mainly wrote that program to give out binary patches of my
|
||||
other programs; I also have a nice Turbo Pascal version of a
|
||||
'patch' utility; if you want it, no problem, but I doubt it
|
||||
helps you too much under Windows. For fairness I should say the
|
||||
'bdiff' is not the best binary-diff program there is (at least I
|
||||
already had one which found smaller diffs, but I can't find it
|
||||
right now), but it is simple and easy to handle.
|
||||
|
||||
> > I hope you are happy for your code to be used in this way and for me to
|
||||
> > develop it to meet my needs and to publish the result. Please let me know if
|
||||
> > you have any problems with this.
|
||||
|
||||
To be honest, I had almost forgotten that that file was on my
|
||||
web site :)
|
||||
|
||||
Oh well, this reminds me that the version on the website has a
|
||||
bug. And since I forgot that it's there, I forgot to update it.
|
||||
I attach the fixed version of 'blksort.c'. The bug causes it to
|
||||
crash on certain data. The problem is in 'find_string'.
|
||||
|
||||
|
||||
Stefan
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
|
49
contrib/bdiff/Docs/OldLicenses.txt
Normal file
49
contrib/bdiff/Docs/OldLicenses.txt
Normal file
@@ -0,0 +1,49 @@
|
||||
================================================================================
|
||||
License for original BDiff / BPatch releases 0.1 and 0.2 (C source code)
|
||||
================================================================================
|
||||
|
||||
(c) copyright 1999 by Stefan Reuther <Streu@gmx.de>. Copying this program is
|
||||
allowed, as long as you include source code and document changes you made in a
|
||||
user-visible way so people know they're using your version, not mine.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but without
|
||||
warranties of any kind, be they explicit or implicit.
|
||||
|
||||
|
||||
================================================================================
|
||||
License used for BDiff / BPatch v0.2.1 and v0.2.2
|
||||
================================================================================
|
||||
|
||||
The copyright statement and terms of use and distribution granted by the
|
||||
original author are:
|
||||
|
||||
<20> copyright 1999 by Stefan Reuther*. Copying this program is allowed, as long
|
||||
as you include source code and document changes you made in a user-visible way
|
||||
so people know they're using your version, not mine.
|
||||
|
||||
This program is distributed in the hope that it will be useful, but without
|
||||
warranties of any kind, be they explicit or implicit.
|
||||
|
||||
Additional copyright and terms of using the Pascal translation are as follows:
|
||||
|
||||
The Pascal translation is <20> copyright 2003 by Peter Johnson. Copying the
|
||||
Pascal translation and any modifications of the original code is allowed
|
||||
providing changes are made clear.
|
||||
|
||||
No warranties of any kind are provided.
|
||||
|
||||
Many thanks to Stefan for creating this software.
|
||||
|
||||
* Stefan's email address is included in the original document but has not been
|
||||
included here for obvious reasons - please see the file bdiff.1 that is included
|
||||
in the download for details.
|
||||
|
||||
|
||||
================================================================================
|
||||
License used for current version BDiff / BPatch
|
||||
================================================================================
|
||||
|
||||
The current version of the license can be found in LICENSE.md in the root of the
|
||||
Git repository.
|
||||
|
||||
================================================================================
|
54
contrib/bdiff/Docs/PasTrans.txt
Normal file
54
contrib/bdiff/Docs/PasTrans.txt
Normal file
@@ -0,0 +1,54 @@
|
||||
================================================================================
|
||||
|
||||
NOTES ON THE PASCAL TRANSLATION OF BDIFF / BPATCH
|
||||
|
||||
================================================================================
|
||||
|
||||
Release 0.2.1 (pas)
|
||||
-------------------
|
||||
|
||||
This version is a fairly literal, line by line, translation of Stefan Reuther's
|
||||
BDiff v0.2 and BPatch v0.2. The differences are:
|
||||
|
||||
+ The Pascal translation is only suitable for use on Windows targets - it
|
||||
compiles to a Win32 console application and uses the Windows API.
|
||||
|
||||
+ The C version encounters problems reading and writing binary difference files
|
||||
via shell redirection: MS-DOS / Windows could garble input or output because
|
||||
of end-of-line character translations. Therefore Stefan provided the --output
|
||||
(or -o) and --input (or -i) switches to overcome this problem. These switches
|
||||
are used instead of shell redirection on MS-DOS / Windows.
|
||||
|
||||
The Pascal translation does not have this problem and shell redirection can be
|
||||
used safely on Windows systems. Therefore the --input and --output switches
|
||||
are not required, but have been retained.
|
||||
|
||||
+ The numeric parameter to BDiff's -m or --min-equal switches can be specified
|
||||
in decimal, octal or hexadecimal notation on the C version. The Pascal
|
||||
translation supports only decimal notation.
|
||||
|
||||
+ The Pascal versions of BDiff and BPatch contain embedded Windows version
|
||||
information.
|
||||
|
||||
+ Both the C and Pascal versions share a BPatch bug: the program crashes if only
|
||||
one file is supplied on the command line.
|
||||
|
||||
|
||||
Release 0.2.2 (pas)
|
||||
------------------
|
||||
|
||||
This version is again a fairly literal translation. The only change (except for
|
||||
updated version information) is that BDiff contains a Pascal translation of a
|
||||
bug fix in the block sort code for which Stefan provided updated C source code.
|
||||
|
||||
|
||||
Release 0.2.3 and later
|
||||
-----------------------
|
||||
|
||||
From this release BDiff and BPatch broke the link with the original C source and
|
||||
began to develop separately, so further translation notes are not provided.
|
||||
|
||||
Note though that all 0.2.x releases remained functionally equivalent other than
|
||||
for bug fixes.
|
||||
|
||||
--------------------------------------------------------------------------------
|
644
contrib/bdiff/Docs/PreSVNHistory.txt
Normal file
644
contrib/bdiff/Docs/PreSVNHistory.txt
Normal file
@@ -0,0 +1,644 @@
|
||||
================================================================================
|
||||
|
||||
BDIFF / BPATCH: Historical update information from v0.2.1 to v0.2.5
|
||||
|
||||
================================================================================
|
||||
|
||||
This file records known changes to files and releases of the BDiff / BPatch
|
||||
utilities from the first Pascal release (v0.2.1) until release 0.2.5 when the
|
||||
project was placed under version control with Subversion. Later the code was
|
||||
ported from Subversion to Git.
|
||||
|
||||
There are three sections:
|
||||
+ Files: Lists all source code and development tools and provides details of
|
||||
changes to these files that preceded version control.
|
||||
+ Releases: Lists all the releases of BDiff / BPatch and notes which file
|
||||
revisions were included in each release.
|
||||
+ Compilers: Lists the compilers required to build each release.
|
||||
|
||||
================================================================================
|
||||
FILES
|
||||
================================================================================
|
||||
|
||||
This section lists all files for which update history is known between the first
|
||||
released version of the utilities and release 0.2.5.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DevTools\BuildAll.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - Original version
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DevTools\BuildPascal.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - First version.
|
||||
v1.1 of 07 Apr 2008 - Modified to work with BPtch renamed from BPatch.
|
||||
v1.2 of 14 Aug 2008 - Changed back to work "unrenamed" BPatch.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DevTools\BuildResources.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - First version.
|
||||
v1.1 of 07 Apr 2008 - Modified to work with BPtch renamed from BPatch.
|
||||
v1.2 of 14 Aug 2008 - Changed back to work "unrenamed" BPatch.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DevTools\Release.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 18 Sep 2007 - First version.
|
||||
v1.1 of 07 Apr 2008 - Updated to work with renamed BPtch (from BPatch).
|
||||
- Now copy .res files from Bin directories.
|
||||
v1.2 of 14 Aug 2008 - Changed back to work "unrenamed" BPatch.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
DevTools\Tidy.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - Original version.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\BDiff.phf
|
||||
--------------------------------------------------------------------------------
|
||||
18 Sep 2007 - New project update file for BDiff.
|
||||
07 Apr 2008 - Added details of BDiff v0.2.3 build 4.
|
||||
14 Aug 2008 - Added details of BDiff v0.2.5 build 5.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\BDiff.txt
|
||||
--------------------------------------------------------------------------------
|
||||
27 Nov 2003 - Original version - based on OrigC\bdiff.1.
|
||||
07 Apr 2008 - Revised to refer to BDiff 0.2.4 instead of 0.2.
|
||||
- Removed crosss references to other "man pages"
|
||||
14 Aug 2008 - Reformatted document.
|
||||
- Revised, clarified and corrected text.
|
||||
- Provided new disclaimer paragraph.
|
||||
- Provided new copyright paragraph.
|
||||
- Revised to refer to BDiff 0.2.4 instead of 0.2.4.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\BPatch.phf
|
||||
--------------------------------------------------------------------------------
|
||||
18 Sep 2007 - New project update file for BPatch.
|
||||
07 Apr 2008 - Added details of BPtch v0.2.4.
|
||||
- Noted BPatch renamed as BPtch.
|
||||
- Renamed as BPtch.phf from BPatch.phf.
|
||||
14 Aug 2008 - Added details of BPatch v0.2.5.
|
||||
- Noted BPatch renamed back to original name.
|
||||
- Renamed from BPtch.phf back to BPatch.phf.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\BPatch.txt
|
||||
--------------------------------------------------------------------------------
|
||||
27 Nov 2003 - Original version - based on OrigC\bpatch.1.
|
||||
07 Apr 2008 - Revised to refer to BPtch 0.2.4 instead of BPatch 0.2.
|
||||
- Removed crosss references to other "man pages"
|
||||
- Renamed as BPtch.txt from BPatch.txt
|
||||
14 Aug 2008 - Reformatted document.
|
||||
- Revised, clarified and corrected text.
|
||||
- Provided new disclaimer paragraph.
|
||||
- Provided new copyright paragraph.
|
||||
- Revised to refer to BDiff 0.2.4 instead of 0.2.4.
|
||||
- Renamed back to BPatch.txt from BPtch.txt
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\ChangeLog.txt
|
||||
--------------------------------------------------------------------------------
|
||||
29 Nov 2003 - First version of project's changelog for release 0.2.1.
|
||||
21 Dec 2003 - Added info about release 0.2.2.
|
||||
18 Sep 2007 - Added info about release 0.2.3.
|
||||
- Removed info about C versions.
|
||||
07 Apr 2008 - Added info about release 0.2.4.
|
||||
14 Aug 2008 - Added info about release 0.2.5.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\EmailsReLicense.txt
|
||||
--------------------------------------------------------------------------------
|
||||
17 Sep 2007 - Record of emails between Peter Johnson and Stefan Reuther
|
||||
re licensing terms.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\LICENSE
|
||||
--------------------------------------------------------------------------------
|
||||
18 Sep 2007 - License file containing new license for project.
|
||||
08 Apr 2008 - Revised re change of name of BPatch to BPtch.
|
||||
14 Aug 2008 - Revised re change of name of BPtch back to BPacth.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\OldLicenses.txt
|
||||
--------------------------------------------------------------------------------
|
||||
18 Sep 2007 - Record of old licenses for C code and Pascal
|
||||
translations.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\PasTrans.txt
|
||||
--------------------------------------------------------------------------------
|
||||
29 Nov 2003 - First version of Pascal Translation notes.
|
||||
21 Dec 2003 - Modified re changes in release 0.2.2
|
||||
18 Sep 2007 - Modified re changes in release 0.2.3 and later
|
||||
08 Apr 2008 - Noted change of name of BPatch to BPtch.
|
||||
- Added section for release 0.2.4 and later.
|
||||
14 Aug 2008 - Noted change of name of BPtch back to BPatch.
|
||||
- Added section for release 0.2.5 and later.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Docs\README
|
||||
--------------------------------------------------------------------------------
|
||||
29 Nov 2003 - First version of read me file covering program outline,
|
||||
installation, source code and copyright.
|
||||
- Original name was ReadMe.txt
|
||||
18 Sep 2007 - Renamed from ReadMe.txt to README.
|
||||
- Completely rewritten.
|
||||
07 Apr 2008 - Noted change of name of BPatch to BPtch.
|
||||
- Added note re provided binary files in source code
|
||||
section.
|
||||
14 Aug 2008 - Noted change of name of BPtch back to BPatch.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\bdiff.1
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\bdiff.c
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\blksort.c
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
16 Dec 2003 - Bug fix supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\bpatch.1
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\bpatch.c
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\makefile
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
OrigC\README
|
||||
--------------------------------------------------------------------------------
|
||||
20 Jul 1999 - Original version supplied by Stefan Reuther
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff.bpg
|
||||
--------------------------------------------------------------------------------
|
||||
28 Nov 2003 - Original project group file containing BDiff and BPatch.
|
||||
07 Apr 2008 - Revised re renaming of BPatch to BPtch.
|
||||
14 Aug 2008 - Revised re renaming of BPtch back to BPatch.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\BDiff.cfg
|
||||
--------------------------------------------------------------------------------
|
||||
28 Nov 2003 - Original Delphi project config file.
|
||||
21 Dec 2003 - Changed some absolute file paths.
|
||||
18 Sep 2007 - Revised for Delphi 7.
|
||||
- Made path to exe files relative.
|
||||
07 Apr 2008 - Changed some absolute library file paths.
|
||||
14 Aug 2008 - No changes: touched file.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\BDiff.dpr
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Changed copyright and license notice.
|
||||
v1.2 of 14 Aug 2008 - Included BDiff resource that contains a manifest that
|
||||
tells Vista to run program as invoked.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\BDiff.manifest
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 14 Aug 2008 - Original version that permits application to run without
|
||||
elevation on Vista.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\BDiff.rc
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 14 Aug 2008 - Original version
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\Build.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - First version.
|
||||
v1.1 of 14 Aug 2008 - Added code to compile .rc file.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\UBDiff.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original Pascal translation of bdiff.c
|
||||
v1.1 of 18 Sep 2007 - Fixed memory leaks by freeing various memory buffers.
|
||||
- Removed "side-by-side" C code.
|
||||
- Updated help screen copyright statement and added
|
||||
information about -o / --output switch and various
|
||||
format options.
|
||||
- Changed date format displayed by --version switch.
|
||||
- Fixed small bug in -h and -v options.
|
||||
- Fixed a buffer size in print_binary_add routine.
|
||||
- Updated version constant to 0.2.3.
|
||||
- Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\UBDiffTypes.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\UBDiffUtils.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Added new RedirectStdOut() routine.
|
||||
- Removed redundant malloc() routine.
|
||||
- Explicitly cast handles of stdout and stderr to
|
||||
correct types
|
||||
- Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\UBlkSort.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original Pascal translation of blksort.c
|
||||
v1.1 of 21 Dec 2003 - Bug fix based on updated blksort.c provided by Stefan
|
||||
Reuther.
|
||||
v1.2 of 18 Sep 2007 - Replaced call to C-style malloc() function with call to
|
||||
GetMem. Made a few minor related modifications.
|
||||
- Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BDiff\VBDiff.vi
|
||||
--------------------------------------------------------------------------------
|
||||
28 Nov 2003 - First version: file version is 0.2.1 build 1 and product
|
||||
version is 0.2.1.
|
||||
21 Dec 2003 - Updated file version to 0.2.2 build 2 and product version
|
||||
to 0.2.2.
|
||||
18 Sep 2007 - Added header comments and license.
|
||||
- Removed RC comments and output dir path.
|
||||
- Modified LegalCopyright string table entry.
|
||||
- Updated file version to 0.2.3 build 3 and product version
|
||||
to 0.2.3.
|
||||
- Updated file description.
|
||||
- Changed comments to give overview of distribution and
|
||||
refer to License.txt.
|
||||
- Deleted identifier string to let default value be used.
|
||||
- Removed SpecialBuild string item and macro references.
|
||||
- Added build number to file version string.
|
||||
07 Apr 2008 - Updated file version to 0.2.3 build 4 and product version
|
||||
to 0.2.4.
|
||||
14 Aug 2008 - Updated file version to 0.2.5 build 5 and product version
|
||||
to 0.2.5.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\BPatch.cfg
|
||||
--------------------------------------------------------------------------------
|
||||
28 Nov 2003 - Original Delphi project config file.
|
||||
21 Dec 2003 - Changed some absolute file paths.
|
||||
18 Sep 2007 - Revised for Delphi 7.
|
||||
- Made path to exe files relative.
|
||||
07 Apr 2008 - Changed some absolute library file paths.
|
||||
- Change relative paths re renamed BPtch directory.
|
||||
- Renamed file from BPatch.cfg to BPtch.cfg.
|
||||
14 Aug 2008 - Change relative paths re renamed BPatch directory.
|
||||
- Renamed file from BPtch.cfg back to BPatch.cfg.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\BPatch.dpr
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Changed copyright and license notice.
|
||||
v1.2 of 07 Apr 2008 - Renamed from BPatch.dpr to BPtch.dpr. "BPatch" caused
|
||||
Windows Vista to flag the program for elevation!
|
||||
v1.3 of 14 Aug 2008 - Renamed back to BPatch.dpr from BPtch.dpr.
|
||||
- Included BPatch.res containing manifest that causes
|
||||
program to be run as invoked, overriding Vista's desire
|
||||
to elevate the program because "patch" is included in
|
||||
name.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\BPatch.manifest
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 14 Aug 2008 - Original version that permits application to run without
|
||||
elevation on Vista (Vista would elevate without this
|
||||
because "Patch" is in file name).
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\BPatch.rc
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 14 Aug 2008 - Original version.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\Build.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 16 Sep 2007 - First version.
|
||||
v1.1 of 07 Apr 2008 - Altered to work with BPtch renamed from BPatch.
|
||||
v1.2 of 14 Aug 2008 - Altered back work with "unrenamed" BPatch.
|
||||
- Added code to compile .rc file.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\UBPatch.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original Pascal translation of bpatch.c
|
||||
v1.1 of 18 Sep 2007 - Fixed bug preventing overwriting of existing output
|
||||
files.
|
||||
- Removed "side-by-side" C code.
|
||||
- Removed conditional Windows / DOS conditional code.
|
||||
- Updated help screen copyright statement.
|
||||
- Changed date format displayed by --version switch.
|
||||
- Fixed small bug in -h and -v options.
|
||||
- Moved code that redirects stdin to UBDiffUtils unit.
|
||||
- Updated version constant to 0.2.3 (skipping 0.2.2).
|
||||
- Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\UBPatchTypes.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\UBPatchUtils.pas
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 28 Nov 2003 - Original version.
|
||||
v1.1 of 18 Sep 2007 - Added RedirectStdIn() routine.
|
||||
- Explicitly cast handles of stdin, stdout and stderr to
|
||||
correct types.
|
||||
- Changed copyright and license notice.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Src\BPatch\VBPatch.vi
|
||||
--------------------------------------------------------------------------------
|
||||
28 Nov 2003 - First version: file version is 0.2.1 build 1 and product
|
||||
version is 0.2.1.
|
||||
21 Dec 2003 - Updated file version to 0.2.1 build 2 and product number
|
||||
to 0.2.2
|
||||
18 Sep 2007 - Added header comments license.
|
||||
- Removed RC comments and output dir path.
|
||||
- Modified LegalCopyright string table entry.
|
||||
- Updated file version to 0.2.3 build 3 and product version
|
||||
to 0.2.3.
|
||||
- Updated file description.
|
||||
- Changed comments to give overview of distribution and
|
||||
refer to License.txt.
|
||||
- Deleted identifier string to let default value be used.
|
||||
- Removed SpecialBuild string item and macro references.
|
||||
- Added build number to file version string.
|
||||
07 Apr 2008 - Updated file version to 0.2.4 build 4 and product version
|
||||
to 0.2.4.
|
||||
- Rephrased text to avoid the use of the word "patch" due
|
||||
to problems with Windows Vista.
|
||||
- Changed OriginalFileName to BPtch.exe
|
||||
14 Aug 2008 - Updated file version to 0.2.5 build 5 and product version
|
||||
to 0.2.5.
|
||||
- Changed OriginalFileName back to BPatch.exe.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Test\Test.bat
|
||||
--------------------------------------------------------------------------------
|
||||
v1.0 of 18 Sep 2007 - First version.
|
||||
v1.0 of 07 Apr 2008 - Revised to work with BPtch renamed from BPatch.
|
||||
v1.2 of 14 Aug 2008 - Revised to work with "unrenamed" BPatch.
|
||||
- Forced to work with exe files from Exe folder, preventing
|
||||
calling of any other versions on path.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Test\Test1
|
||||
--------------------------------------------------------------------------------
|
||||
21 Dec 2003 - Copy of UBlkSort.pas used as 1st generation document used
|
||||
in test comparisons.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
Test\Test2
|
||||
--------------------------------------------------------------------------------
|
||||
15 Sep 2007 - Modified copy of UBlkSort.pas used as 2nd generation
|
||||
document for use in test comparisons for checking against
|
||||
Test1.
|
||||
31 Jul 2009 - MOVED TO SUBVERSION
|
||||
|
||||
================================================================================
|
||||
RELEASES
|
||||
================================================================================
|
||||
|
||||
This section lists all releases of the utilities from the first Pascal version
|
||||
to release 0.2.5. For each release the following is noted:
|
||||
|
||||
+ Version and build number of BDiff and BPatch.
|
||||
+ Brief notes of changes to each utility.
|
||||
+ List of new and added source files.
|
||||
|
||||
The Development tools, .bpg and .cfg files, test files and documentation are not
|
||||
included in this information.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.1 of 29 Nov 2003
|
||||
--------------------------------------------------------------------------------
|
||||
BDiff.exe v0.2.1 build 1
|
||||
Notes:
|
||||
+ First Pascal translation of BDiff v0.2 by Stefan Reuther.
|
||||
File changes:
|
||||
+ New: BDiff.dpr 1.0
|
||||
+ New: UBDiff.pas 1.0
|
||||
+ New: UBDiffTypes.pas 1.0
|
||||
+ New: UBDiffUtils.pas 1.0
|
||||
+ New: UBlkSort.pas 1.0
|
||||
+ New: VBDiff.vi 28 Nov 2003
|
||||
BPatch.exe v0.2.1 build 1
|
||||
Notes:
|
||||
+ First Pascal translation of BPatch v0.2 by Stefan Reuther.
|
||||
File changes:
|
||||
+ New: BPatch.dpr 1.0
|
||||
+ New: UBPatch.pas 1.0
|
||||
+ New: UBPatchTypes.pas 1.0
|
||||
+ New: UBPatchUtils.pas 1.0
|
||||
+ New: VBPatch.vi 28 Nov 2003
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.2 of 21 Dec 2003
|
||||
--------------------------------------------------------------------------------
|
||||
BDiff.exe v0.2.2 build 2
|
||||
Notes:
|
||||
+ Fixed bug in block sort, per fix in C program provided by Stefan Reuther.
|
||||
File changes:
|
||||
+ Updated: UBlkSort.pas 1.1
|
||||
+ Updated: VBDiff.vi 21 Dec 2003
|
||||
BPatch.exe v0.2.1 build 2
|
||||
Notes:
|
||||
+ Unchanged other than to update product abd build number in version
|
||||
information.
|
||||
File changes:
|
||||
+ Updated: VBPatch.vi 21 Dec 2003
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.3 of 18 Sep 2007
|
||||
--------------------------------------------------------------------------------
|
||||
BDiff.exe v0.2.3 build 3
|
||||
Notes:
|
||||
+ Fixed some memory leaks.
|
||||
+ Fixed small bug in -h and -v switches.
|
||||
+ Updated copyright statements on help screen and description of missing
|
||||
options.
|
||||
+ Updated version to v0.2.3.
|
||||
+ Added batch file that can build the project.
|
||||
+ Some minor refactoring.
|
||||
+ Switched off various warnings in .cfg file.
|
||||
+ Changed to new binary and source license.
|
||||
File changes:
|
||||
+ Updated: BDiff.dpr 1.1
|
||||
+ Updated: UBDiff.pas 1.1
|
||||
+ Updated: UBDiffTypes.pas 1.1
|
||||
+ Updated: UBDiffUtils.pas 1.1
|
||||
+ Updated: UBlkSort.pas 1.2
|
||||
+ Updated: VBDiff.vi 18 Sep 2007
|
||||
+ New: Build.bat 1.0
|
||||
BPatch.exe v0.2.3 build 3 (v0.2.2 skipped)
|
||||
Notes:
|
||||
+ Fixed bug where the program could not overwrite existing files.
|
||||
+ Fixed small bug in -h and -v switches.
|
||||
+ Removed conditional compilation for unsupported target OSs.
|
||||
+ Updated copyright statements on help screen.
|
||||
+ Updated version to v0.2.3, skipping v0.2.2 to synchronise with BDiff.
|
||||
+ Added batch file that can build the project.
|
||||
+ Some minor refactoring.
|
||||
+ Switched off various warnings in .cfg file.
|
||||
+ Changed to new binary and source license.
|
||||
File changes:
|
||||
+ Updated: BPatch.dpr 1.1
|
||||
+ Updated: UBPatch.pas 1.1
|
||||
+ Updated: UBPatchTypes.pas 1.1
|
||||
+ Updated: UBPatchUtils.pas 1.1
|
||||
+ Updated: VBPatch.vi 18 Sep 2007
|
||||
+ New: Build.bat 1.0
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.4 of 07 Apr 2008
|
||||
--------------------------------------------------------------------------------
|
||||
BDiff.exe v0.2.3 build 4
|
||||
Notes:
|
||||
+ Unchanged except that build number incremented to 4.
|
||||
File changes:
|
||||
+ VBDiff.vi 07 Apr 2008
|
||||
BPatch.exe v0.2.4 build 4
|
||||
Notes:
|
||||
+ Renamed program from BPatch to BPtch and removed the word "patch" from
|
||||
version information. This was to prevent Windows Vista from requiring the
|
||||
program to be run in elevated state.
|
||||
File changes:
|
||||
+ Updated: BPtch.dpr 1.2 (renamed from BPatch.dpr)
|
||||
+ Updated: VBPatch.vi 07 Apr 2008
|
||||
+ Updated: Build.bat 1.1
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.5 of 14 Aug 2008
|
||||
--------------------------------------------------------------------------------
|
||||
BDiff.exe v0.2.5 build 5 (v0.2.4 skipped)
|
||||
Notes:
|
||||
+ Added manifest to resources that tells Windows Vista to run program as
|
||||
invoked.
|
||||
+ Skipped a version number to v0.2.5 to keep in sync with BPatch.
|
||||
File changes:
|
||||
+ Updated: BDiff.dpr 1.2
|
||||
+ New: BDiff.manifest 1.0
|
||||
+ New: BDiff.rc 1.0
|
||||
+ Updated: Build.bat 1.1
|
||||
+ Updated: VBDiff.vi 14 Aug 2008
|
||||
BPatch.exe v0.2.5 build 5
|
||||
Notes:
|
||||
+ Renamed program back to BPatch from BPtch.
|
||||
+ Added a manifest to resources that informs Vista to run the program as
|
||||
invoked. This overrides Vista's desire to run elevated because "patch" is
|
||||
in file name.
|
||||
File changes:
|
||||
+ Updated: BPatch.dpr 1.3 (renamed from BPtch.dpr)
|
||||
+ New: BPatch.manifest 1.0
|
||||
+ New: BPatch.rc 1.0
|
||||
+ Updated: Build.bat 1.2
|
||||
+ Updated: VBPatch.vi 14 Aug 2008
|
||||
|
||||
================================================================================
|
||||
COMPILERS
|
||||
================================================================================
|
||||
|
||||
This section notes the various compilers and build tools used to create each
|
||||
release of the utilities from the first Pascal version to v0.2.5.
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.1 of 29 Nov 2003
|
||||
--------------------------------------------------------------------------------
|
||||
+ Delphi 4
|
||||
+ DelphiDabbler Version Information Editor v2.10
|
||||
+ Borland BRCC32
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.2 of 21 Dec 2003
|
||||
--------------------------------------------------------------------------------
|
||||
+ Delphi 4
|
||||
+ DelphiDabbler Version Information Editor v2.10.1
|
||||
+ Borland BRCC32
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.3 of 18 Sep 2007
|
||||
--------------------------------------------------------------------------------
|
||||
+ Delphi 7
|
||||
+ DelphiDabbler Version Information Editor v2.11
|
||||
+ Borland BRCC32 v5.4
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.4 of 07 Apr 2008
|
||||
--------------------------------------------------------------------------------
|
||||
+ Delphi 7
|
||||
+ DelphiDabbler Version Information Editor v2.11
|
||||
+ Borland BRCC32 v5.4
|
||||
|
||||
--------------------------------------------------------------------------------
|
||||
v0.2.5 of 14 Aug 2008
|
||||
--------------------------------------------------------------------------------
|
||||
+ Delphi 7
|
||||
+ DelphiDabbler Version Information Editor v2.11.2
|
||||
+ Borland BRCC32 v5.4
|
18
contrib/bdiff/LICENSE.md
Normal file
18
contrib/bdiff/LICENSE.md
Normal file
@@ -0,0 +1,18 @@
|
||||
BDiff / BPatch License
|
||||
======================
|
||||
|
||||
_BDiff_ and _BPatch_ have been developed from a Pascal translation of original C source code by Stefan Reuther. The Pascal translation was created by Peter D Johnson.
|
||||
|
||||
The original C source code was copyright (c) 1999 by Stefan Reuther (Streu@gmx.de). The Pascal translation and subsequent updates are copyright (c) 2003-2016 by Peter D Johnson (@delphidabbler).
|
||||
|
||||
THIS SOFTWARE IS PROVIDED "AS-IS", WITHOUT ANY EXPRESS OR IMPLIED WARRANTY. IN NO EVENT WILL THE AUTHORS BE HELD LIABLE FOR ANY DAMAGES ARISING FROM THE USE OF THIS SOFTWARE.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose and to alter it and redistribute it, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgement in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. All redistributions of source code files must retain any author, copyright and license notices that are currently in place in the source code files. An unchanged copy of this license must be included with the redistribution.
|
||||
|
||||
3. All redistributions in binary form must contain all occurrences of the above copyright notices and any web site addresses that are currently in place (for example in help screens). A copy of this license must be included with the redistribution.
|
||||
|
||||
4. Modified versions in source or binary form must be plainly marked as such, and must not be misrepresented as being the original software. Details of modification must be included in source code files. All original author, license and copyright statements must be retained unchanged.
|
60
contrib/bdiff/README.md
Normal file
60
contrib/bdiff/README.md
Normal file
@@ -0,0 +1,60 @@
|
||||
BDiff / BPatch
|
||||
==============
|
||||
|
||||
Binary diff and patch programs for the Windows command line.
|
||||
|
||||
Introduction
|
||||
------------
|
||||
|
||||
_BDiff_ computes differences between two binary files. Output can be either a somewhat human-readable protocol in plain text, or a binary file that is readable by _BPatch_.
|
||||
|
||||
_BPatch_ applies a binary patch generated by _BDiff_ to a file to recreate the original file.
|
||||
|
||||
See the files `BDiff.txt` and `BPatch.txt` in the `Docs` directory for details of how to use the programs.
|
||||
|
||||
_BDiff_ and _BPatch_ are derived from Stefan Reuther's _bdiff_ and _bpatch_ v0.2 and a later bug fix by Stefan.
|
||||
|
||||
The original C source was translated into Object Pascal by Peter D Johnson ([@delphdabbler](https://twitter.com/delphidabbler)). The programs are are based on updates of the Pascal code base.
|
||||
|
||||
The programs should run on any current version of Windows.
|
||||
|
||||
For more information see the see the [project web pages](http://delphidabbler.com/software/bdiff).
|
||||
|
||||
Installation
|
||||
------------
|
||||
|
||||
Copy the provided executable files to the required location. No further installation is required.
|
||||
|
||||
You may want to modify the Windows PATH environment variable to include the location of the programs.
|
||||
|
||||
To uninstall simply delete the programs. They make no changes to the system. If you changed the PATH environment variable you may wish to adjust this.
|
||||
|
||||
Tests
|
||||
-----
|
||||
|
||||
You can test the operation of _BDiff_ and _BPatch_ using the `Test.bat` script in the `Test` directory. See `ReadMe.txt` in that directory for details.
|
||||
|
||||
Source Code
|
||||
-----------
|
||||
|
||||
### Pascal Source
|
||||
|
||||
The current source code is maintained in the [delphidabbler/bdiff](https://github.com/delphidabbler/bdiff) Git repository on GitHub. It contains releases going back to v0.2.5. Earlier versions were not under version control and are no longer available.
|
||||
|
||||
> **Note:** Until February 2014 the source code was maintained in a Subversion repository. A dump of the repo is available from [Google Drive](https://drive.google.com/file/d/0B8qEVqTUMgmJcF9zVnk0Zk1VMDQ/view?usp=sharing).
|
||||
|
||||
For information on how to build the Pascal source, see `Build.txt` in the root of the Git repo.
|
||||
|
||||
### C Source
|
||||
|
||||
The original C source code can be downloaded from http://phost.de/~stefan/Files/bdiff-02.zip.
|
||||
|
||||
Copyright and License
|
||||
---------------------
|
||||
|
||||
See the file `LICENCE.md` for details of copyright and the license that applies to this software.
|
||||
|
||||
Change Log
|
||||
----------
|
||||
|
||||
The change log is provided in the file `CHANGELOG.txt`.
|
105
contrib/bdiff/UAppInfo.pas
Normal file
105
contrib/bdiff/UAppInfo.pas
Normal file
@@ -0,0 +1,105 @@
|
||||
{
|
||||
* Provides information about program: file name, date and version info.
|
||||
* Common code used by both BDiff and BPatch.
|
||||
}
|
||||
|
||||
|
||||
unit UAppInfo;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TAppInfo = class(TObject)
|
||||
private
|
||||
{ Fully specified file name of program, with absolute path }
|
||||
class function ProgramPath: string;
|
||||
public
|
||||
{ Name of program's executable file, without path }
|
||||
class function ProgramFileName: string;
|
||||
{ Name of program, without file extension }
|
||||
class function ProgramBaseName: string;
|
||||
{ Program's product version number }
|
||||
class function ProgramVersion: string;
|
||||
{ Last modification date of program's executable file }
|
||||
class function ProgramExeDate: string;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils, Windows;
|
||||
|
||||
|
||||
{ TAppInfo }
|
||||
|
||||
class function TAppInfo.ProgramBaseName: string;
|
||||
begin
|
||||
Result := ChangeFileExt(ProgramFileName, '');
|
||||
end;
|
||||
|
||||
class function TAppInfo.ProgramExeDate: string;
|
||||
var
|
||||
FileDate: TDateTime; // date stamp of exe file
|
||||
begin
|
||||
if FileAge(ProgramPath, FileDate) then
|
||||
Result := FormatDateTime('dd mmm yyyy', FileDate)
|
||||
else
|
||||
Result := '';
|
||||
end;
|
||||
|
||||
class function TAppInfo.ProgramFileName: string;
|
||||
begin
|
||||
Result := ExtractFileName(ProgramPath);
|
||||
end;
|
||||
|
||||
class function TAppInfo.ProgramPath: string;
|
||||
begin
|
||||
Result := ParamStr(0);
|
||||
end;
|
||||
|
||||
class function TAppInfo.ProgramVersion: string;
|
||||
var
|
||||
Dummy: DWORD; // unused variable required in API calls
|
||||
VerInfoSize: Integer; // size of version information data
|
||||
VerInfoBuf: Pointer; // buffer holding version information
|
||||
ValPtr: Pointer; // pointer to a version information value
|
||||
FFI: TVSFixedFileInfo; // fixed file information from version info
|
||||
begin
|
||||
Result := '';
|
||||
// Get fixed file info from program's version info
|
||||
// get size of version info
|
||||
VerInfoSize := GetFileVersionInfoSize(PChar(ProgramPath), Dummy);
|
||||
if VerInfoSize > 0 then
|
||||
begin
|
||||
// create buffer and read version info into it
|
||||
GetMem(VerInfoBuf, VerInfoSize);
|
||||
try
|
||||
if GetFileVersionInfo(
|
||||
PChar(ProgramPath), Dummy, VerInfoSize, VerInfoBuf
|
||||
) then
|
||||
begin
|
||||
// get fixed file info from version info (ValPtr points to it)
|
||||
if VerQueryValue(VerInfoBuf, '\', ValPtr, Dummy) then
|
||||
begin
|
||||
FFI := PVSFixedFileInfo(ValPtr)^;
|
||||
// Build version info string from product version field of FFI
|
||||
Result := Format(
|
||||
'%d.%d.%d',
|
||||
[
|
||||
HiWord(FFI.dwProductVersionMS),
|
||||
LoWord(FFI.dwProductVersionMS),
|
||||
HiWord(FFI.dwProductVersionLS)
|
||||
]
|
||||
);
|
||||
end
|
||||
end;
|
||||
finally
|
||||
FreeMem(VerInfoBuf);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
54
contrib/bdiff/UBDiffInfoWriter.pas
Normal file
54
contrib/bdiff/UBDiffInfoWriter.pas
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
* Class that emits BDiff's version information and help screen on standard
|
||||
* output.
|
||||
}
|
||||
|
||||
|
||||
unit UBDiffInfoWriter;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UInfoWriter;
|
||||
|
||||
type
|
||||
TBDiffInfoWriter = class(TInfoWriter)
|
||||
protected
|
||||
class function HelpText: string; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
UAppInfo;
|
||||
|
||||
{ TBDiffInfoWriter }
|
||||
|
||||
class function TBDiffInfoWriter.HelpText: string;
|
||||
begin
|
||||
Result := Format(
|
||||
'%0:s: binary ''diff'' - compare two binary files'#13#10#13#10
|
||||
+ 'Usage: %0:s [options] old-file new-file [>patch-file]'#13#10#13#10
|
||||
+ 'Difference between old-file and new-file written to standard output'
|
||||
+ #13#10#13#10
|
||||
+ 'Valid options:'#13#10
|
||||
+ ' -q Use QUOTED format'#13#10
|
||||
+ ' -f Use FILTERED format'#13#10
|
||||
+ ' -b Use BINARY format'#13#10
|
||||
+ ' --format=FMT Use format FMT (''quoted'', ''filter[ed]'' '
|
||||
+ 'or ''binary'')'#13#10
|
||||
+ ' -m N --min-equal=N Minimum equal bytes to recognize an equal chunk'
|
||||
+ #13#10
|
||||
+ ' -o FN --output=FN Set output file name (instead of stdout)'#13#10
|
||||
+ ' -V --verbose Show status messages'#13#10
|
||||
+ ' -h --help Show this help screen'#13#10
|
||||
+ ' -v --version Show version information'#13#10
|
||||
+ #13#10
|
||||
+ '(c) copyright 1999 Stefan Reuther <Streu@gmx.de>'#13#10
|
||||
+ '(c) copyright 2003-2016 Peter Johnson (@delphidabbler)'#13#10,
|
||||
[TAppInfo.ProgramFileName]
|
||||
);
|
||||
end;
|
||||
|
||||
end.
|
107
contrib/bdiff/UBDiffMain.pas
Normal file
107
contrib/bdiff/UBDiffMain.pas
Normal file
@@ -0,0 +1,107 @@
|
||||
{
|
||||
* Static class containing main program logic for BDiff program.
|
||||
}
|
||||
|
||||
|
||||
unit UBDiffMain;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UBDiffParams;
|
||||
|
||||
type
|
||||
TMain = class(TObject)
|
||||
private
|
||||
class procedure DisplayHelp;
|
||||
class procedure DisplayVersion;
|
||||
class procedure CreateDiff(Params: TParams);
|
||||
class procedure RedirectStdOut(const FileName: string);
|
||||
public
|
||||
class procedure Run;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
UAppInfo, UDiffer, UBDiffInfoWriter, UBDiffUtils, UErrors, ULogger;
|
||||
|
||||
{ TMain }
|
||||
|
||||
class procedure TMain.CreateDiff(Params: TParams);
|
||||
var
|
||||
Differ: TDiffer;
|
||||
Logger: TLogger;
|
||||
begin
|
||||
// create the diff
|
||||
Logger := TLoggerFactory.Instance(Params.Verbose);
|
||||
try
|
||||
Differ := TDiffer.Create;
|
||||
try
|
||||
Differ.MinMatchLength := Params.MinEqual;
|
||||
Differ.Format := Params.Format;
|
||||
Differ.MakeDiff(Params.OldFileName, Params.NewFileName, Logger);
|
||||
finally
|
||||
Differ.Free;
|
||||
end;
|
||||
finally
|
||||
Logger.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TMain.DisplayHelp;
|
||||
begin
|
||||
TBDiffInfoWriter.HelpScreen;
|
||||
end;
|
||||
|
||||
class procedure TMain.DisplayVersion;
|
||||
begin
|
||||
TBDiffInfoWriter.VersionInfo;
|
||||
end;
|
||||
|
||||
class procedure TMain.RedirectStdOut(const FileName: string);
|
||||
var
|
||||
PatchFileHandle: Integer;
|
||||
begin
|
||||
// redirect standard output to patch file
|
||||
PatchFileHandle := FileCreate(FileName);
|
||||
if PatchFileHandle <= 0 then
|
||||
OSError;
|
||||
TIO.RedirectStdOut(PatchFileHandle);
|
||||
end;
|
||||
|
||||
class procedure TMain.Run;
|
||||
var
|
||||
Params: TParams;
|
||||
begin
|
||||
ExitCode := 0;
|
||||
try
|
||||
Params := TParams.Create;
|
||||
try
|
||||
Params.Parse;
|
||||
if Params.Help then
|
||||
DisplayHelp
|
||||
else if Params.Version then
|
||||
DisplayVersion
|
||||
else
|
||||
begin
|
||||
if (Params.PatchFileName <> '') and (Params.PatchFileName <> '-') then
|
||||
RedirectStdOut(Params.PatchFileName);
|
||||
CreateDiff(Params);
|
||||
end;
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ExitCode := 1;
|
||||
TIO.WriteStrFmt(
|
||||
TIO.StdErr, '%0:s: %1:s'#13#10, [TAppInfo.ProgramFileName, E.Message]
|
||||
);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
185
contrib/bdiff/UBDiffParams.pas
Normal file
185
contrib/bdiff/UBDiffParams.pas
Normal file
@@ -0,0 +1,185 @@
|
||||
{
|
||||
* Implements a class that parses command lines and records parameters.
|
||||
}
|
||||
|
||||
|
||||
unit UBDiffParams;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBaseParams, UBDiffTypes;
|
||||
|
||||
type
|
||||
|
||||
TParams = class(TBaseParams)
|
||||
private
|
||||
fVerbose: Boolean;
|
||||
fMinEqual: Integer;
|
||||
fOldFileName: string;
|
||||
fPatchFileName: string;
|
||||
fNewFileName: string;
|
||||
fFormat: TFormat;
|
||||
procedure SetFormat(const Value: string);
|
||||
procedure SetMinEqual(const Value: string);
|
||||
protected
|
||||
function ParseLongOption(const Option: string; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean; override;
|
||||
function ParseShortOption(const Options: string; const OptionIdx: Integer;
|
||||
var ParamIdx: Integer; var Terminated: Boolean): Boolean; override;
|
||||
procedure ParseFileName(const FileName: string); override;
|
||||
procedure Finalize; override;
|
||||
public
|
||||
constructor Create;
|
||||
property OldFileName: string read fOldFileName;
|
||||
property NewFileName: string read fNewFileName;
|
||||
property PatchFileName: string read fPatchFileName;
|
||||
property MinEqual: Integer read fMinEqual default 24;
|
||||
property Verbose: Boolean read fVerbose default False;
|
||||
property Help;
|
||||
property Version;
|
||||
property Format: TFormat read fFormat default FMT_QUOTED;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils, StrUtils;
|
||||
|
||||
{ TParams }
|
||||
|
||||
constructor TParams.Create;
|
||||
begin
|
||||
inherited;
|
||||
fOldFileName := '';
|
||||
fNewFileName := '';
|
||||
fPatchFileName := '';
|
||||
fMinEqual := 24;
|
||||
fVerbose := False;
|
||||
fFormat := FMT_QUOTED;
|
||||
end;
|
||||
|
||||
procedure TParams.Finalize;
|
||||
begin
|
||||
if fNewFileName = '' then
|
||||
Error('need two filenames');
|
||||
if SameFileName(fOldFileName, fNewFileName) then
|
||||
Error('file names must not be the same');
|
||||
if SameFileName(fOldFileName, fPatchFileName)
|
||||
or SameFileName(fNewFileName, fPatchFileName) then
|
||||
Error('output file name must differ from other file names');
|
||||
end;
|
||||
|
||||
procedure TParams.ParseFileName(const FileName: string);
|
||||
begin
|
||||
if fOldFileName = '' then
|
||||
fOldFileName := FileName
|
||||
else if fNewFileName = '' then
|
||||
fNewFileName := FileName
|
||||
else
|
||||
Error('too many file names on command line');
|
||||
end;
|
||||
|
||||
function TParams.ParseLongOption(const Option: string; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean;
|
||||
begin
|
||||
Result := inherited ParseLongOption(Option, ParamIdx, Terminated);
|
||||
if Result then
|
||||
Exit;
|
||||
Result := True;
|
||||
if Option = '--verbose' then
|
||||
fVerbose := True
|
||||
else if Option = '--output' then
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
if ParamStr(ParamIdx) = '' then
|
||||
Error('missing argument to ''--output''');
|
||||
fPatchFileName := ParamStr(ParamIdx);
|
||||
end
|
||||
else if AnsiStartsStr('--output=', Option) then
|
||||
fPatchFileName := StripLeadingChars(Option, Length('--output='))
|
||||
else if Option = '--format' then
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
SetFormat(ParamStr(ParamIdx));
|
||||
end
|
||||
else if AnsiStartsStr('--format=', Option) then
|
||||
SetFormat(StripLeadingChars(Option, Length('--format=')))
|
||||
else if Option = '--min-equal' then
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
SetMinEqual(ParamStr(ParamIdx));
|
||||
end
|
||||
else if AnsiStartsStr('--min-equal=', Option) then
|
||||
SetMinEqual(StripLeadingChars(Option, Length('--min-equal=')))
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TParams.ParseShortOption(const Options: string;
|
||||
const OptionIdx: Integer; var ParamIdx: Integer; var Terminated: Boolean):
|
||||
Boolean;
|
||||
begin
|
||||
Result := inherited ParseShortOption(
|
||||
Options, OptionIdx, ParamIdx, Terminated
|
||||
);
|
||||
if Result then
|
||||
Exit;
|
||||
Result := True;
|
||||
case Options[OptionIdx] of
|
||||
'V':
|
||||
fVerbose := True;
|
||||
'q':
|
||||
fFormat := FMT_QUOTED;
|
||||
'f':
|
||||
fFormat := FMT_FILTERED;
|
||||
'b':
|
||||
fFormat := FMT_BINARY;
|
||||
'm':
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
SetMinEqual(ParamStr(ParamIdx));
|
||||
end;
|
||||
'o':
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
if ParamStr(ParamIdx) = '' then
|
||||
Error('missing argument to ''-o''');
|
||||
fPatchFileName := ParamStr(ParamIdx);
|
||||
end;
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TParams.SetFormat(const Value: string);
|
||||
begin
|
||||
if Value = '' then
|
||||
Error('missing argument to ''--format''');
|
||||
if Value = 'quoted' then
|
||||
fFormat := FMT_QUOTED
|
||||
else if (Value = 'filter') or (Value = 'filtered') then
|
||||
fFormat := FMT_FILTERED
|
||||
else if Value = 'binary' then
|
||||
fFormat := FMT_BINARY
|
||||
else
|
||||
Error('invalid format specification');
|
||||
end;
|
||||
|
||||
procedure TParams.SetMinEqual(const Value: string);
|
||||
var
|
||||
X: Int64; // number parsed from command line
|
||||
begin
|
||||
if Value = '' then
|
||||
Error('missing argument to ''--min-equal'' / ''-m''');
|
||||
if not TryStrToInt64(Value, X) or (X < 0) then
|
||||
Error('malformed number on command line');
|
||||
if (X = 0) or (X > $7FFF) then
|
||||
Error('number out of range on command line');
|
||||
fMinEqual := Integer(X);
|
||||
end;
|
||||
|
||||
end.
|
||||
|
40
contrib/bdiff/UBDiffTypes.pas
Normal file
40
contrib/bdiff/UBDiffTypes.pas
Normal file
@@ -0,0 +1,40 @@
|
||||
{
|
||||
* Contains type declarations for BDiff.
|
||||
}
|
||||
|
||||
|
||||
unit UBDiffTypes;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
type
|
||||
{ Some uses of *size_t in original C code actually reference an array of
|
||||
size_t and are referenced using array[] notation. The following types are
|
||||
declared to use in these circumstances to enable similar notation in
|
||||
Pascal }
|
||||
TBlock = array[0..0] of Cardinal;
|
||||
PBlock = ^TBlock;
|
||||
|
||||
{ The original C code refers to the buffered file contents as an array of
|
||||
Char. The fact that Char is signed in C (-127..128) and unsigned in Pascal
|
||||
(0..255) means that the block sort algorithm and string lookup functions
|
||||
operate differently in C and Pascal. We therefore define a signed *ansi*
|
||||
char type - SignedAnsiChar - of the correct range and refer to the buffered
|
||||
file contents as an array of this new type. Since ShortInt is defined as
|
||||
(-127..128) we use this as the basis for SignedAnsiChar}
|
||||
SignedAnsiChar = type ShortInt;
|
||||
PSignedAnsiChar = ^SignedAnsiChar;
|
||||
TSignedAnsiCharArray = array[0..(MaxInt div SizeOf(SignedAnsiChar) - 1)]
|
||||
of SignedAnsiChar;
|
||||
PSignedAnsiCharArray = ^TSignedAnsiCharArray;
|
||||
|
||||
{ Output format to use }
|
||||
TFormat = (FMT_BINARY, FMT_FILTERED, FMT_QUOTED);
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
end.
|
||||
|
36
contrib/bdiff/UBDiffUtils.pas
Normal file
36
contrib/bdiff/UBDiffUtils.pas
Normal file
@@ -0,0 +1,36 @@
|
||||
{
|
||||
* Contains utility functions used for BDiff. Includes Pascal implementations
|
||||
* of, or alternatives for, some standard C library code.
|
||||
}
|
||||
|
||||
|
||||
unit UBDiffUtils;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UUtils;
|
||||
|
||||
type
|
||||
TIO = class(TCommonIO)
|
||||
public
|
||||
{ Redirects standard output to a given file handle }
|
||||
class procedure RedirectStdOut(const Handle: Integer);
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
Windows;
|
||||
|
||||
{ TIO }
|
||||
|
||||
class procedure TIO.RedirectStdOut(const Handle: Integer);
|
||||
begin
|
||||
Windows.SetStdHandle(STD_OUTPUT_HANDLE, Cardinal(Handle));
|
||||
end;
|
||||
|
||||
end.
|
||||
|
49
contrib/bdiff/UBPatchInfoWriter.pas
Normal file
49
contrib/bdiff/UBPatchInfoWriter.pas
Normal file
@@ -0,0 +1,49 @@
|
||||
{
|
||||
* Class that emits BPatch's version information and help screen on standard
|
||||
* output.
|
||||
}
|
||||
|
||||
|
||||
unit UBPatchInfoWriter;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UInfoWriter;
|
||||
|
||||
type
|
||||
TBPatchInfoWriter = class(TInfoWriter)
|
||||
protected
|
||||
class function HelpText: string; override;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
UAppInfo;
|
||||
|
||||
{ TBPatchInfoWriter }
|
||||
|
||||
class function TBPatchInfoWriter.HelpText: string;
|
||||
begin
|
||||
Result := Format(
|
||||
'%0:s: binary ''patch'' - apply binary patch'#13#10
|
||||
+ #13#10
|
||||
+ 'Usage: %0:s [options] old-file [new-file] [<patch-file]'#13#10#13#10
|
||||
+ 'Creates new-file from old-file and patch-file'#13#10
|
||||
+ 'If new-file is not provided old-file is updated in place'#13#10
|
||||
+ #13#10
|
||||
+ 'Valid options:'#13#10
|
||||
+ ' -i FN --input=FN Set input file name (instead of stdin)'
|
||||
+ #13#10
|
||||
+ ' -h --help Show this help screen'#13#10
|
||||
+ ' -v --version Show version information'#13#10
|
||||
+ #13#10
|
||||
+ '(c) copyright 1999 Stefan Reuther <Streu@gmx.de>'#13#10
|
||||
+ '(c) copyright 2003-2016 Peter Johnson (@delphidabbler)'#13#10,
|
||||
[TAppInfo.ProgramFileName]
|
||||
);
|
||||
end;
|
||||
|
||||
end.
|
82
contrib/bdiff/UBPatchMain.pas
Normal file
82
contrib/bdiff/UBPatchMain.pas
Normal file
@@ -0,0 +1,82 @@
|
||||
{
|
||||
* Static class containing main program logic for BPatch program.
|
||||
}
|
||||
|
||||
|
||||
unit UBPatchMain;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TMain = class(TObject)
|
||||
private
|
||||
class procedure DisplayHelp;
|
||||
class procedure DisplayVersion;
|
||||
class procedure RedirectStdIn(const FileName: string);
|
||||
public
|
||||
class procedure Run;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
SysUtils,
|
||||
UAppInfo, UPatcher, UBPatchInfoWriter, UBPatchParams, UBPatchUtils, UErrors;
|
||||
|
||||
{ TMain }
|
||||
|
||||
class procedure TMain.DisplayHelp;
|
||||
begin
|
||||
TBPatchInfoWriter.HelpScreen;
|
||||
end;
|
||||
|
||||
class procedure TMain.DisplayVersion;
|
||||
begin
|
||||
TBPatchInfoWriter.VersionInfo;
|
||||
end;
|
||||
|
||||
class procedure TMain.RedirectStdIn(const FileName: string);
|
||||
var
|
||||
PatchFileHandle: Integer;
|
||||
begin
|
||||
PatchFileHandle := FileOpen(FileName, fmOpenRead or fmShareDenyNone);
|
||||
if PatchFileHandle <= 0 then
|
||||
OSError;
|
||||
TIO.RedirectStdIn(PatchFileHandle);
|
||||
end;
|
||||
|
||||
class procedure TMain.Run;
|
||||
var
|
||||
Params: TParams;
|
||||
begin
|
||||
ExitCode := 0;
|
||||
Params := TParams.Create;
|
||||
try
|
||||
try
|
||||
Params.Parse;
|
||||
if Params.Help then
|
||||
DisplayHelp
|
||||
else if Params.Version then
|
||||
DisplayVersion
|
||||
else
|
||||
begin
|
||||
if (Params.PatchFileName <> '') and (Params.PatchFileName <> '-') then
|
||||
RedirectStdIn(Params.PatchFileName);
|
||||
TPatcher.Apply(Params.OldFileName, Params.NewFileName);
|
||||
end;
|
||||
finally
|
||||
Params.Free;
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
ExitCode := 1;
|
||||
TIO.WriteStrFmt(
|
||||
TIO.StdErr, '%0:s: %1:s'#13#10, [TAppInfo.ProgramFileName, E.Message]
|
||||
);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
|
||||
end.
|
115
contrib/bdiff/UBPatchParams.pas
Normal file
115
contrib/bdiff/UBPatchParams.pas
Normal file
@@ -0,0 +1,115 @@
|
||||
{
|
||||
* Implements a class that parses command lines and records parameters.
|
||||
}
|
||||
|
||||
|
||||
unit UBPatchParams;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBaseParams;
|
||||
|
||||
type
|
||||
|
||||
TParams = class(TBaseParams)
|
||||
private
|
||||
fOldFileName: string;
|
||||
fNewFileName: string;
|
||||
fPatchFileName: string;
|
||||
protected
|
||||
function ParseLongOption(const Option: string; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean; override;
|
||||
function ParseShortOption(const Options: string; const OptionIdx: Integer;
|
||||
var ParamIdx: Integer; var Terminated: Boolean): Boolean; override;
|
||||
procedure ParseFileName(const FileName: string); override;
|
||||
procedure Finalize; override;
|
||||
public
|
||||
constructor Create;
|
||||
property OldFileName: string read fOldFileName;
|
||||
property NewFileName: string read fNewFileName;
|
||||
property PatchFileName: string read fPatchFileName;
|
||||
property Help;
|
||||
property Version;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
StrUtils;
|
||||
|
||||
{ TParams }
|
||||
|
||||
constructor TParams.Create;
|
||||
begin
|
||||
inherited;
|
||||
fOldFileName := '';
|
||||
fNewFileName := '';
|
||||
fPatchFileName := '';
|
||||
end;
|
||||
|
||||
procedure TParams.Finalize;
|
||||
begin
|
||||
if fOldFileName = '' then
|
||||
Error('file name argument missing');
|
||||
if fNewFileName = '' then
|
||||
fNewFileName := fOldFileName;
|
||||
end;
|
||||
|
||||
procedure TParams.ParseFileName(const FileName: string);
|
||||
begin
|
||||
if fOldFileName = '' then
|
||||
fOldFileName := FileName
|
||||
else if fNewFileName = '' then
|
||||
fNewFileName := FileName
|
||||
else
|
||||
Error('too many file names on command line');
|
||||
end;
|
||||
|
||||
function TParams.ParseLongOption(const Option: string; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean;
|
||||
begin
|
||||
Result := inherited ParseLongOption(Option, ParamIdx, Terminated);
|
||||
if Result then
|
||||
Exit;
|
||||
Result := True;
|
||||
if Option = '--input' then
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
if ParamStr(ParamIdx) = '' then
|
||||
Error('missing argument to ''--input''');
|
||||
fPatchFileName := ParamStr(ParamIdx);
|
||||
end
|
||||
else if AnsiStartsStr('--input=', Option) then
|
||||
fPatchFileName := StripLeadingChars(Option, Length('--input='))
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TParams.ParseShortOption(const Options: string;
|
||||
const OptionIdx: Integer; var ParamIdx: Integer; var Terminated: Boolean):
|
||||
Boolean;
|
||||
begin
|
||||
Result := inherited ParseShortOption(
|
||||
Options, OptionIdx, ParamIdx, Terminated
|
||||
);
|
||||
if Result then
|
||||
Exit;
|
||||
Result := True;
|
||||
case Options[OptionIdx] of
|
||||
'i':
|
||||
begin
|
||||
Inc(ParamIdx);
|
||||
if ParamStr(ParamIdx) = '' then
|
||||
Error('missing argument to ''-i''');
|
||||
fPatchFileName := ParamStr(ParamIdx);
|
||||
end
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
81
contrib/bdiff/UBPatchUtils.pas
Normal file
81
contrib/bdiff/UBPatchUtils.pas
Normal file
@@ -0,0 +1,81 @@
|
||||
{
|
||||
* Contains utility functions used for BPatch. Includes Pascal implementations
|
||||
* of some standard C library code.
|
||||
}
|
||||
|
||||
|
||||
unit UBPatchUtils;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
uses
|
||||
// Project
|
||||
UUtils;
|
||||
|
||||
const
|
||||
// Value representing end of file (as returned from TIO.GetCh).
|
||||
EOF: Integer = -1;
|
||||
// seek flag used by TIO.Seek (other possible values not used in program).
|
||||
SEEK_SET = 0;
|
||||
|
||||
type
|
||||
TIO = class(TCommonIO)
|
||||
public
|
||||
{ Redirects standard input from a given file handle }
|
||||
class procedure RedirectStdIn(const Handle: Integer);
|
||||
{ Seeks to given offset from given origin in file specified by Handle.
|
||||
Returns True on success, false on failure. }
|
||||
class function Seek(Handle: Integer; Offset: Longint; Origin: Integer):
|
||||
Boolean;
|
||||
{ Checks if given file handle is at end of file. }
|
||||
class function AtEOF(Handle: Integer): Boolean;
|
||||
{ Gets a single ANSI character from file specified by Handle and returns it,
|
||||
or EOF. }
|
||||
class function GetCh(Handle: Integer): Integer;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils, Windows;
|
||||
|
||||
{ TIO }
|
||||
|
||||
class function TIO.AtEOF(Handle: Integer): Boolean;
|
||||
var
|
||||
CurPos: Integer;
|
||||
Size: Integer;
|
||||
begin
|
||||
CurPos := SysUtils.FileSeek(Handle, 0, 1);
|
||||
Size := Windows.GetFileSize(Handle, nil);
|
||||
Result := CurPos = Size;
|
||||
end;
|
||||
|
||||
class function TIO.GetCh(Handle: Integer): Integer;
|
||||
var
|
||||
Ch: AnsiChar;
|
||||
begin
|
||||
if AtEOF(Handle) then
|
||||
Result := EOF
|
||||
else
|
||||
begin
|
||||
SysUtils.FileRead(Handle, Ch, SizeOf(Ch));
|
||||
Result := Integer(Ch);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TIO.RedirectStdIn(const Handle: Integer);
|
||||
begin
|
||||
Windows.SetStdHandle(STD_INPUT_HANDLE, Cardinal(Handle));
|
||||
end;
|
||||
|
||||
class function TIO.Seek(Handle, Offset, Origin: Integer): Boolean;
|
||||
begin
|
||||
Result := SysUtils.FileSeek(Handle, Offset, Origin) >= 0;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
160
contrib/bdiff/UBaseParams.pas
Normal file
160
contrib/bdiff/UBaseParams.pas
Normal file
@@ -0,0 +1,160 @@
|
||||
{
|
||||
* Implements an abstract base class for classes that parse command lines.
|
||||
}
|
||||
|
||||
|
||||
unit UBaseParams;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils;
|
||||
|
||||
type
|
||||
|
||||
TBaseParams = class(TObject)
|
||||
private
|
||||
fHelp: Boolean;
|
||||
fVersion: Boolean;
|
||||
protected
|
||||
class function StripLeadingChars(const S: string; const Count: Integer):
|
||||
string;
|
||||
procedure Error(const Msg: string); overload;
|
||||
procedure Error(const Fmt: string; const Args: array of const); overload;
|
||||
function ParseLongOption(const Option: string; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean; virtual;
|
||||
function ParseShortOption(const Options: string; const OptionIdx: Integer;
|
||||
var ParamIdx: Integer; var Terminated: Boolean): Boolean; virtual;
|
||||
procedure ParseFileName(const FileName: string); virtual; abstract;
|
||||
procedure Finalize; virtual; abstract;
|
||||
public
|
||||
constructor Create;
|
||||
procedure Parse;
|
||||
property Help: Boolean read fHelp default False;
|
||||
property Version: Boolean read fVersion default False;
|
||||
end;
|
||||
|
||||
type
|
||||
EParams = class(Exception);
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
StrUtils,
|
||||
// Project
|
||||
UErrors;
|
||||
|
||||
{ TBaseParams }
|
||||
|
||||
procedure TBaseParams.Error(const Msg: string);
|
||||
begin
|
||||
raise EParams.Create(Msg);
|
||||
end;
|
||||
|
||||
constructor TBaseParams.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
fVersion := False;
|
||||
fHelp := False;
|
||||
end;
|
||||
|
||||
procedure TBaseParams.Error(const Fmt: string; const Args: array of const);
|
||||
begin
|
||||
raise EParams.CreateFmt(Fmt, Args);
|
||||
end;
|
||||
|
||||
procedure TBaseParams.Parse;
|
||||
var
|
||||
ParamIdx: Integer;
|
||||
CharIdx: Integer;
|
||||
Param: string;
|
||||
Terminated: Boolean;
|
||||
begin
|
||||
// Parse command line
|
||||
Terminated := False;
|
||||
ParamIdx := 1;
|
||||
while ParamIdx <= ParamCount do
|
||||
begin
|
||||
Param := ParamStr(ParamIdx);
|
||||
if AnsiStartsStr('-', Param) then
|
||||
begin
|
||||
if AnsiStartsStr('--', Param) then
|
||||
begin
|
||||
// long option
|
||||
if not ParseLongOption(Param, ParamIdx, Terminated) then
|
||||
Error('unknown option ''%s''', [Param]);
|
||||
if Terminated then
|
||||
Exit;
|
||||
end
|
||||
else
|
||||
begin
|
||||
// short options
|
||||
for CharIdx := 2 to Length(Param) do
|
||||
begin
|
||||
if not ParseShortOption(Param, CharIdx, ParamIdx, Terminated) then
|
||||
Error('unknown option ''-%s''', [Param[CharIdx]]);
|
||||
if Terminated then
|
||||
Exit;
|
||||
end;
|
||||
end;
|
||||
end
|
||||
else
|
||||
ParseFileName(Param);
|
||||
Inc(ParamIdx);
|
||||
end;
|
||||
Finalize;
|
||||
end;
|
||||
|
||||
function TBaseParams.ParseLongOption(const Option: string;
|
||||
var ParamIdx: Integer; var Terminated: Boolean): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
if Option = '--help' then
|
||||
begin
|
||||
fHelp := True;
|
||||
Terminated := True;
|
||||
end
|
||||
else if Option = '--version' then
|
||||
begin
|
||||
fVersion := True;
|
||||
Terminated := True;
|
||||
end
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
|
||||
function TBaseParams.ParseShortOption(const Options: string;
|
||||
const OptionIdx: Integer; var ParamIdx: Integer;
|
||||
var Terminated: Boolean): Boolean;
|
||||
begin
|
||||
Result := True;
|
||||
case Options[OptionIdx] of
|
||||
'h':
|
||||
if OptionIdx = Length(Options) then
|
||||
begin
|
||||
fHelp := True;
|
||||
Terminated := True;
|
||||
end;
|
||||
'v':
|
||||
if OptionIdx = Length(Options) then
|
||||
begin
|
||||
fVersion := True;
|
||||
Terminated := True;
|
||||
end;
|
||||
else
|
||||
Result := False;
|
||||
end;
|
||||
end;
|
||||
|
||||
class function TBaseParams.StripLeadingChars(const S: string;
|
||||
const Count: Integer): string;
|
||||
begin
|
||||
if Count > 0 then
|
||||
Result := AnsiRightStr(S, Length(S) - Count)
|
||||
else
|
||||
Result := S;
|
||||
end;
|
||||
|
||||
end.
|
153
contrib/bdiff/UBlockSort.pas
Normal file
153
contrib/bdiff/UBlockSort.pas
Normal file
@@ -0,0 +1,153 @@
|
||||
{
|
||||
* Implements block sort.
|
||||
*
|
||||
* Based on parts of blksort.c by Stefan Reuther, copyright (c) 1999 Stefan
|
||||
* Reuther <Streu@gmx.de>.
|
||||
}
|
||||
|
||||
|
||||
unit UBlockSort;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBDiffTypes;
|
||||
|
||||
|
||||
type
|
||||
TBlockSort = class(TObject)
|
||||
private
|
||||
class function Compare(A: Cardinal; B: Cardinal; Data: PSignedAnsiCharArray;
|
||||
DataSize: Cardinal): Integer;
|
||||
{ The 'sink element' part of heapsort }
|
||||
class procedure Sink(Left: Cardinal; Right: Cardinal; Block: PBlock;
|
||||
Data: PSignedAnsiCharArray; DataSize: Cardinal);
|
||||
public
|
||||
{ Returns array of offsets into data, sorted by position.
|
||||
@param Data [in] Data to be sorted. Must not be nil.
|
||||
@param DataSize [in] Size of data to be sorted, must be > 0.
|
||||
@return Pointer to block of sorted indices into Data. Caller must free.
|
||||
@except raises EOutOfMemory if can't allocate sorted data block.
|
||||
}
|
||||
class function Execute(Data: PSignedAnsiCharArray; DataSize: Cardinal):
|
||||
PBlock;
|
||||
end;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
{
|
||||
GENERAL IMPLEMENTATION NOTE (Stefan Reuther)
|
||||
|
||||
Block-sort part of bdiff:
|
||||
|
||||
Taking the data area of length N, we generate N substrings:
|
||||
- first substring is data area, length N
|
||||
- 2nd is data area sans first character, length N-1
|
||||
- ith is data area sans first i-1 characters, length N-i+1
|
||||
- Nth is last character of data area, length 1
|
||||
|
||||
These strings are sorted to allow fast (i.e., binary) searching in data
|
||||
area. Of course, we don't really generate these N*N/2 bytes of strings: we
|
||||
use an array of N size_t's indexing the data.
|
||||
|
||||
PASCAL IMPLEMENTATION NOTE (Peter Johnson)
|
||||
|
||||
The fact that C's (ansi) Char type is signed and Pascal's is unsigned is
|
||||
relevant to the string sorting and accessing code described above. Thefore
|
||||
we use a specially defined SignedAnsiChar to maintain the data buffer to
|
||||
ensure that the the Pascal performs in the same way as the C code.
|
||||
}
|
||||
|
||||
|
||||
{ TBlockSort }
|
||||
|
||||
class function TBlockSort.Compare(A, B: Cardinal;
|
||||
Data: PSignedAnsiCharArray; DataSize: Cardinal): Integer;
|
||||
var
|
||||
PA: PSignedAnsiChar;
|
||||
PB: PSignedAnsiChar;
|
||||
Len: Cardinal;
|
||||
begin
|
||||
PA := @Data[A];
|
||||
PB := @Data[B];
|
||||
Len := DataSize - A;
|
||||
if DataSize - B < Len then
|
||||
Len := DataSize - B;
|
||||
while (Len <> 0) and (PA^ = PB^) do
|
||||
begin
|
||||
Inc(PA);
|
||||
Inc(PB);
|
||||
Dec(Len);
|
||||
end;
|
||||
if Len = 0 then
|
||||
begin
|
||||
Result := A - B;
|
||||
Exit;
|
||||
end;
|
||||
Result := PA^ - PB^;
|
||||
end;
|
||||
|
||||
class function TBlockSort.Execute(Data: PSignedAnsiCharArray;
|
||||
DataSize: Cardinal): PBlock;
|
||||
var
|
||||
I, Temp, Left, Right: Cardinal;
|
||||
begin
|
||||
if DataSize = 0 then
|
||||
begin
|
||||
Result := nil;
|
||||
Exit;
|
||||
end;
|
||||
|
||||
GetMem(Result, SizeOf(Cardinal) * DataSize);
|
||||
|
||||
// initialize unsorted data
|
||||
for I := 0 to Pred(DataSize) do
|
||||
Result[I] := I;
|
||||
|
||||
// heapsort
|
||||
Left := DataSize div 2;
|
||||
Right := DataSize;
|
||||
while Left > 0 do
|
||||
begin
|
||||
Dec(Left);
|
||||
Sink(Left, Right, Result, Data, DataSize);
|
||||
end;
|
||||
while Right > 0 do
|
||||
begin
|
||||
Temp := Result[Left];
|
||||
Result[Left] := Result[Right-1];
|
||||
Result[Right-1] := Temp;
|
||||
Dec(Right);
|
||||
Sink(Left, Right, Result, Data, DataSize);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TBlockSort.Sink(Left, Right: Cardinal; Block: PBlock;
|
||||
Data: PSignedAnsiCharArray; DataSize: Cardinal);
|
||||
var
|
||||
I, J, X: Cardinal;
|
||||
begin
|
||||
I := Left;
|
||||
X := Block[I];
|
||||
while True do
|
||||
begin
|
||||
J := 2 * I + 1;
|
||||
if J >= Right then
|
||||
Break;
|
||||
if J < Right - 1 then
|
||||
if Compare(Block[J], Block[J+1], Data, DataSize) < 0 then
|
||||
Inc(J);
|
||||
if Compare(X, Block[J], Data, DataSize) > 0 then
|
||||
Break;
|
||||
Block[I] := Block[J];
|
||||
I := J;
|
||||
end;
|
||||
Block[I] := X;
|
||||
end;
|
||||
|
||||
end.
|
||||
|
304
contrib/bdiff/UDiffer.pas
Normal file
304
contrib/bdiff/UDiffer.pas
Normal file
@@ -0,0 +1,304 @@
|
||||
{
|
||||
* Class that generates a diff for two files, logging progress as required.
|
||||
*
|
||||
* Based on bdiff.c and part of blksort.c by Stefan Reuther, copyright (c) 1999
|
||||
* Stefan Reuther <Streu@gmx.de>.
|
||||
}
|
||||
|
||||
unit UDiffer;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
UBDiffTypes, UFileData, ULogger;
|
||||
|
||||
{ Structure for a matching block }
|
||||
type
|
||||
TMatch = record
|
||||
OldOffset: Cardinal;
|
||||
NewOffset: Cardinal;
|
||||
BlockLength: Cardinal;
|
||||
end;
|
||||
|
||||
PMatch = ^TMatch;
|
||||
|
||||
type
|
||||
TDiffer = class(TObject)
|
||||
private
|
||||
fMinMatchLength: Cardinal;
|
||||
fFormat: TFormat;
|
||||
function FindMaxMatch(OldFile: TFileData; SortedOldData: PBlock;
|
||||
SearchText: PSignedAnsiChar; SearchTextLength: Cardinal): TMatch;
|
||||
/// <summary>Finds maximum length "sub-string" of CompareData that is in
|
||||
/// Data.</summary>
|
||||
/// <param name="Data">PSignedAnsiCharArray [in] Data to be searched for
|
||||
/// "sub-string".</param>
|
||||
/// <param name="Block">PBlock [in] Block of indexes into Data that sort
|
||||
/// sub-strings of Data.</param>
|
||||
/// <param name="DataSize">Cardinal [in] Size of Data.</param>
|
||||
/// <param name="CompareData">PSignedAnsiChar [in] Pointer to data to be
|
||||
/// compared to Data.</param>
|
||||
/// <param name="CompareDataSize">Cardinal [in] Size of data pointed to by
|
||||
/// CompareData.</param>
|
||||
/// <param name="FoundPos">Cardinal [out] Position in Data where
|
||||
/// "sub-string" was found.</param>
|
||||
/// <returns>Cardinal. Length of found "sub-string".</returns>
|
||||
function FindString(Data: PSignedAnsiCharArray; Block: PBlock;
|
||||
DataSize: Cardinal; CompareData: PSignedAnsiChar;
|
||||
CompareDataSize: Cardinal; out FoundPos: Cardinal): Cardinal;
|
||||
public
|
||||
constructor Create;
|
||||
destructor Destroy; override;
|
||||
procedure MakeDiff(const OldFileName, NewFileName: string;
|
||||
const Logger: TLogger); overload;
|
||||
procedure MakeDiff(OldData, NewData, DiffData: Pointer;
|
||||
OldSize, NewSize: Integer; var DiffSize: Integer;
|
||||
const Logger: TLogger); overload;
|
||||
property MinMatchLength: Cardinal read fMinMatchLength write fMinMatchLength
|
||||
default 24;
|
||||
property Format: TFormat read fFormat write fFormat default FMT_QUOTED;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{$IOCHECKS OFF}
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBlockSort, UErrors, UPatchWriters;
|
||||
|
||||
{ TDiffer }
|
||||
|
||||
constructor TDiffer.Create;
|
||||
begin
|
||||
inherited Create;
|
||||
fMinMatchLength := 24; // default minimum match length
|
||||
fFormat := FMT_QUOTED; // default output format
|
||||
end;
|
||||
|
||||
destructor TDiffer.Destroy;
|
||||
begin
|
||||
inherited;
|
||||
end;
|
||||
|
||||
function TDiffer.FindMaxMatch(OldFile: TFileData; SortedOldData: PBlock;
|
||||
SearchText: PSignedAnsiChar; SearchTextLength: Cardinal): TMatch;
|
||||
var
|
||||
FoundPos: Cardinal;
|
||||
FoundLen: Cardinal;
|
||||
begin
|
||||
Result.BlockLength := 0; { no match }
|
||||
Result.NewOffset := 0;
|
||||
while (SearchTextLength <> 0) do
|
||||
begin
|
||||
FoundLen := FindString(OldFile.Data, SortedOldData, OldFile.Size,
|
||||
SearchText, SearchTextLength, FoundPos);
|
||||
if FoundLen >= fMinMatchLength then
|
||||
begin
|
||||
Result.OldOffset := FoundPos;
|
||||
Result.BlockLength := FoundLen;
|
||||
Exit;
|
||||
end;
|
||||
Inc(SearchText);
|
||||
Inc(Result.NewOffset);
|
||||
Dec(SearchTextLength);
|
||||
end;
|
||||
end;
|
||||
|
||||
function TDiffer.FindString(Data: PSignedAnsiCharArray; Block: PBlock;
|
||||
DataSize: Cardinal; CompareData: PSignedAnsiChar; CompareDataSize: Cardinal;
|
||||
out FoundPos: Cardinal): Cardinal;
|
||||
var
|
||||
First: Cardinal; // first position in Data to search
|
||||
Last: Cardinal; // last position in Data to search
|
||||
Mid: Cardinal; // mid point of Data to search
|
||||
FoundSize: Cardinal; // size of matching "sub-string"
|
||||
FoundMax: Cardinal; // maximum size of matching "sub-string"
|
||||
PData: PSignedAnsiChar; // ptr to char in Data to be compared
|
||||
PCompareData: PSignedAnsiChar; // ptr to char in CompareData to be compared
|
||||
begin
|
||||
First := 0;
|
||||
Last := DataSize - 1;
|
||||
Result := 0;
|
||||
FoundPos := 0;
|
||||
|
||||
// Do binary search of Data
|
||||
while First <= Last do
|
||||
begin
|
||||
// Get mid point of (sorted) Data to search
|
||||
Mid := (First + Last) div 2;
|
||||
// Set pointer to start of Data search string
|
||||
PData := @Data[Block[Mid]];
|
||||
// Set pointer to start of CompareData
|
||||
PCompareData := CompareData;
|
||||
// Calculate maximum possible size of matching substring
|
||||
FoundMax := DataSize - Block[Mid];
|
||||
if FoundMax > CompareDataSize then
|
||||
FoundMax := CompareDataSize;
|
||||
// Find and count match chars from Data and CompareData
|
||||
FoundSize := 0;
|
||||
while (FoundSize < FoundMax) and (PData^ = PCompareData^) do
|
||||
begin
|
||||
Inc(FoundSize);
|
||||
Inc(PData);
|
||||
Inc(PCompareData);
|
||||
end;
|
||||
|
||||
// We found a "match" of length FoundSize, position Block[Mid]
|
||||
if FoundSize > Result then
|
||||
begin
|
||||
Result := FoundSize;
|
||||
FoundPos := Block[Mid];
|
||||
end;
|
||||
|
||||
// Determine next search area
|
||||
// Note: If FoundSize = FoundMatch then substrings match
|
||||
if (FoundSize = FoundMax) or (PData^ < PCompareData^) then
|
||||
// substring <= current data string: search above
|
||||
First := Mid + 1
|
||||
else
|
||||
// substring < current data string: search below
|
||||
begin
|
||||
Last := Mid;
|
||||
if Last <> 0 then
|
||||
Dec(Last)
|
||||
else
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDiffer.MakeDiff(const OldFileName, NewFileName: string;
|
||||
const Logger: TLogger);
|
||||
var
|
||||
OldFile: TFileData;
|
||||
NewFile: TFileData;
|
||||
NewOffset: Cardinal;
|
||||
ToDo: Cardinal;
|
||||
SortedOldData: PBlock;
|
||||
Match: TMatch;
|
||||
PatchWriter: TPatchWriter;
|
||||
begin
|
||||
{ initialize }
|
||||
OldFile := nil;
|
||||
NewFile := nil;
|
||||
SortedOldData := nil;
|
||||
PatchWriter := TPatchWriterFactory.Instance(fFormat);
|
||||
try
|
||||
Logger.Log('loading old file');
|
||||
OldFile := TFileData.Create(OldFileName);
|
||||
Logger.Log('loading new file');
|
||||
NewFile := TFileData.Create(NewFileName);
|
||||
Logger.Log('block sorting old file');
|
||||
SortedOldData := TBlockSort.Execute(OldFile.Data, OldFile.Size);
|
||||
if not Assigned(SortedOldData) then
|
||||
Error('virtual memory exhausted');
|
||||
Logger.Log('generating patch');
|
||||
PatchWriter.Header(OldFile.Name, NewFile.Name, OldFile.Size, NewFile.Size);
|
||||
{ main loop }
|
||||
ToDo := NewFile.Size;
|
||||
NewOffset := 0;
|
||||
while (ToDo <> 0) do
|
||||
begin
|
||||
Match := FindMaxMatch(OldFile, SortedOldData,
|
||||
@NewFile.Data[NewOffset], ToDo);
|
||||
if Match.BlockLength <> 0 then
|
||||
begin
|
||||
{ found a match }
|
||||
if Match.NewOffset <> 0 then
|
||||
{ preceded by a "copy" block }
|
||||
PatchWriter.Add(@NewFile.Data[NewOffset], Match.NewOffset);
|
||||
Inc(NewOffset, Match.NewOffset);
|
||||
Dec(ToDo, Match.NewOffset);
|
||||
PatchWriter.Copy(NewFile.Data, NewOffset, Match.OldOffset,
|
||||
Match.BlockLength);
|
||||
Inc(NewOffset, Match.BlockLength);
|
||||
Dec(ToDo, Match.BlockLength);
|
||||
end
|
||||
else
|
||||
begin
|
||||
PatchWriter.Add(@NewFile.Data[NewOffset], ToDo);
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
Logger.Log('done');
|
||||
finally
|
||||
// finally section new to v1.1
|
||||
if Assigned(SortedOldData) then
|
||||
FreeMem(SortedOldData);
|
||||
OldFile.Free;
|
||||
NewFile.Free;
|
||||
PatchWriter.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TDiffer.MakeDiff(OldData, NewData, DiffData: Pointer;
|
||||
OldSize, NewSize: Integer; var DiffSize: Integer; const Logger: TLogger);
|
||||
var
|
||||
OldFile: TFileData;
|
||||
NewFile: TFileData;
|
||||
NewOffset: Cardinal;
|
||||
ToDo: Cardinal;
|
||||
SortedOldData: PBlock;
|
||||
Match: TMatch;
|
||||
PatchWriter: TPatchWriter;
|
||||
begin
|
||||
{ initialize }
|
||||
DiffSize := 0;
|
||||
OldFile := nil;
|
||||
NewFile := nil;
|
||||
SortedOldData := nil;
|
||||
PatchWriter := TPatchWriterFactory.Instance(fFormat);
|
||||
PatchWriter.Memory := DiffData;
|
||||
PatchWriter.Size := 0;
|
||||
PatchWriter.WriteToMemory := True;
|
||||
try
|
||||
Logger.Log('loading old file');
|
||||
OldFile := TFileData.Create(OldData, OldSize);
|
||||
Logger.Log('loading new file');
|
||||
NewFile := TFileData.Create(NewData, NewSize);
|
||||
Logger.Log('block sorting old file');
|
||||
SortedOldData := TBlockSort.Execute(OldFile.Data, OldFile.Size);
|
||||
if not Assigned(SortedOldData) then
|
||||
Error('virtual memory exhausted');
|
||||
Logger.Log('generating patch');
|
||||
PatchWriter.Header(OldFile.Name, NewFile.Name, OldFile.Size, NewFile.Size);
|
||||
{ main loop }
|
||||
ToDo := NewFile.Size;
|
||||
NewOffset := 0;
|
||||
while (ToDo <> 0) do
|
||||
begin
|
||||
Match := FindMaxMatch(OldFile, SortedOldData,
|
||||
@NewFile.Data[NewOffset], ToDo);
|
||||
if Match.BlockLength <> 0 then
|
||||
begin
|
||||
{ found a match }
|
||||
if Match.NewOffset <> 0 then
|
||||
{ preceded by a "copy" block }
|
||||
PatchWriter.Add(@NewFile.Data[NewOffset], Match.NewOffset);
|
||||
Inc(NewOffset, Match.NewOffset);
|
||||
Dec(ToDo, Match.NewOffset);
|
||||
PatchWriter.Copy(NewFile.Data, NewOffset, Match.OldOffset,
|
||||
Match.BlockLength);
|
||||
Inc(NewOffset, Match.BlockLength);
|
||||
Dec(ToDo, Match.BlockLength);
|
||||
end
|
||||
else
|
||||
begin
|
||||
PatchWriter.Add(@NewFile.Data[NewOffset], ToDo);
|
||||
Break;
|
||||
end;
|
||||
end;
|
||||
Logger.Log('done');
|
||||
DiffSize := PatchWriter.Size;
|
||||
finally
|
||||
// finally section new to v1.1
|
||||
if Assigned(SortedOldData) then
|
||||
FreeMem(SortedOldData);
|
||||
OldFile.Free;
|
||||
NewFile.Free;
|
||||
PatchWriter.Free;
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
58
contrib/bdiff/UErrors.pas
Normal file
58
contrib/bdiff/UErrors.pas
Normal file
@@ -0,0 +1,58 @@
|
||||
{
|
||||
* Helper routines to generate exceptions.
|
||||
* Common code used by both BDiff and BPatch.
|
||||
}
|
||||
|
||||
|
||||
unit UErrors;
|
||||
|
||||
|
||||
interface
|
||||
|
||||
|
||||
{ Raises an exception with given message }
|
||||
procedure Error(const Msg: string); overload;
|
||||
|
||||
{ Raises an exception with message created from format string and values }
|
||||
procedure Error(const Fmt: string; const Args: array of const); overload;
|
||||
|
||||
{ Raises exception determined by last operating system error }
|
||||
procedure OSError;
|
||||
|
||||
|
||||
implementation
|
||||
|
||||
|
||||
uses
|
||||
// Project
|
||||
Sysutils;
|
||||
|
||||
|
||||
{ Raises an exception with given message }
|
||||
procedure Error(const Msg: string);
|
||||
begin
|
||||
raise Exception.Create(Msg);
|
||||
end;
|
||||
|
||||
{ Raises an exception with message created from format string and values }
|
||||
procedure Error(const Fmt: string; const Args: array of const);
|
||||
begin
|
||||
raise Exception.CreateFmt(Fmt, Args);
|
||||
end;
|
||||
|
||||
{ Raises exception determined by last operating system error }
|
||||
procedure OSError;
|
||||
var
|
||||
LastError: Integer;
|
||||
Err: EOSError;
|
||||
begin
|
||||
LastError := GetLastError;
|
||||
if LastError <> 0 then
|
||||
Err := EOSError.Create(SysErrorMessage(LastError))
|
||||
else
|
||||
Err := EOSError.Create('Unknown operating system error');
|
||||
Err.ErrorCode := LastError;
|
||||
raise Err;
|
||||
end;
|
||||
|
||||
end.
|
95
contrib/bdiff/UFileData.pas
Normal file
95
contrib/bdiff/UFileData.pas
Normal file
@@ -0,0 +1,95 @@
|
||||
{
|
||||
* Implements class that reads a file and provides access to its data.
|
||||
}
|
||||
|
||||
unit UFileData;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBDiffTypes;
|
||||
|
||||
type
|
||||
|
||||
TFileData = class(TObject)
|
||||
private
|
||||
fData: PSignedAnsiCharArray;
|
||||
fSize: Cardinal;
|
||||
fName: string;
|
||||
procedure LoadFile;
|
||||
public
|
||||
constructor Create(const FileName: string); overload;
|
||||
constructor Create(Memory: Pointer; Size: Integer); overload;
|
||||
destructor Destroy; override;
|
||||
property Name: string read fName;
|
||||
property Size: Cardinal read fSize;
|
||||
property Data: PSignedAnsiCharArray read fData;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils, Windows,
|
||||
// Project
|
||||
UErrors;
|
||||
|
||||
{ TFileData }
|
||||
|
||||
constructor TFileData.Create(const FileName: string);
|
||||
begin
|
||||
inherited Create;
|
||||
fName := FileName;
|
||||
LoadFile;
|
||||
end;
|
||||
|
||||
constructor TFileData.Create(Memory: Pointer; Size: Integer);
|
||||
begin
|
||||
inherited Create;
|
||||
fName := '';
|
||||
fData := Memory;
|
||||
fSize := Size;
|
||||
end;
|
||||
|
||||
destructor TFileData.Destroy;
|
||||
begin
|
||||
if fName <> '' then
|
||||
if Assigned(fData) then
|
||||
FreeMem(fData);
|
||||
inherited;
|
||||
end;
|
||||
|
||||
procedure TFileData.LoadFile;
|
||||
var
|
||||
FileHandle: Integer;
|
||||
BytesRead: Integer;
|
||||
begin
|
||||
FileHandle := FileOpen(fName, fmOpenRead or fmShareDenyWrite);
|
||||
try
|
||||
if FileHandle = -1 then
|
||||
Error('Cannot open file %s', [fName]);
|
||||
fSize := GetFileSize(FileHandle, nil);
|
||||
if fSize = Cardinal(-1) then
|
||||
Error('Cannot find size of file %s - may be to large', [fName]);
|
||||
if fSize = 0 then
|
||||
Error('File %s is empty', [fName]);
|
||||
try
|
||||
GetMem(fData, fSize);
|
||||
BytesRead := FileRead(FileHandle, fData^, fSize);
|
||||
if BytesRead = -1 then
|
||||
Error('Cannot read from file %s', [fName]);
|
||||
if fSize <> Cardinal(BytesRead) then
|
||||
Error('Error reading from file %s', [fName]);
|
||||
except
|
||||
if Assigned(fData) then
|
||||
FreeMem(fData, fSize);
|
||||
raise;
|
||||
end;
|
||||
finally
|
||||
if FileHandle <> -1 then
|
||||
FileClose(FileHandle);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
45
contrib/bdiff/UInfoWriter.pas
Normal file
45
contrib/bdiff/UInfoWriter.pas
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
* Abstract base class for classes that emit version information and help
|
||||
* screens on standard output.
|
||||
}
|
||||
|
||||
|
||||
unit UInfoWriter;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TInfoWriter = class(TObject)
|
||||
protected
|
||||
class function HelpText: string; virtual; abstract;
|
||||
public
|
||||
class procedure VersionInfo;
|
||||
class procedure HelpScreen;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
UAppInfo, UUtils;
|
||||
|
||||
|
||||
{ TInfoWriter }
|
||||
|
||||
class procedure TInfoWriter.HelpScreen;
|
||||
begin
|
||||
TCommonIO.WriteStr(TCommonIO.StdOut, HelpText);
|
||||
end;
|
||||
|
||||
class procedure TInfoWriter.VersionInfo;
|
||||
begin
|
||||
// NOTE: original code displayed compile date using C's __DATE__ macro. Since
|
||||
// there is no Pascal equivalent of __DATE__ we display update date of program
|
||||
// file instead
|
||||
TCommonIO.WriteStrFmt(
|
||||
TCommonIO.StdOut,
|
||||
'%s-%s %s '#13#10,
|
||||
[TAppInfo.ProgramBaseName, TAppInfo.ProgramVersion, TAppInfo.ProgramExeDate]
|
||||
);
|
||||
end;
|
||||
|
||||
end.
|
64
contrib/bdiff/ULogger.pas
Normal file
64
contrib/bdiff/ULogger.pas
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
* Classes used to log messages plus a factory class. One logger class logs to
|
||||
* standard error while the second does nothing.
|
||||
}
|
||||
|
||||
|
||||
unit ULogger;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TLogger = class(TObject)
|
||||
public
|
||||
procedure Log(const Msg: string); virtual; abstract;
|
||||
end;
|
||||
|
||||
type
|
||||
TLoggerFactory = class(TObject)
|
||||
public
|
||||
class function Instance(Verbose: Boolean): TLogger;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
UAppInfo, UBDiffUtils;
|
||||
|
||||
type
|
||||
TVerboseLogger = class(TLogger)
|
||||
public
|
||||
procedure Log(const Msg: string); override;
|
||||
end;
|
||||
|
||||
type
|
||||
TSilentLogger = class(TLogger)
|
||||
public
|
||||
procedure Log(const Msg: string); override;
|
||||
end;
|
||||
|
||||
{ TVerboseLogger }
|
||||
|
||||
procedure TVerboseLogger.Log(const Msg: string);
|
||||
begin
|
||||
TIO.WriteStrFmt(TIO.StdErr, '%s: %s'#13#10, [TAppInfo.ProgramFileName, Msg]);
|
||||
end;
|
||||
|
||||
{ TSilentLogger }
|
||||
|
||||
procedure TSilentLogger.Log(const Msg: string);
|
||||
begin
|
||||
// Do nothing: no output required
|
||||
end;
|
||||
|
||||
{ TLoggerFactory }
|
||||
|
||||
class function TLoggerFactory.Instance(Verbose: Boolean): TLogger;
|
||||
begin
|
||||
if Verbose then
|
||||
Result := TVerboseLogger.Create
|
||||
else
|
||||
Result := TSilentLogger.Create;
|
||||
end;
|
||||
|
||||
end.
|
299
contrib/bdiff/UPatchWriters.pas
Normal file
299
contrib/bdiff/UPatchWriters.pas
Normal file
@@ -0,0 +1,299 @@
|
||||
{
|
||||
* Heirachy of classes used to write various types of patch, along with factory
|
||||
* class.
|
||||
*
|
||||
* Patch generation code based on portions of bdiff.c by Stefan Reuther,
|
||||
* copyright (c) 1999 Stefan Reuther <Streu@gmx.de>.
|
||||
}
|
||||
|
||||
unit UPatchWriters;
|
||||
|
||||
interface
|
||||
|
||||
uses
|
||||
// Project
|
||||
UBDiffTypes;
|
||||
|
||||
type
|
||||
|
||||
TPatchWriter = class(TObject)
|
||||
private
|
||||
FWriteToMemory: Boolean;
|
||||
public
|
||||
Memory: Pointer;
|
||||
Size: Integer;
|
||||
procedure Header(const OldFileName, NewFileName: string;
|
||||
const OldFileSize, NewFileSize: Cardinal); virtual; abstract;
|
||||
procedure Add(Data: PSignedAnsiChar; Length: Cardinal); virtual; abstract;
|
||||
procedure Copy(NewBuf: PSignedAnsiCharArray; NewPos: Cardinal;
|
||||
OldPos: Cardinal; Length: Cardinal); virtual; abstract;
|
||||
property WriteToMemory: Boolean read FWriteToMemory write FWriteToMemory
|
||||
default false;
|
||||
end;
|
||||
|
||||
TPatchWriterFactory = class(TObject)
|
||||
public
|
||||
class function Instance(const Format: TFormat): TPatchWriter;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils,
|
||||
// Project
|
||||
UBDiffUtils;
|
||||
|
||||
type
|
||||
TBinaryPatchWriter = class(TPatchWriter)
|
||||
private
|
||||
procedure PackLong(P: PSignedAnsiChar; L: Longint);
|
||||
function CheckSum(Data: PSignedAnsiChar; Length: Cardinal): Longint;
|
||||
public
|
||||
procedure Header(const OldFileName, NewFileName: string;
|
||||
const OldFileSize, NewFileSize: Cardinal); override;
|
||||
procedure Add(Data: PSignedAnsiChar; Length: Cardinal); override;
|
||||
procedure Copy(NewBuf: PSignedAnsiCharArray; NewPos: Cardinal;
|
||||
OldPos: Cardinal; Length: Cardinal); override;
|
||||
end;
|
||||
|
||||
TTextPatchWriter = class(TPatchWriter)
|
||||
protected
|
||||
{ Checks if an ANSI character is a printable ASCII character. }
|
||||
class function IsPrint(const Ch: AnsiChar): Boolean;
|
||||
procedure CopyHeader(NewPos: Cardinal; OldPos: Cardinal; Length: Cardinal);
|
||||
procedure Header(const OldFileName, NewFileName: string;
|
||||
const OldFileSize, NewFileSize: Cardinal); override;
|
||||
end;
|
||||
|
||||
TQuotedPatchWriter = class(TTextPatchWriter)
|
||||
private
|
||||
procedure QuotedData(Data: PSignedAnsiChar; Length: Cardinal);
|
||||
{ Returns octal representation of given value as a 3 digit string. }
|
||||
class function ByteToOct(const Value: Byte): string;
|
||||
public
|
||||
procedure Add(Data: PSignedAnsiChar; Length: Cardinal); override;
|
||||
procedure Copy(NewBuf: PSignedAnsiCharArray; NewPos: Cardinal;
|
||||
OldPos: Cardinal; Length: Cardinal); override;
|
||||
end;
|
||||
|
||||
TFilteredPatchWriter = class(TTextPatchWriter)
|
||||
private
|
||||
procedure FilteredData(Data: PSignedAnsiChar; Length: Cardinal);
|
||||
public
|
||||
procedure Add(Data: PSignedAnsiChar; Length: Cardinal); override;
|
||||
procedure Copy(NewBuf: PSignedAnsiCharArray; NewPos: Cardinal;
|
||||
OldPos: Cardinal; Length: Cardinal); override;
|
||||
end;
|
||||
|
||||
{ TPatchWriterFactory }
|
||||
|
||||
class function TPatchWriterFactory.Instance(const Format: TFormat)
|
||||
: TPatchWriter;
|
||||
begin
|
||||
case Format of
|
||||
FMT_BINARY:
|
||||
Result := TBinaryPatchWriter.Create;
|
||||
FMT_FILTERED:
|
||||
Result := TFilteredPatchWriter.Create;
|
||||
FMT_QUOTED:
|
||||
Result := TQuotedPatchWriter.Create;
|
||||
else
|
||||
raise Exception.Create('Invalid format type');
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TBinaryPatchWriter }
|
||||
|
||||
procedure TBinaryPatchWriter.Add(Data: PSignedAnsiChar; Length: Cardinal);
|
||||
var
|
||||
Rec: packed record DataLength: array [0 .. 3] of SignedAnsiChar;
|
||||
// length of added adata
|
||||
end;
|
||||
|
||||
const
|
||||
cPlusSign: AnsiChar = '+'; // flags added data
|
||||
begin
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, cPlusSign, FWriteToMemory, Memory, Size));
|
||||
PackLong(@Rec.DataLength, Length);
|
||||
Inc(Size, TIO.WriteRaw(TIO.StdOut, @Rec, SizeOf(Rec), FWriteToMemory,
|
||||
Memory, Size));
|
||||
Inc(Size, TIO.WriteRaw(TIO.StdOut, Data, Length, FWriteToMemory,
|
||||
Memory, Size));
|
||||
// data added
|
||||
end;
|
||||
|
||||
{ Compute simple checksum }
|
||||
function TBinaryPatchWriter.CheckSum(Data: PSignedAnsiChar;
|
||||
Length: Cardinal): Longint;
|
||||
begin
|
||||
Result := 0;
|
||||
while Length <> 0 do
|
||||
begin
|
||||
Dec(Length);
|
||||
Result := ((Result shr 30) and 3) or (Result shl 2);
|
||||
Result := Result xor Ord(Data^);
|
||||
Inc(Data);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TBinaryPatchWriter.Copy(NewBuf: PSignedAnsiCharArray;
|
||||
NewPos, OldPos, Length: Cardinal);
|
||||
var
|
||||
Rec: packed record CopyStart: array [0 .. 3] of SignedAnsiChar;
|
||||
// starting pos of copied data
|
||||
CopyLength: array [0 .. 3] of SignedAnsiChar; // length copied data
|
||||
CheckSum: array [0 .. 3] of SignedAnsiChar; // validates copied data
|
||||
end;
|
||||
|
||||
const
|
||||
cAtSign: AnsiChar = '@'; // flags command data in both file
|
||||
begin
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, cAtSign, FWriteToMemory, Memory, Size));
|
||||
PackLong(@Rec.CopyStart, OldPos);
|
||||
PackLong(@Rec.CopyLength, Length);
|
||||
PackLong(@Rec.CheckSum, CheckSum(@NewBuf[NewPos], Length));
|
||||
Inc(Size, TIO.WriteRaw(TIO.StdOut, @Rec, SizeOf(Rec), FWriteToMemory,
|
||||
Memory, Size));
|
||||
end;
|
||||
|
||||
procedure TBinaryPatchWriter.Header(const OldFileName, NewFileName: string;
|
||||
const OldFileSize, NewFileSize: Cardinal);
|
||||
var
|
||||
Head: packed record Signature: array [0 .. 7] of SignedAnsiChar;
|
||||
// file signature
|
||||
OldDataSize: array [0 .. 3] of SignedAnsiChar; // size of old data file
|
||||
NewDataSize: array [0 .. 3] of SignedAnsiChar; // size of new data file
|
||||
end;
|
||||
|
||||
const
|
||||
// File signature. Must be 8 bytes. Format is 'bdiff' + file-version + #$1A
|
||||
// where file-version is a two char string, here '02'.
|
||||
// If file format is changed then increment the file version
|
||||
cFileSignature: array [0 .. 7] of AnsiChar = 'bdiff02'#$1A;
|
||||
begin
|
||||
Assert(Length(cFileSignature) = 8);
|
||||
Move(cFileSignature, Head.Signature[0], Length(cFileSignature));
|
||||
PackLong(@Head.OldDataSize, OldFileSize);
|
||||
PackLong(@Head.NewDataSize, NewFileSize);
|
||||
Inc(Size, TIO.WriteRaw(TIO.StdOut, @Head, SizeOf(Head), FWriteToMemory,
|
||||
Memory, Size));
|
||||
end;
|
||||
|
||||
{ Pack long in little-endian format to P }
|
||||
{ NOTE: P must point to a block of at least 4 bytes }
|
||||
procedure TBinaryPatchWriter.PackLong(P: PSignedAnsiChar; L: Integer);
|
||||
begin
|
||||
P^ := L and $FF;
|
||||
Inc(P);
|
||||
P^ := (L shr 8) and $FF;
|
||||
Inc(P);
|
||||
P^ := (L shr 16) and $FF;
|
||||
Inc(P);
|
||||
P^ := (L shr 24) and $FF;
|
||||
end;
|
||||
|
||||
{ TTextPatchWriter }
|
||||
|
||||
procedure TTextPatchWriter.CopyHeader(NewPos, OldPos, Length: Cardinal);
|
||||
begin
|
||||
Inc(Size, TIO.WriteStrFmt(TIO.StdOut, '@ -[%d] => +[%d] %d bytes'#13#10' ',
|
||||
[OldPos, NewPos, Length], FWriteToMemory, Memory, Size));
|
||||
end;
|
||||
|
||||
procedure TTextPatchWriter.Header(const OldFileName, NewFileName: string;
|
||||
const OldFileSize, NewFileSize: Cardinal);
|
||||
begin
|
||||
Inc(Size, TIO.WriteStrFmt(TIO.StdOut,
|
||||
'%% --- %s (%d bytes)'#13#10'%% +++ %s (%d bytes)'#13#10,
|
||||
[OldFileName, OldFileSize, NewFileName, NewFileSize], FWriteToMemory,
|
||||
Memory, Size));
|
||||
end;
|
||||
|
||||
class function TTextPatchWriter.IsPrint(const Ch: AnsiChar): Boolean;
|
||||
begin
|
||||
Result := Ch in [#32 .. #126];
|
||||
end;
|
||||
|
||||
{ TQuotedPatchWriter }
|
||||
|
||||
procedure TQuotedPatchWriter.Add(Data: PSignedAnsiChar; Length: Cardinal);
|
||||
begin
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, '+', FWriteToMemory, Memory, Size));
|
||||
QuotedData(Data, Length);
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, #13#10, FWriteToMemory, Memory, Size));
|
||||
end;
|
||||
|
||||
class function TQuotedPatchWriter.ByteToOct(const Value: Byte): string;
|
||||
var
|
||||
Idx: Integer;
|
||||
Digit: Byte;
|
||||
Remainder: Byte;
|
||||
begin
|
||||
Result := '';
|
||||
Remainder := Value;
|
||||
for Idx := 1 to 3 do
|
||||
begin
|
||||
Digit := Remainder mod 8;
|
||||
Remainder := Remainder div 8;
|
||||
Result := Chr(Digit + Ord('0')) + Result;
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TQuotedPatchWriter.Copy(NewBuf: PSignedAnsiCharArray;
|
||||
NewPos, OldPos, Length: Cardinal);
|
||||
begin
|
||||
CopyHeader(NewPos, OldPos, Length);
|
||||
QuotedData(@NewBuf[NewPos], Length);
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, #13#10, FWriteToMemory, Memory, Size));
|
||||
end;
|
||||
|
||||
procedure TQuotedPatchWriter.QuotedData(Data: PSignedAnsiChar;
|
||||
Length: Cardinal);
|
||||
begin
|
||||
while (Length <> 0) do
|
||||
begin
|
||||
if IsPrint(AnsiChar(Data^)) and (AnsiChar(Data^) <> '\') then
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, AnsiChar(Data^), FWriteToMemory,
|
||||
Memory, Size))
|
||||
else
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, '\' + ByteToOct(Data^ and $FF),
|
||||
FWriteToMemory, Memory, Size));
|
||||
Inc(Data);
|
||||
Dec(Length);
|
||||
end;
|
||||
end;
|
||||
|
||||
{ TFilteredPatchWriter }
|
||||
|
||||
procedure TFilteredPatchWriter.Add(Data: PSignedAnsiChar; Length: Cardinal);
|
||||
begin
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, '+', FWriteToMemory, Memory, Size));
|
||||
FilteredData(Data, Length);
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, #13#10, FWriteToMemory, Memory, Size));
|
||||
end;
|
||||
|
||||
procedure TFilteredPatchWriter.Copy(NewBuf: PSignedAnsiCharArray;
|
||||
NewPos, OldPos, Length: Cardinal);
|
||||
begin
|
||||
CopyHeader(NewPos, OldPos, Length);
|
||||
FilteredData(@NewBuf[NewPos], Length);
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, #13#10, FWriteToMemory, Memory, Size));
|
||||
end;
|
||||
|
||||
procedure TFilteredPatchWriter.FilteredData(Data: PSignedAnsiChar;
|
||||
Length: Cardinal);
|
||||
begin
|
||||
while Length <> 0 do
|
||||
begin
|
||||
if IsPrint(AnsiChar(Data^)) then
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, AnsiChar(Data^), FWriteToMemory,
|
||||
Memory, Size))
|
||||
else
|
||||
Inc(Size, TIO.WriteStr(TIO.StdOut, '.', FWriteToMemory, Memory, Size));
|
||||
Inc(Data);
|
||||
Dec(Length);
|
||||
end;
|
||||
end;
|
||||
|
||||
end.
|
375
contrib/bdiff/UPatcher.pas
Normal file
375
contrib/bdiff/UPatcher.pas
Normal file
@@ -0,0 +1,375 @@
|
||||
{
|
||||
* Class that applies patch to source file to re-create destination file.
|
||||
*
|
||||
* Based on bpatch.c by Stefan Reuther, copyright (c) 1999 Stefan Reuther
|
||||
* <Streu@gmx.de>.
|
||||
}
|
||||
|
||||
unit UPatcher;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TPatcher = class(TObject)
|
||||
private
|
||||
{ Compute simple checksum }
|
||||
class function CheckSum(Data: PAnsiChar; DataSize: Cardinal;
|
||||
const BFCheckSum: Longint): Longint;
|
||||
{ Get 32-bit quantity from char array }
|
||||
class function GetLong(PCh: PAnsiChar): Longint;
|
||||
{ Copy data from one stream to another, computing checksums
|
||||
@param SourceFileHandle [in] Handle to file containing data to be copied.
|
||||
@param DestFileHandle [in] Handle to file to receive copied data.
|
||||
@param Count [in] Number of bytes to copy.
|
||||
@param SourceCheckSum [in] Checksum for data to be copied
|
||||
@param SourceIsPatch [in] Flag True when SourceFileHandle is patch file and
|
||||
False when SourceFileHandle is source file.
|
||||
}
|
||||
class procedure CopyData(const SourceFileHandle, DestFileHandle: Integer;
|
||||
Count, SourceCheckSum: Longint; const SourceIsPatch: Boolean); overload;
|
||||
class procedure CopyData(SourceMemory, DestMemory: Pointer;
|
||||
Count, SourceCheckSum: Longint; const SourceIsPatch: Boolean;
|
||||
var Position1, Position2, OutSize: Integer); overload;
|
||||
{ Creates a temporary file in user's temp directory and returns its name }
|
||||
class function GetTempFileName: string;
|
||||
public
|
||||
{ Apply patch from standard input to SourceFileName and regenerate
|
||||
DestFileName. }
|
||||
class procedure Apply(const SourceFileName, DestFileName: string); overload;
|
||||
class procedure Apply(OldData, DiffData, NewData: Pointer;
|
||||
OldSize, DiffSize: Integer; var NewSize: Integer); overload;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
{$IOCHECKS OFF}
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
Windows, SysUtils,
|
||||
// Project
|
||||
UAppInfo, UBPatchInfoWriter, UBPatchParams, UBPatchUtils, UErrors;
|
||||
|
||||
procedure ShowMessage(Msg: string; Caption: string = '');
|
||||
begin
|
||||
MessageBox(0, PWideChar(Msg), PWideChar(Caption), MB_OK or MB_TASKMODAL);
|
||||
end;
|
||||
|
||||
const
|
||||
FORMAT_VERSION = '02'; // binary diff file format version
|
||||
BUFFER_SIZE = 4096; // size of buffer used to read files
|
||||
|
||||
{ TPatcher }
|
||||
|
||||
class procedure TPatcher.Apply(const SourceFileName, DestFileName: string);
|
||||
var
|
||||
SourceFileHandle: Integer; // source file handle
|
||||
DestFileHandle: Integer; // destination file handle
|
||||
TempFileName: string; // temporary file name
|
||||
Header: array [0 .. 15] of AnsiChar; // patch file header
|
||||
SourceLen: Longint; // expected length of source file
|
||||
DestLen: Longint; // expected length of destination file
|
||||
DataSize: Longint; // size of data to be copied to destination
|
||||
SourceFilePos: Longint; // position in source file
|
||||
Ch: Integer; // next character from patch, or EOF
|
||||
const
|
||||
ErrorMsg = 'Patch garbled - invalid section ''%''';
|
||||
begin
|
||||
try
|
||||
// read header from patch file on standard input
|
||||
if FileRead(TIO.StdIn, Header, 16) <> 16 then
|
||||
Error('Patch not in BINARY format');
|
||||
if StrLComp(Header, PAnsiChar('bdiff' + FORMAT_VERSION + #$1A), 8) <> 0 then
|
||||
Error('Patch not in BINARY format');
|
||||
// get length of source and destination files from header
|
||||
SourceLen := GetLong(@Header[8]);
|
||||
DestLen := GetLong(@Header[12]);
|
||||
|
||||
DestFileHandle := 0;
|
||||
// open source file
|
||||
SourceFileHandle := FileOpen(SourceFileName, fmOpenRead + fmShareDenyNone);
|
||||
try
|
||||
if SourceFileHandle <= 0 then
|
||||
OSError;
|
||||
|
||||
// check destination file name
|
||||
if Length(DestFileName) = 0 then
|
||||
Error('Empty destination file name');
|
||||
|
||||
// create temporary file
|
||||
TempFileName := GetTempFileName;
|
||||
DestFileHandle := FileCreate(TempFileName);
|
||||
if DestFileHandle <= 0 then
|
||||
Error('Can''t create temporary file');
|
||||
|
||||
{ apply patch }
|
||||
while True do
|
||||
begin
|
||||
Ch := TIO.GetCh(TIO.StdIn);
|
||||
if Ch = EOF then
|
||||
Break;
|
||||
case Ch of
|
||||
Integer('@'):
|
||||
begin
|
||||
// common block: copy from source
|
||||
if FileRead(TIO.StdIn, Header, 12) <> 12 then
|
||||
Error('Patch garbled - unexpected end of data');
|
||||
DataSize := GetLong(@Header[4]);
|
||||
SourceFilePos := GetLong(@Header[0]);
|
||||
if (SourceFilePos < 0) or (DataSize <= 0) or
|
||||
(SourceFilePos > SourceLen) or (DataSize > SourceLen) or
|
||||
(DataSize + SourceFilePos > SourceLen) then
|
||||
Error('Patch garbled - invalid change request');
|
||||
if not TIO.Seek(SourceFileHandle, SourceFilePos, SEEK_SET) then
|
||||
Error('Seek on source file failed');
|
||||
CopyData(SourceFileHandle, DestFileHandle, DataSize,
|
||||
GetLong(@Header[8]), False);
|
||||
Dec(DestLen, DataSize);
|
||||
end;
|
||||
Integer('+'):
|
||||
begin
|
||||
// add data from patch file
|
||||
if FileRead(TIO.StdIn, Header, 4) <> 4 then
|
||||
Error('Patch garbled - unexpected end of data');
|
||||
DataSize := GetLong(@Header[0]);
|
||||
CopyData(TIO.StdIn, DestFileHandle, DataSize, 0, True);
|
||||
Dec(DestLen, DataSize);
|
||||
end;
|
||||
else
|
||||
Error('Patch garbled - invalid section ''%s''', [Char(Ch)]);
|
||||
end;
|
||||
if DestLen < 0 then
|
||||
Error('Patch garbled - patch file longer than announced in header');
|
||||
end;
|
||||
if DestLen <> 0 then
|
||||
Error('Patch garbled - destination file shorter than announced in header');
|
||||
|
||||
finally
|
||||
FileClose(SourceFileHandle);
|
||||
FileClose(DestFileHandle);
|
||||
end;
|
||||
// create destination file: overwrites any existing dest file with same name
|
||||
SysUtils.DeleteFile(DestFileName);
|
||||
if not RenameFile(TempFileName, DestFileName) then
|
||||
Error('Can''t rename temporary file');
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
SysUtils.DeleteFile(TempFileName);
|
||||
raise;
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TPatcher.Apply(OldData, DiffData, NewData: Pointer;
|
||||
OldSize, DiffSize: Integer; var NewSize: Integer);
|
||||
var
|
||||
Position1, Position2, Position3, Size1, Size2, Size3: Integer;
|
||||
Header: array [0 .. 15] of AnsiChar; // patch file header
|
||||
SourceLen: Longint; // expected length of source file
|
||||
DestLen: Longint; // expected length of destination file
|
||||
DataSize: Longint; // size of data to be copied to destination
|
||||
SourceFilePos: Longint; // position in source file
|
||||
Ch: Integer; // next character from patch, or EOF
|
||||
B: AnsiChar;
|
||||
const
|
||||
ErrorMsg = 'Patch garbled - invalid section ''%''';
|
||||
begin
|
||||
Position1 := 0;
|
||||
Position2 := 0;
|
||||
Position3 := 0;
|
||||
Size1 := OldSize;
|
||||
Size2 := DiffSize;
|
||||
Size3 := 0;
|
||||
try
|
||||
// read header from patch file on standard input
|
||||
Move((PByte(DiffData) + Position2)^, Header, 16);
|
||||
Inc(Position2, 16);
|
||||
if StrLComp(Header, PAnsiChar('bdiff' + FORMAT_VERSION + #$1A), 8) <> 0 then
|
||||
Error('Patch not in BINARY format');
|
||||
// get length of source and destination files from header
|
||||
SourceLen := GetLong(@Header[8]);
|
||||
DestLen := GetLong(@Header[12]);
|
||||
|
||||
try
|
||||
{ apply patch }
|
||||
while True do
|
||||
begin
|
||||
if Position2 >= Size2 then
|
||||
Ch := EOF
|
||||
else
|
||||
begin
|
||||
Move((PByte(DiffData) + Position2)^, B, SizeOf(B));
|
||||
Ch := Integer(B);
|
||||
Inc(Position2, SizeOf(AnsiChar));
|
||||
end;
|
||||
if Ch = EOF then
|
||||
Break;
|
||||
case Ch of
|
||||
Integer('@'):
|
||||
begin
|
||||
// common block: copy from source
|
||||
Move((PByte(DiffData) + Position2)^, Header, 12);
|
||||
Inc(Position2, 12);
|
||||
DataSize := GetLong(@Header[4]);
|
||||
SourceFilePos := GetLong(@Header[0]);
|
||||
if (SourceFilePos < 0) or (DataSize <= 0) or
|
||||
(SourceFilePos > SourceLen) or (DataSize > SourceLen) or
|
||||
(DataSize + SourceFilePos > SourceLen) then
|
||||
Error('Patch garbled - invalid change request');
|
||||
Position1 := SourceFilePos;
|
||||
CopyData((PByte(OldData) + Position1),
|
||||
(PByte(NewData) + Position3), DataSize, GetLong(@Header[8]),
|
||||
False, Position1, Position3, Size3);
|
||||
Dec(DestLen, DataSize);
|
||||
end;
|
||||
Integer('+'):
|
||||
begin
|
||||
// add data from patch file
|
||||
Move((PByte(DiffData) + Position2)^, Header, 4);
|
||||
Inc(Position2, 4);
|
||||
DataSize := GetLong(@Header[0]);
|
||||
CopyData((PByte(DiffData) + Position2),
|
||||
(PByte(NewData) + Position3), DataSize, 0, True, Position2,
|
||||
Position3, Size3);
|
||||
Dec(DestLen, DataSize);
|
||||
end;
|
||||
else
|
||||
Error('Patch garbled - invalid section ''%s''', [Char(Ch)]);
|
||||
end;
|
||||
if DestLen < 0 then
|
||||
Error('Patch garbled - patch file longer than announced in header');
|
||||
end;
|
||||
if DestLen <> 0 then
|
||||
Error('Patch garbled - destination file shorter than announced in header');
|
||||
|
||||
finally
|
||||
|
||||
end;
|
||||
except
|
||||
on E: Exception do
|
||||
begin
|
||||
raise;
|
||||
end;
|
||||
end;
|
||||
NewSize := Size3;
|
||||
end;
|
||||
|
||||
class function TPatcher.CheckSum(Data: PAnsiChar; DataSize: Cardinal;
|
||||
const BFCheckSum: Integer): Longint;
|
||||
begin
|
||||
Result := BFCheckSum;
|
||||
while DataSize <> 0 do
|
||||
begin
|
||||
Dec(DataSize);
|
||||
Result := ((Result shr 30) and 3) or (Result shl 2);
|
||||
Result := Result xor PShortInt(Data)^;
|
||||
Inc(Data);
|
||||
end;
|
||||
end;
|
||||
|
||||
class procedure TPatcher.CopyData(const SourceFileHandle, DestFileHandle
|
||||
: Integer; Count, SourceCheckSum: Integer; const SourceIsPatch: Boolean);
|
||||
var
|
||||
DestCheckSum: Longint;
|
||||
Buffer: array [0 .. BUFFER_SIZE - 1] of AnsiChar;
|
||||
BytesToCopy: Cardinal;
|
||||
begin
|
||||
DestCheckSum := 0;
|
||||
|
||||
while Count <> 0 do
|
||||
begin
|
||||
if Count > BUFFER_SIZE then
|
||||
BytesToCopy := BUFFER_SIZE
|
||||
else
|
||||
BytesToCopy := Count;
|
||||
if FileRead(SourceFileHandle, Buffer, BytesToCopy) <> Integer(BytesToCopy)
|
||||
then
|
||||
begin
|
||||
if TIO.AtEOF(SourceFileHandle) then
|
||||
begin
|
||||
if SourceIsPatch then
|
||||
Error('Patch garbled - unexpected end of data')
|
||||
else
|
||||
Error('Source file does not match patch');
|
||||
end
|
||||
else
|
||||
begin
|
||||
if SourceIsPatch then
|
||||
Error('Error reading patch file')
|
||||
else
|
||||
Error('Error reading source file');
|
||||
end;
|
||||
end;
|
||||
if DestFileHandle <> 0 then
|
||||
if FileWrite(DestFileHandle, Buffer, BytesToCopy) <> Integer(BytesToCopy)
|
||||
then
|
||||
Error('Error writing temporary file');
|
||||
DestCheckSum := CheckSum(Buffer, BytesToCopy, DestCheckSum);
|
||||
Dec(Count, BytesToCopy);
|
||||
end;
|
||||
if not SourceIsPatch and (DestCheckSum <> SourceCheckSum) then
|
||||
Error('Source file does not match patch');
|
||||
end;
|
||||
|
||||
class procedure TPatcher.CopyData(SourceMemory, DestMemory: Pointer;
|
||||
Count, SourceCheckSum: Integer; const SourceIsPatch: Boolean;
|
||||
var Position1, Position2, OutSize: Integer);
|
||||
var
|
||||
DestCheckSum: Longint;
|
||||
BytesToCopy: Cardinal;
|
||||
Pos: Integer;
|
||||
begin
|
||||
DestCheckSum := 0;
|
||||
Pos := 0;
|
||||
Inc(Position1, Count);
|
||||
Inc(Position2, Count);
|
||||
Inc(OutSize, Count);
|
||||
while Count <> 0 do
|
||||
begin
|
||||
if Count > BUFFER_SIZE then
|
||||
BytesToCopy := BUFFER_SIZE
|
||||
else
|
||||
BytesToCopy := Count;
|
||||
|
||||
Move((PByte(SourceMemory) + Pos)^, (PByte(DestMemory) + Pos)^, BytesToCopy);
|
||||
// Move((PByte(SourceMemory) + Pos)^, Buffer, BytesToCopy);
|
||||
// Move(Buffer, (PByte(DestMemory) + Pos)^, BytesToCopy);
|
||||
DestCheckSum := CheckSum(PAnsiChar((PByte(SourceMemory) + Pos)),
|
||||
BytesToCopy, DestCheckSum);
|
||||
// DestCheckSum := CheckSum(Buffer, BytesToCopy, DestCheckSum);
|
||||
Inc(Pos, BytesToCopy);
|
||||
Dec(Count, BytesToCopy);
|
||||
end;
|
||||
if not SourceIsPatch and (DestCheckSum <> SourceCheckSum) then
|
||||
Error('Source file does not match patch');
|
||||
end;
|
||||
|
||||
class function TPatcher.GetLong(PCh: PAnsiChar): Longint;
|
||||
var
|
||||
PB: PByte;
|
||||
LW: LongWord;
|
||||
begin
|
||||
PB := PByte(PCh);
|
||||
LW := PB^;
|
||||
Inc(PB);
|
||||
LW := LW + 256 * PB^;
|
||||
Inc(PB);
|
||||
LW := LW + 65536 * PB^;
|
||||
Inc(PB);
|
||||
LW := LW + 16777216 * PB^;
|
||||
Result := LW;
|
||||
end;
|
||||
|
||||
class function TPatcher.GetTempFileName: string;
|
||||
begin
|
||||
// Get temporary folder
|
||||
SetLength(Result, Windows.MAX_PATH);
|
||||
Windows.GetTempPath(Windows.MAX_PATH, PChar(Result));
|
||||
// Get unique temporary file name (it is created as side effect of this call)
|
||||
if Windows.GetTempFileName(PChar(Result), '', 0, PChar(Result)) = 0 then
|
||||
Error('Can''t create temporary file');
|
||||
Result := PChar(Result)
|
||||
end;
|
||||
|
||||
end.
|
96
contrib/bdiff/UUtils.pas
Normal file
96
contrib/bdiff/UUtils.pas
Normal file
@@ -0,0 +1,96 @@
|
||||
{
|
||||
* Contains utility functions used by both BDiff and BPatch.
|
||||
}
|
||||
|
||||
unit UUtils;
|
||||
|
||||
interface
|
||||
|
||||
type
|
||||
TCommonIO = class(TObject)
|
||||
public
|
||||
{ Returns Windows standard input handle }
|
||||
class function StdIn: Integer;
|
||||
{ Returns Windows standard output handle }
|
||||
class function StdOut: Integer;
|
||||
{ Returns Windows standard error handle }
|
||||
class function StdErr: Integer;
|
||||
{ Writes binary data to a file }
|
||||
class function WriteRaw(Handle: THandle; BufPtr: Pointer; Size: Integer;
|
||||
Memory: Boolean = False; Mem: Pointer = nil;
|
||||
Position: Integer = 0): Integer;
|
||||
{ Writes a string to a file }
|
||||
class function WriteStr(Handle: THandle; const S: UnicodeString;
|
||||
Memory: Boolean = False; Mem: Pointer = nil; Position: Integer = 0)
|
||||
: Integer; overload;
|
||||
class function WriteStr(Handle: THandle; const S: AnsiString;
|
||||
Memory: Boolean = False; Mem: Pointer = nil; Position: Integer = 0)
|
||||
: Integer; overload;
|
||||
{ Writes a string built from format string and arguments to file }
|
||||
class function WriteStrFmt(Handle: THandle; const Fmt: string;
|
||||
Args: array of const; Memory: Boolean = False; Mem: Pointer = nil;
|
||||
Position: Integer = 0): Integer;
|
||||
end;
|
||||
|
||||
implementation
|
||||
|
||||
uses
|
||||
// Delphi
|
||||
SysUtils, Windows;
|
||||
|
||||
{ TCommonIO }
|
||||
|
||||
class function TCommonIO.StdErr: Integer;
|
||||
begin
|
||||
Result := Integer(Windows.GetStdHandle(STD_ERROR_HANDLE));
|
||||
end;
|
||||
|
||||
class function TCommonIO.StdIn: Integer;
|
||||
begin
|
||||
Result := Integer(Windows.GetStdHandle(STD_INPUT_HANDLE));
|
||||
end;
|
||||
|
||||
class function TCommonIO.StdOut: Integer;
|
||||
begin
|
||||
Result := Integer(Windows.GetStdHandle(STD_OUTPUT_HANDLE));
|
||||
end;
|
||||
|
||||
class function TCommonIO.WriteRaw(Handle: THandle; BufPtr: Pointer;
|
||||
Size: Integer; Memory: Boolean = False; Mem: Pointer = nil;
|
||||
Position: Integer = 0): Integer;
|
||||
var
|
||||
Dummy: DWORD;
|
||||
begin
|
||||
Result := 0;
|
||||
if Size <= 0 then
|
||||
Exit;
|
||||
Result := Size;
|
||||
if Memory then
|
||||
Move(BufPtr^, (PByte(Mem) + Position)^, Size)
|
||||
else
|
||||
Windows.WriteFile(Handle, BufPtr^, Size, Dummy, nil);
|
||||
end;
|
||||
|
||||
class function TCommonIO.WriteStr(Handle: THandle; const S: UnicodeString;
|
||||
Memory: Boolean = False; Mem: Pointer = nil; Position: Integer = 0): Integer;
|
||||
var
|
||||
Bytes: TBytes;
|
||||
begin
|
||||
Bytes := TEncoding.Default.GetBytes(S);
|
||||
Result := WriteRaw(Handle, Bytes, Length(S), Memory, Mem, Position);
|
||||
end;
|
||||
|
||||
class function TCommonIO.WriteStr(Handle: THandle; const S: AnsiString;
|
||||
Memory: Boolean = False; Mem: Pointer = nil; Position: Integer = 0): Integer;
|
||||
begin
|
||||
Result := WriteRaw(Handle, PAnsiChar(S), Length(S), Memory, Mem, Position);
|
||||
end;
|
||||
|
||||
class function TCommonIO.WriteStrFmt(Handle: THandle; const Fmt: string;
|
||||
Args: array of const; Memory: Boolean = False; Mem: Pointer = nil;
|
||||
Position: Integer = 0): Integer;
|
||||
begin
|
||||
Result := WriteStr(Handle, Format(Fmt, Args), Memory, Mem, Position);
|
||||
end;
|
||||
|
||||
end.
|
Reference in New Issue
Block a user