From efaf570aaa4f21d45028bcaa8dbe8c143b0f9e77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=A9dric=20Bosdonnat?= Date: Tue, 21 Nov 2017 16:10:56 +0100 Subject: [PATCH] builder: add a template parameter to get_index get_index now gets a new template parameter. Setting it to true will make the index parsing less picky about missing important data. This can be used to parse a partial index file. --- builder/index_parser.ml | 51 +++++++++++++++++++++++++++++++++------- builder/index_parser.mli | 5 +++- 2 files changed, 47 insertions(+), 9 deletions(-) diff --git a/builder/index_parser.ml b/builder/index_parser.ml index d79c807e4..79653a91b 100644 --- a/builder/index_parser.ml +++ b/builder/index_parser.ml @@ -25,7 +25,7 @@ open Utils open Printf open Unix -let get_index ~downloader ~sigchecker { Sources.uri; proxy } = +let get_index ~downloader ~sigchecker ?(template = false) { Sources.uri; proxy } = let corrupt_file () = error (f_"The index file downloaded from ‘%s’ is corrupt.\nYou need to ask the supplier of this file to fix it and upload a fixed version.") uri in @@ -99,8 +99,23 @@ let get_index ~downloader ~sigchecker { Sources.uri; proxy } = let arch = try Index.Arch (List.assoc ("arch", None) fields) with Not_found -> - eprintf (f_"%s: no ‘arch’ entry for ‘%s’\n") prog n; - corrupt_file () in + if template then + let g = open_guestfs ~identifier:"template" () in + g#add_drive_ro file_uri; + g#launch (); + let roots = g#inspect_os () in + let nroots = Array.length roots in + if nroots <> 1 then ( + eprintf (f_"%s: no ‘arch’ entry for %s and failed to guess it\n") prog n; + corrupt_file () + ); + let inspected_arch = g#inspect_get_arch (Array.get roots 0) in + g#close(); + Index.GuessedArch inspected_arch + else ( + eprintf (f_"%s: no ‘arch’ entry for ‘%s’\n") prog n; + corrupt_file () + ) in let signature_uri = try Some (make_absolute_uri (List.assoc ("sig", None) fields)) with Not_found -> None in @@ -112,21 +127,41 @@ let get_index ~downloader ~sigchecker { Sources.uri; proxy } = let revision = try Rev_int (int_of_string (List.assoc ("revision", None) fields)) with - | Not_found -> Rev_int 1 + | Not_found -> if template then Rev_int 0 else Rev_int 1 | Failure _ -> eprintf (f_"%s: cannot parse ‘revision’ field for ‘%s’\n") prog n; corrupt_file () in let format = try Some (List.assoc ("format", None) fields) with Not_found -> None in let size = + let get_image_size filepath = + (* If a compressed image manages to reach this code, qemu-img just + returns a virtual-size equal to actual-size *) + match detect_file_type filepath with + | `Unknown -> + let infos = Utils.get_image_infos filepath in + Yajl.object_get_number "virtual-size" infos + | `XZ | `GZip | `Tar | ` Zip -> + eprintf (f_"%s: cannot determine the virtual size of %s due to compression") + prog filepath; + corrupt_file () in + try Int64.of_string (List.assoc ("size", None) fields) with | Not_found -> - eprintf (f_"%s: no ‘size’ field for ‘%s’\n") prog n; - corrupt_file () + if template then + get_image_size file_uri + else ( + eprintf (f_"%s: no ‘size’ field for ‘%s’\n") prog n; + corrupt_file () + ) | Failure _ -> - eprintf (f_"%s: cannot parse ‘size’ field for ‘%s’\n") prog n; - corrupt_file () in + if template then + get_image_size file_uri + else ( + eprintf (f_"%s: cannot parse ‘size’ field for ‘%s’\n") prog n; + corrupt_file () + ) in let compressed_size = try Some (Int64.of_string (List.assoc ("compressed_size", None) fields)) with diff --git a/builder/index_parser.mli b/builder/index_parser.mli index f77ae9376..dc6b0b407 100644 --- a/builder/index_parser.mli +++ b/builder/index_parser.mli @@ -16,7 +16,10 @@ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. *) -val get_index : downloader:Downloader.t -> sigchecker:Sigchecker.t -> Sources.source -> Index.index +val get_index : downloader:Downloader.t -> sigchecker:Sigchecker.t -> ?template:bool -> Sources.source -> Index.index +(** [get_index download sigchecker template source] will parse the source + index file into an index entry list. If the template flag is set to + true, the parser will be less picky about missing values. *) val write_entry : out_channel -> (string * Index.entry) -> unit (** [write_entry chan entry] writes the index entry to the chan output