VPatch 2.1:

* Added argument checking and error handling to GenPat. Now returns exit codes as well to indicate success/failure (and the reason for failure). Only GenPat has changed in this version compared to 2.0 final.
* Bug Fix: GenPat no longer gives an Access Violation when attempting to patch a file smaller than 64 bytes into a file larger than 64 bytes.


git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@3318 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
kichik 2003-12-27 18:36:57 +00:00
parent 14f2e625e4
commit b7c7a31b3e
5 changed files with 314 additions and 108 deletions

View file

@ -11,6 +11,9 @@ program GenPat2;
What's new
----------
2.1 20031219 Koen Added error checking, handling, shouldn't
crash when invalid arguments, returns
exit codes now.
2.0 20030811 Koen Initial documentation
}
@ -38,18 +41,20 @@ type
var
Config: TextFile;
T1,T2: TDateTime;
d: Integer;
d, i: Integer;
S,Key: String;
ShowDebug: Boolean;
SourceFile, TargetFile, PatchFile: String;
ShowDebug, ShowHelp: Boolean;
PG: TPatchGenerator;
EV: TEventHandler;
begin
EV:=TEventHandler.Create;
PG:=TPatchGenerator.Create;
PG.StartBlockSize:=64;
WriteLn('GenPat v2.0 final');
WriteLn('=================');
WriteLn('GenPat v2.1');
WriteLn('===========');
WriteLn;
WriteLn('(c) 2001-2003 Van de Sande Productions');
WriteLn('Website: http://www.tibed.net/vpatch');
@ -75,13 +80,35 @@ begin
CloseFile(Config);
end;
{$ENDIF}
i:=0;
for d:=1 to ParamCount do begin
if CompareStr(LowerCase(Copy(ParamStr(d),1,3)),'/b=')=0 then begin
PG.StartBlockSize:=StrToInt(Copy(ParamStr(d),4,10));
end else begin
// not a parameter?
if not (ParamStr(d)[1] = '/') then begin
if i = 2 then begin
PatchFile:=ParamStr(d);
Inc(i);
end;
if i = 1 then begin
TargetFile:=ParamStr(d);
Inc(i);
end;
if i = 0 then begin
SourceFile:=ParamStr(d);
Inc(i);
end;
end;
end;
end;
if (CompareStr(ParamStr(1),'')=0) or (CompareStr(ParamStr(2),'')=0) or (CompareStr(ParamStr(3),'')=0) then begin
ShowHelp:=False;
if(CompareStr(PatchFile,'')=0) then ShowHelp:=True;
if SourceFile = '' then ShowHelp:=True;
if TargetFile = '' then ShowHelp:=True;
if ShowHelp then begin
WriteLn('This program will take (sourcefile) as input and create a (patchfile).');
WriteLn('With this patchfile, you can convert a (sourcefile) into (targetfile).');
WriteLn;
@ -90,36 +117,110 @@ begin
WriteLn;
WriteLn('Command line options (you do not need them):');
WriteLn('/B=(BlockSize) Set blocksize (def=64), multiple of 2');
WriteLn('/WAIT Wait for a keypress after program complete');
WriteLn('/NOEQUALERROR Exit code becomes 0 instead of 10 when');
WriteLn(' two files with equal CRC are encountered');
WriteLn(' (patch file will remain unchanged)');
WriteLn('/DEBUG Show runtime debug information');
WriteLn('Note: all these parameters must be *after* the filenames!');
WriteLn;
Write('Press a enter to exit ');
ReadLn(S);
WriteLn('Note: filenames should never start with / character!');
WriteLn;
WriteLn('Possible exit codes:');
WriteLn(' 0 Success');
WriteLn(' 1 Arguments missing');
WriteLn(' 2 Source file not found');
WriteLn(' 3 Target file not found');
WriteLn(' 4 Unknown error while reading existing patch file');
WriteLn(' 5 Unknown error while generating patch');
WriteLn(' 6 Unknown error while writing patch file to disk');
WriteLn(' 10 CRC of source and target file are equal (impossible with /NOEQUALERROR)');
WriteLn(' 11 Not enough memory for source file');
WriteLn(' 12 Not enough memory for target file');
PG.Free;
ExitCode:=1;
Exit;
end;
if FileExists(ParamStr(3)) then begin
WriteLn('Using existing file to include patches in: '+ParamStr(3));
PG.LoadFromFile(ParamStr(3));
// stop if file error, result shown above
if not FileExists(SourceFile) then begin
WriteLn('Error: Source file not found');
PG.Free;
ExitCode:=2;
Exit;
end;
if not FileExists(TargetFile) then begin
WriteLn('Error: Target file not found');
PG.Free;
ExitCode:=3;
Exit;
end;
if FileExists(PatchFile) then begin
WriteLn('Using existing file to include patches in: '+PatchFile);
try
PG.LoadFromFile(PatchFile);
except
on E: Exception do begin
WriteLn('Error: Reading existing patch file failed');
WriteLn('Error message: ', E.ClassName, ': ', E.Message);
PG.Free;
ExitCode:=4;
Exit;
end;
end;
end;
WriteLn('Source (original) file: ', SourceFile);
WriteLn('Target (newer) file: ', TargetFile);
T1:=Now;
WriteLn('Patch body size: '+IntToStr(PG.CreatePatch(ParamStr(1),ParamStr(2))));
PG.WriteToFile(ParamStr(3));
T2:=Now;
Write('GenPat.exe finished execution in: ');
WriteLn(FloatToStr((T2-T1)*24*60*60),'s');
WriteLn;
{$IFNDEF AUTOWAIT}
if FindCmdLineSwitch('wait',['/'],True) then begin
{$ENDIF}
WriteLn;
WriteLn('Press a key');
ReadLn(S);
{$IFNDEF AUTOWAIT}
// create patch file, with error handling
try
i:=PG.CreatePatch(SourceFile,TargetFile);
except
on E: Exception do begin
WriteLn('Error: Generating patch failed');
WriteLn('Error message: ', E.ClassName, ': ', E.Message);
PG.Free;
ExitCode:=5;
Exit;
end;
end;
{$ENDIF}
if(i < 0) then begin
if(i = -1) then begin
if not FindCmdLineSwitch('noequalerror',['/'],True) then
WriteLn('Error: CRC of source and target file are equal');
end;
if(i = -2) then WriteLn('Error: Not enough memory for source file');
if(i = -3) then WriteLn('Error: Not enough memory for target file');
ExitCode:=9 - i;
if(i = -1) and (FindCmdLineSwitch('noequalerror',['/'],True)) then begin
WriteLn('Equal CRCs ignored (no patch will be written and exit code is 0)');
ExitCode:=0;
end;
end else begin
WriteLn('Patch body size: '+IntToStr(i));
try
PG.WriteToFile(PatchFile);
except
on E: Exception do begin
WriteLn('Error: Writing patch to file ' + PatchFile + ' failed');
WriteLn('Error message: ', E.ClassName, ': ', E.Message);
PG.Free;
ExitCode:=6;
Exit;
end;
end;
T2:=Now;
Write('Time taken for generation: ');
WriteLn(FloatToStr((T2-T1)*24*60*60),'s');
WriteLn;
ExitCode:=0;
end;
PG.Free;
end.

View file

@ -32,6 +32,8 @@ unit PatchGenerator;
What's new
----------
2.1 20031219 Koen Added error checking to CreatePatch, returns
negative numbers when there are errors.
2.0 20030811 Koen Initial documentation
}
@ -141,8 +143,8 @@ var
retTO: Integer;
noN: Integer;
begin
fsSource:=TFileStream.Create(SourceFileName,fmOpenRead);
fsTarget:=TFileStream.Create(TargetFileName,fmOpenRead);
fsSource:=TFileStream.Create(SourceFileName,fmOpenRead+fmShareDenyNone);
fsTarget:=TFileStream.Create(TargetFileName,fmOpenRead+fmShareDenyNone);
fm:=TMemoryStream.Create;
SetLength(PRay,INIT_BLOCK_COUNT);
@ -150,7 +152,14 @@ begin
//Load those files into memory!
SourceSize:=fsSource.Size;
GetMem(Source,SourceSize);
try
GetMem(Source,SourceSize);
except
on EOutOfMemory do begin
Result:=-2; // not enough memory for source file
Exit;
end;
end;
fm.CopyFrom(fsSource,SourceSize);
Move(fm.Memory^,Source^,SourceSize);
SourceCRC:=FileCRC(fsSource);
@ -158,13 +167,28 @@ begin
fm.Clear;
TargetSize:=fsTarget.Size;
GetMem(Target,TargetSize);
try
GetMem(Target,TargetSize);
except
on EOutOfMemory do begin
FreeMem(Source,SourceSize);
Result:=-3; // not enough memory for target file
Exit;
end;
end;
fm.CopyFrom(fsTarget,TargetSize);
Move(fm.Memory^,Target^,TargetSize);
TargetCRC:=FileCRC(fsTarget);
fsTarget.Free;
fm.Free;
if(SourceCRC = TargetCRC) then begin
FreeMem(Source,SourceSize);
FreeMem(Target,TargetSize);
Result:=-1;
Exit;
end;
PRay[0].TargetOffset:=0;
PRay[0].SourceOffset:=0;
PRay[0].Size:=0;

View file

@ -15,6 +15,8 @@ unit TreeCode;
What's new
----------
2.1 20031219 Koen Fixed bug in TreeFind: when tree was a nil
pointer, now returns instead of AVing
2.0 20030811 Koen Initial documentation
}
@ -179,6 +181,10 @@ var
lo,mid,hi,m: Integer;
tmp: Cardinal;
begin
if not Assigned(ABlockTree) then begin
FoundCount:=0; Result:=nil;
Exit;
end;
lo:=0;
hi:=ABlockTreeNodeCount-1;
while true do begin