While doing a test trying to create and press a vpatch with Linux kernel source, I discovered that vpatch cannot handle files in the press root directory1. The reason for this lies in the Path_Prefix function:
function Path_Prefix(Pathname: String;
Suffix: Positive) return String is
Pos: Natural := Pathname'Last;
begin
for I in 1..Suffix loop
Pos := Ada.Strings.Fixed.Index(Pathname, "/",
From => Pos,
Going => Ada.Strings.Backward);
if Pos = 0 then
return Pathname;
end if;
Pos := Pos - 1;
end loop;
return Pathname(Pathname'First .. Pos);
end;
The function is written in such a way that when Suffix argument is greater then the number of slash-delimited components in the path, it will incorrectly return the unmodified Pathname argument2. Even though vpatch calls Path_Prefix with Suffix of 1 only, this still triggers the failure case with files in the press directory, forcing creation of directories with the intended names of the files instead:
if Has_Input_File then
Close(In_F);
Dirs.Delete_File(To_F_Name);
else
if not Dirs.Exists(Path_Prefix(To_F_Name, 1)) then
Dirs.Create_Path(Path_Prefix(To_F_Name, 1));
end if;
end if;
My vpatch simplifies code a bit, replacing Path_Prefix with Directory_Name (after unix dirname(1)), which correctly handles the case of missing directory components of the path:
function Directory_Name(Pathname: String) return String is
Pos: Natural := Pathname'Last;
begin
Pos := Ada.Strings.Fixed.Index(Pathname, "/",
From => Pos,
Going => Ada.Strings.Backward);
if Pos = 0 then
return Dirs.Current_Directory;
end if;
return Pathname(Pathname'First .. Pos);
end;
Additionally, I fixed a bug with handling of empty vpatches - a cryptic error was thrown on reading them before:
@@ -651,6 +647,7 @@
begin
Read_Loop:
loop
+ exit Read_Loop when End_Of_File;
declare
S: String := Get_Line;
begin
@@ -659,7 +656,6 @@
H: Header := Get_Header;
begin
Process_Hunks_For_Header(H);
- exit Read_Loop when End_Of_File;
end;
else
Put_Line("Prelude: " & S);
With the fix, empty vpatch files are silently ignored. If you wish to have an explicit error in this case, please write in.
The vpatch and seal are available here:
curl 'http://bvt-trace.net/vpatches/vtools_fixes_rootdir_files.vpatch' > vtools_fixes_rootdir_files.vpatch curl 'http://bvt-trace.net/vpatches/vtools_fixes_rootdir_files.vpatch.bvt.sig' > vtools_fixes_rootdir_files.vpatch.bvt.sig