Source file : comp_zip_prc.adb
------------------------------------------------------------------------------
-- File: Comp_Zip_Prc.adb
-- Description: A Zip comparison tool using Zip-Ada lib.
-- Demonstrates the Zip.Traverse procedure.
-- See Comp_Zip for a command-line tool using it.
-- Author: Gautier de Montmollin
------------------------------------------------------------------------------
with Ada.Characters.Handling,
Ada.Integer_Text_IO,
Ada.Text_IO;
with Interfaces;
with Zip;
with UnZip.Streams;
procedure Comp_Zip_Prc (
z1, z2 : Zip.Zip_Info;
quiet : Natural;
password : String := "";
total_differences : out Natural
)
is
use Interfaces;
z : array (1 .. 2) of Zip.Zip_Info;
total_1,
total_2,
common,
size_failures,
compare_failures,
missing_1_in_2,
just_a_directory,
missing_2_in_1 : Natural := 0;
total_bytes : Integer_64 := 0;
first_item : Boolean := True;
use Ada.Text_IO;
procedure Compare_1_file (file_name : String) is
use UnZip.Streams;
f : array (1 .. 2) of Zipped_File_Type;
s : array (1 .. 2) of Stream_Access;
c : array (1 .. 2) of Character;
p : Integer_64 := 1;
function Cut_name (n : String; l : Natural) return String is
dots : constant String := "...";
begin
if n'Length > l then
return dots & n (n'Last - (l - 1) + dots'Length .. n'Last);
else
return n;
end if;
end Cut_name;
l : constant := 40;
mininame : constant String := Ada.Characters.Handling.To_Lower (Cut_name (file_name, l));
stuffing : constant String (1 .. l - mininame'Length + 1) := (others => ' ');
begin
if quiet = 0 then
if first_item then
New_Line;
first_item := False;
end if;
Put (" [" & stuffing & mininame & "] ");
end if;
for i in 1 .. 2 loop
begin
Open (f (i), z (i), file_name, password);
if i = 1 then
total_1 := total_1 + 1;
end if;
exception
when Zip.Entry_name_not_found =>
if quiet = 0 then
Put (" # Not found in archive [" & Zip.Zip_Name (z (i)) & ']');
end if;
if i = 1 then
Put_Line ("-- internal error!");
else
Close (f (1));
end if;
if file_name (file_name'Last) = '/' or file_name (file_name'Last) = '\' then
just_a_directory := just_a_directory + 1;
if quiet = 0 then
Put_Line (" (just a dir.)");
end if;
else
if quiet = 0 then
New_Line;
end if;
end if;
missing_1_in_2 := missing_1_in_2 + 1;
return;
end;
s (i) := Stream (f (i));
end loop;
-- File found, now the comparison:
while not End_Of_File (f (1)) loop
if End_Of_File (f (2)) then
if quiet = 0 then
Put_Line (" # Shorter in [" & Zip.Zip_Name (z (2)) & "] at position" &
Integer_64'Image (p));
end if;
Close (f (1));
Close (f (2));
size_failures := size_failures + 1;
return;
end if;
-- Read one character in each stream
for i in 1 .. 2 loop
Character'Read (s (i), c (i));
end loop;
if c (1) /= c (2) then
if quiet = 0 then
Put_Line (" # Difference at position" & Integer_64'Image (p));
end if;
Close (f (1));
Close (f (2));
compare_failures := compare_failures + 1;
return;
end if;
p := p + 1;
end loop;
if not End_Of_File (f (2)) then
if quiet = 0 then
Put_Line (" # Longer in [" & Zip.Zip_Name (z (2)) & "]");
end if;
Close (f (1));
Close (f (2));
size_failures := size_failures + 1;
return;
end if;
Close (f (1));
Close (f (2));
if quiet = 0 then
Put_Line ("OK -" & Integer_64'Image (p - 1) & " bytes compared");
end if;
total_bytes := total_bytes + (p - 1);
end Compare_1_file;
procedure Compare_all_files is new Zip.Traverse (Compare_1_file);
err_str : String (1 .. 5);
use Ada.Integer_Text_IO;
begin
z (1) := z1;
z (2) := z2;
if quiet <= 3 then
Put ("* Comparing [" & Zip.Zip_Name (z (1)) & "] and [" & Zip.Zip_Name (z (2)) & ']');
end if;
Compare_all_files (z (1));
total_2 := Zip.Entries (z (2));
common := total_1 - missing_1_in_2;
if quiet < 2 then
Put_Line ("* === Results ===");
Put_Line (" 1st archive: [" & Zip.Zip_Name (z (1)) & "], total files:" & Natural'Image (total_1));
Put_Line (" 2nd archive: [" & Zip.Zip_Name (z (2)) & "], total files:" & Natural'Image (total_2));
Put_Line (" Total files compared: " & Natural'Image (common));
Put_Line (" Total of correct bytes: " & Integer_64'Image (total_bytes));
end if;
missing_2_in_1 := total_2 - common;
-- t2 - m21 = t1 - m12 = # common files
total_differences :=
size_failures + compare_failures +
missing_1_in_2 + missing_2_in_1;
case quiet is
when 0 .. 2 =>
New_Line;
Put_Line ("* === Comparison summary ===");
Put (err_str, size_failures);
Put_Line (" Size failures . . . . . . . . . . . :" & err_str);
Put (err_str, compare_failures);
Put_Line (" Content comparison failures . . . . :" & err_str);
Put (err_str, missing_1_in_2);
Put (" Files of 1st archive missing in 2nd :" & err_str);
--
if just_a_directory > 0 then
Put_Line (" (" & Integer'Image (just_a_directory) & " useless dir. names)");
else
New_Line;
end if;
--
Put (err_str, missing_2_in_1);
for i in err_str'Range loop
if err_str (i) = ' ' then err_str (i) := '_'; end if;
end loop;
Put_Line (" __Files of 2nd archive missing in 1st :" & err_str & "__");
--
Put (err_str, total_differences);
Put_Line (" Total of errors . . . . . . . . . . . :" & err_str);
when 3 =>
if total_differences = 0 then
Put_Line (" OK");
else
Put (err_str, total_differences);
Put_Line (" Differences:" & err_str);
end if;
when others =>
null;
end case;
end Comp_Zip_Prc;
Zip-Ada: Ada library for zip archive files (.zip).
Ada programming.
Some news about Zip-Ada and other Ada projects
on Gautier's blog.