tree checksum vpatch file split hunks
all signers: phf
antecedents: vtools_vpatch vtools_fixes_static_tohex
press order:
vtools_genesis | phf |
vdiff_fixes_newline_gcc | phf |
keccak | phf |
vdiff_keccak | phf |
vtools_fixes_bitrate_char_array | phf |
vtools_vpatch | phf |
vtools_fixes_static_tohex | phf |
vtools_vpatch_newline | phf |
patch:
(5 . 3)(5 . 4)
5 512600 phf vtools_fixes_bitrate_char_array Fixes for keccak from diana_coman, different approach to C interop.
6 514700 phf vtools_vpatch Initial vpatch tool implementation in Ada.
7 517100 phf vtools_fixes_static_tohex Fixes for xalloc's use of static inline courtesy of spyked, fix broken ToHex implementation
8 517100 phf vtools_vpatch_newline Vpatch tool support for "No newline at end of file" directive.
-(0 . 0)(1 . 81)
13 package body Character_IO is
14 LM: constant Character := ASCII.LF;
15
16 procedure Get_Line(File : in Character_IO.File_Type;
17 Item : out String;
18 Last : out Natural;
19 New_Line : out Boolean) is
20 C: Character;
21 begin
22 New_Line := False;
23 Last := Item'First - 1;
24 if Last >= Item'Last then
25 return;
26 end if;
27 if Character_IO.End_Of_File(File) then
28 raise Character_IO.End_Error;
29 end if;
30 loop
31 Character_IO.Read(File, C);
32 if C = LM then
33 New_Line := True;
34 return;
35 end if;
36 Last := Last + 1;
37 Item(Last) := C;
38 if Last = Item'Last then
39 return;
40 end if;
41 exit when Character_IO.End_Of_File(File);
42 end loop;
43 end;
44
45 function Get_Line (File : Character_IO.File_Type;
46 New_Line : out Boolean) return String is
47 Buffer : String (1 .. 500);
48 Last : Natural;
49
50 function Get_Rest (S : String) return String is
51 Buffer : String (1 .. S'Length);
52 Last : Natural;
53 begin
54 Get_Line (File, Buffer, Last, New_Line);
55 declare
56 R : constant String := S & Buffer (1 .. Last);
57 begin
58 if Last < Buffer'Last then
59 return R;
60 else
61 return Get_Rest (R);
62 end if;
63 end;
64 end Get_Rest;
65
66 begin
67 Get_Line (File, Buffer, Last, New_Line);
68
69 if Last < Buffer'Last then
70 return Buffer (1 .. Last);
71 else
72 return Get_Rest (Buffer (1 .. Last));
73 end if;
74 end Get_Line;
75
76 function Get_Line(File : in Character_IO.File_Type) return String is
77 New_Line : Boolean;
78 begin
79 return Get_Line(File, New_Line);
80 end Get_Line;
81
82 procedure Put_Line(File : in Character_IO.File_Type;
83 Item : in String;
84 New_Line : Boolean := True) is
85 begin
86 for C of Item loop
87 Character_IO.Write(File, C);
88 end loop;
89 if New_Line then
90 Character_IO.Write(File, LM);
91 end if;
92 end;
93 end;
-(0 . 0)(1 . 28)
98 with Ada.Sequential_IO;
99 package Character_IO is
100 package Character_IO is
101 new Ada.Sequential_IO(Element_Type => Character);
102
103 procedure Open (File : in out Character_IO.File_Type;
104 Mode : in Character_IO.File_Mode;
105 Name : in String;
106 Form : in String := "") renames Character_IO.Open;
107 procedure Create(File : in out Character_IO.File_Type;
108 Mode : in Character_IO.File_Mode := Character_IO.Out_File;
109 Name : in String := "";
110 Form : in String := "") renames Character_IO.Create;
111 function End_Of_File(File : in Character_IO.File_Type) return Boolean
112 renames Character_IO.End_Of_File;
113 function Name (File : in Character_IO.File_Type) return String
114 renames Character_IO.Name;
115 function Is_Open(File : in Character_IO.File_Type) return Boolean
116 renames Character_IO.Is_Open;
117 procedure Close (File : in out Character_IO.File_Type) renames Character_IO.Close;
118
119 function Get_Line(File : in Character_IO.File_Type) return String;
120 function Get_Line(File : in Character_IO.File_Type;
121 New_Line : out Boolean) return String;
122 procedure Put_Line(File : in Character_IO.File_Type;
123 Item : in String;
124 New_Line : Boolean := True );
125 end Character_IO;
- AFD665D979FE64DFDCC2D99A515A887B8C32E961AFA20201755A80DCCB64713DB2942BF7828748A41C8B88859BE4BFA917CB50134A0D3F4FEF403FCFB26463EF(3 . 6)(3 . 7)
130 with Interfaces.C.Strings;
131 with Ada.Text_IO; use Ada.Text_IO;
132 with Ada.Integer_Text_IO; use Ada.Integer_Text_IO;
133 with Character_IO; use Character_IO;
134 with Ada.Strings.Fixed;
135 with Ada.Directories;
136 with Ada.Characters;
(14 . 6)(15 . 7)
138 procedure VPatch is
139 package Latin_1 renames Ada.Characters.Latin_1;
140 package Dirs renames Ada.Directories;
141 package CIO renames Character_IO.Character_IO;
142
143 -- Utilities
144
(82 . 6)(84 . 15)
146 Create(File, Mode, Name, Form);
147 end;
148
149 procedure Create_Temp(File : in out CIO.File_Type;
150 Mode : in CIO.File_Mode := CIO.Out_File;
151 Template : in String := "vpatch.XXX";
152 Form : in String := "") is
153 Name: String := Temp_File_Name(Template);
154 begin
155 Create(File, Mode, Name, Form);
156 end;
157
158 -- VPatch data structures
159
160 type Patch_Op is (Op_Create, Op_Delete, Op_Patch);
(330 . 8)(341 . 8)
162 From_Count: Natural := 0;
163 To_Count: Natural := 0;
164 Has_Input_File: Boolean;
165 In_F: File_Type;
166 To_F: File_Type;
167 In_F: CIO.File_Type;
168 To_F: CIO.File_Type;
169 Line: Positive := 1;
170 In_Ctx: Keccak_Context;
171 To_Ctx: Keccak_Context;
(339 . 28)(350 . 37)
173 To_Hash: Bitstream(1..64*8);
174 To_F_Name: constant String := Press_Name(A_Header);
175 Op: Patch_Op;
176
177 procedure Hash_Line(Ctx: in out Keccak_Context; S: String) is
178 Newline_Directive: constant String := "\ No newline at end of file";
179
180 procedure Hash_Line(Ctx: in out Keccak_Context;
181 S: String;
182 New_Line: Boolean := True) is
183 B: Bitstream(1..S'Length*8);
184 LF_B: constant Bitstream(1..8) := (0, 1, 0, 1, 0, 0, 0, 0);
185 begin
186 ToBitstream(S, B);
187 KeccakHash(Ctx, B);
188 KeccakHash(Ctx, LF_B);
189 if New_Line then
190 KeccakHash(Ctx, LF_B);
191 end if;
192 end;
193
194
195 Check_Input_File_Hash_Pending: Boolean := True;
196 procedure Check_Input_File_Hash is
197 begin
198 if Has_Input_File then
199 if Has_Input_File and Is_Open(In_F)
200 and Check_Input_File_Hash_Pending then
201 begin
202 Check_Input_File_Hash_Pending := False;
203 Catch_Up_Loop:
204 loop
205 declare
206 In_Line: String := Get_Line(In_F);
207 New_Line: Boolean;
208 In_Line: String := Get_Line(In_F, New_Line);
209 begin
210 Put_Line(To_F, In_Line);
211 Hash_Line(In_Ctx, In_Line);
212 Hash_Line(To_Ctx, In_Line);
213 Put_Line(To_F, In_Line, New_Line);
214 Hash_Line(In_Ctx, In_Line, New_Line);
215 Hash_Line(To_Ctx, In_Line, New_Line);
216 end;
217 end loop Catch_Up_Loop;
218 exception
(374 . 8)(394 . 7)
220 H: Hash := (Value => Hex_Hash,
221 The_Type => Value);
222 begin
223 if A_Header.From_Hash /= (Value => Hex_Hash,
224 The_Type => Value) then
225 if A_Header.From_Hash /= H then
226 raise State with "from hash doesn't match";
227 end if;
228 end;
(408 . 7)(427 . 19)
230 Dirs.Delete_File(Name(To_F));
231 end if;
232 end Cleanup;
233
234
235 function Has_No_Newline_Directive return Boolean is
236 C: Character;
237 begin
238 Look_Ahead(C, EOL);
239 if C = '\' then
240 Looking_At(Newline_Directive);
241 Next_Line;
242 return True;
243 end if;
244 return False;
245 end;
246
247 begin
248 Op := Operation(A_Header);
249
(435 . 14)(466 . 14)
251
252 -- prepare keccak and open files
253 KeccakBegin(To_Ctx);
254 Create_Temp(To_F, Out_File, "tmp.XXX");
255 Create_Temp(To_F, Template => "tmp.XXX");
256 case Op is
257 when Op_Create =>
258 Has_Input_File := False;
259 when Op_Delete | Op_Patch =>
260 Has_Input_File := True;
261 KeccakBegin(In_Ctx);
262 Open(In_F, In_File, To_F_Name);
263 Open(In_F, CIO.In_File, To_F_Name);
264 end case;
265
266 Hunk_Loop:
(466 . 11)(497 . 12)
268 & "but the file has ended";
269 end if;
270 declare
271 In_Line: String := Get_Line(In_F);
272 New_Line: Boolean;
273 In_Line: String := Get_Line(In_F, New_Line);
274 begin
275 Hash_Line(In_Ctx, In_Line);
276 Hash_Line(To_Ctx, In_Line);
277 Put_Line(To_F, In_Line);
278 Hash_Line(In_Ctx, In_Line, New_Line);
279 Hash_Line(To_Ctx, In_Line, New_Line);
280 Put_Line(To_F, In_Line, New_Line);
281 Line := Line + 1;
282 end;
283 end loop;
(483 . 6)(515 . 7)
285 raise Parse with "blank line in hunk";
286 end if;
287 case C is
288
289 when '+' => -- line added
290 Get(C);
291 case Op is
(494 . 13)(527 . 20)
293 raise State with "hunk trying to add lines, "
294 & "but the line count is not valid";
295 end if;
296
297 declare
298 New_Line: Boolean := True;
299 Patch_Line: String := Get_Line;
300 begin
301 Put_Line(To_F, Patch_Line);
302 Hash_Line(To_Ctx, Patch_Line);
303 -- Last line, check for Newline directive.
304 if To_Count = 1 then
305 New_Line := not Has_No_Newline_Directive;
306 end if;
307 Put_Line(To_F, Patch_Line, New_Line);
308 Hash_Line(To_Ctx, Patch_Line, New_Line);
309 end;
310 To_Count := To_Count - 1;
311
312 when '-' => -- line deleted
313 Get(C);
314 case Op is
(515 . 17)(555 . 28)
316 raise State with "hunk trying to remove lines, "
317 & "when the input file already ended";
318 end if;
319
320 declare
321 In_Line: String := Get_Line(In_F);
322 New_Line: Boolean;
323 In_Line: String := Get_Line(In_F, New_Line);
324 Patch_Line: String := Get_Line;
325 begin
326 -- Last line, check for Newline directive.
327 if From_Count = 1 then
328 if Has_No_Newline_Directive and New_Line then
329 raise State with "input file has newline, "
330 & "while hunk claims it doesn't";
331 end if;
332 end if;
333
334 if In_Line /= Patch_Line then
335 raise State with "lines don't match";
336 end if;
337 Hash_Line(In_Ctx, In_Line);
338 Hash_Line(In_Ctx, In_Line, New_Line);
339 end;
340 Line := Line + 1;
341 From_Count := From_Count - 1;
342
343 when ' ' => -- line stays the same
344 Get(C);
345 if not Has_Input_File then
(540 . 20)(591 . 34)
347 raise State with "hunk claims identical lines, "
348 & "when input file already ended";
349 end if;
350
351 declare
352 In_Line: String := Get_Line(In_F);
353 New_Line: Boolean;
354 In_Line: String := Get_Line(In_F, New_Line);
355 Patch_Line: String := Get_Line;
356 begin
357 if In_Line /= Patch_Line then
358 raise State with "lines don't match";
359 end if;
360 Put_Line(To_F, Patch_Line);
361 Hash_Line(In_Ctx, In_Line);
362 Hash_Line(To_Ctx, In_Line);
363 if From_Count = 1 then
364 if Has_No_Newline_Directive and New_Line then
365 raise State with "input file has newline, "
366 & "while hunk claims it doesn't";
367 end if;
368 end if;
369
370 Put_Line(To_F, Patch_Line, New_Line);
371 Hash_Line(In_Ctx, In_Line, New_Line);
372 Hash_Line(To_Ctx, In_Line, New_Line);
373 end;
374 Line := Line + 1;
375 From_Count := From_Count - 1;
376 To_Count := To_Count - 1;
377
378 when '\' =>
379 Looking_At(Newline_Directive);
380 raise State with "invalid line count in hunk";
381
382 when others =>
383 raise Parse with "unexpected character "
384 & Character'Image(C)