Source file : comp_zip_prc.adb
1 ------------------------------------------------------------------------------
2 -- File: Comp_Zip_Prc.adb
3 -- Description: A Zip comparison tool using Zip-Ada lib.
4 -- Demonstrates the Zip.Traverse procedure.
5 -- See Comp_Zip for a command-line tool using it.
6 -- Author: Gautier de Montmollin
7 ------------------------------------------------------------------------------
8
9 with Ada.Characters.Handling,
10 Ada.Integer_Text_IO,
11 Ada.Text_IO;
12
13 with Interfaces;
14
15 with Zip;
16 with UnZip.Streams;
17
18 procedure Comp_Zip_Prc (
19 z1, z2 : Zip.Zip_Info;
20 quiet : Natural;
21 password : String := "";
22 total_differences : out Natural
23 )
24 is
25 use Interfaces;
26 z : array (1 .. 2) of Zip.Zip_Info;
27 total_1,
28 total_2,
29 common,
30 size_failures,
31 compare_failures,
32 missing_1_in_2,
33 just_a_directory,
34 missing_2_in_1 : Natural := 0;
35 total_bytes : Integer_64 := 0;
36
37 first_item : Boolean := True;
38
39 use Ada.Text_IO;
40
41 procedure Compare_1_file (file_name : String) is
42 use UnZip.Streams;
43
44 f : array (1 .. 2) of Zipped_File_Type;
45 s : array (1 .. 2) of Stream_Access;
46 c : array (1 .. 2) of Character;
47 p : Integer_64 := 1;
48
49 function Cut_name (n : String; l : Natural) return String is
50 dots : constant String := "...";
51 begin
52 if n'Length > l then
53 return dots & n (n'Last - (l - 1) + dots'Length .. n'Last);
54 else
55 return n;
56 end if;
57 end Cut_name;
58
59 l : constant := 40;
60 mininame : constant String := Ada.Characters.Handling.To_Lower (Cut_name (file_name, l));
61 stuffing : constant String (1 .. l - mininame'Length + 1) := (others => ' ');
62
63 begin
64 if quiet = 0 then
65 if first_item then
66 New_Line;
67 first_item := False;
68 end if;
69 Put (" [" & stuffing & mininame & "] ");
70 end if;
71 for i in 1 .. 2 loop
72 begin
73 Open (f (i), z (i), file_name, password);
74 if i = 1 then
75 total_1 := total_1 + 1;
76 end if;
77 exception
78 when Zip.Entry_name_not_found =>
79 if quiet = 0 then
80 Put (" # Not found in archive [" & Zip.Zip_Name (z (i)) & ']');
81 end if;
82 if i = 1 then
83 Put_Line ("-- internal error!");
84 else
85 Close (f (1));
86 end if;
87 if file_name (file_name'Last) = '/' or file_name (file_name'Last) = '\' then
88 just_a_directory := just_a_directory + 1;
89 if quiet = 0 then
90 Put_Line (" (just a dir.)");
91 end if;
92 else
93 if quiet = 0 then
94 New_Line;
95 end if;
96 end if;
97 missing_1_in_2 := missing_1_in_2 + 1;
98 return;
99 end;
100 s (i) := Stream (f (i));
101 end loop;
102 -- File found, now the comparison:
103 while not End_Of_File (f (1)) loop
104 if End_Of_File (f (2)) then
105 if quiet = 0 then
106 Put_Line (" # Shorter in [" & Zip.Zip_Name (z (2)) & "] at position" &
107 Integer_64'Image (p));
108 end if;
109 Close (f (1));
110 Close (f (2));
111 size_failures := size_failures + 1;
112 return;
113 end if;
114 -- Read one character in each stream
115 for i in 1 .. 2 loop
116 Character'Read (s (i), c (i));
117 end loop;
118 if c (1) /= c (2) then
119 if quiet = 0 then
120 Put_Line (" # Difference at position" & Integer_64'Image (p));
121 end if;
122 Close (f (1));
123 Close (f (2));
124 compare_failures := compare_failures + 1;
125 return;
126 end if;
127 p := p + 1;
128 end loop;
129 if not End_Of_File (f (2)) then
130 if quiet = 0 then
131 Put_Line (" # Longer in [" & Zip.Zip_Name (z (2)) & "]");
132 end if;
133 Close (f (1));
134 Close (f (2));
135 size_failures := size_failures + 1;
136 return;
137 end if;
138 Close (f (1));
139 Close (f (2));
140 if quiet = 0 then
141 Put_Line ("OK -" & Integer_64'Image (p - 1) & " bytes compared");
142 end if;
143 total_bytes := total_bytes + (p - 1);
144 end Compare_1_file;
145
146 procedure Compare_all_files is new Zip.Traverse (Compare_1_file);
147
148 err_str : String (1 .. 5);
149
150 use Ada.Integer_Text_IO;
151
152 begin
153 z (1) := z1;
154 z (2) := z2;
155 if quiet <= 3 then
156 Put ("* Comparing [" & Zip.Zip_Name (z (1)) & "] and [" & Zip.Zip_Name (z (2)) & ']');
157 end if;
158 Compare_all_files (z (1));
159 total_2 := Zip.Entries (z (2));
160 common := total_1 - missing_1_in_2;
161 if quiet < 2 then
162 Put_Line ("* === Results ===");
163 Put_Line (" 1st archive: [" & Zip.Zip_Name (z (1)) & "], total files:" & Natural'Image (total_1));
164 Put_Line (" 2nd archive: [" & Zip.Zip_Name (z (2)) & "], total files:" & Natural'Image (total_2));
165 Put_Line (" Total files compared: " & Natural'Image (common));
166 Put_Line (" Total of correct bytes: " & Integer_64'Image (total_bytes));
167 end if;
168 missing_2_in_1 := total_2 - common;
169 -- t2 - m21 = t1 - m12 = # common files
170 total_differences :=
171 size_failures + compare_failures +
172 missing_1_in_2 + missing_2_in_1;
173 case quiet is
174 when 0 .. 2 =>
175 New_Line;
176 Put_Line ("* === Comparison summary ===");
177 Put (err_str, size_failures);
178 Put_Line (" Size failures . . . . . . . . . . . :" & err_str);
179 Put (err_str, compare_failures);
180 Put_Line (" Content comparison failures . . . . :" & err_str);
181 Put (err_str, missing_1_in_2);
182 Put (" Files of 1st archive missing in 2nd :" & err_str);
183 --
184 if just_a_directory > 0 then
185 Put_Line (" (" & Integer'Image (just_a_directory) & " useless dir. names)");
186 else
187 New_Line;
188 end if;
189 --
190 Put (err_str, missing_2_in_1);
191 for i in err_str'Range loop
192 if err_str (i) = ' ' then err_str (i) := '_'; end if;
193 end loop;
194 Put_Line (" __Files of 2nd archive missing in 1st :" & err_str & "__");
195 --
196 Put (err_str, total_differences);
197 Put_Line (" Total of errors . . . . . . . . . . . :" & err_str);
198 when 3 =>
199 if total_differences = 0 then
200 Put_Line (" OK");
201 else
202 Put (err_str, total_differences);
203 Put_Line (" Differences:" & err_str);
204 end if;
205 when others =>
206 null;
207 end case;
208 end Comp_Zip_Prc;
Web view of Ada source code generated by GNATHTML, project: ALI_Parse version 1.0.
Zip-Ada: Ada library for zip archive files (.zip).
Ada programming.
Some news about Zip-Ada and other Ada projects
on Gautier's blog.