The function looks up file in tar archive and returns a tuple containing which at byte it starts and how long the file is.
Signed-off-by: Tomáš Golembiovský <[email protected]> --- v2v/utils.ml | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ v2v/utils.mli | 7 +++++++ 2 files changed, 58 insertions(+) diff --git a/v2v/utils.ml b/v2v/utils.ml index 896e16004..111dc0ea9 100644 --- a/v2v/utils.ml +++ b/v2v/utils.ml @@ -111,3 +111,54 @@ let qemu_img_version () = line; 0, 9 ) + +let find_file_in_tar tar filename = + let lines = external_command (sprintf "tar tRvf %s" (Filename.quote tar)) in + let rec loop lines = + match lines with + | [] -> raise Not_found + | line :: lines -> ( + (* Lines have the form: + * block <offset>: <perms> <owner>/<group> <size> <mdate> <mtime> <file> + *) + let elems = Str.bounded_split (Str.regexp " +") line 8 in + if List.length elems = 8 && List.hd elems = "block" then ( + let elems = Array.of_list elems in + let offset = elems.(1) in + let size = elems.(4) in + let fname = elems.(7) in + + if fname <> filename then + loop lines + else ( + let offset = + try + (* There should be a colon at the end *) + let i = String.rindex offset ':' in + if i == (String.length offset)-1 then + Int64.of_string (String.sub offset 0 i) + else + raise (Failure "colon at wrong position") + with Failure _ | Not_found -> + raise (Failure (sprintf "invalid offset returned by tar: %S" + offset)) in + + let size = + try Int64.of_string size + with Failure _ -> + raise (Failure (sprintf + "invalid size returned by tar: %S" size)) in + + (* Note: Offset is actualy block number and there is a single + * block with tar header at the beginning of the file. So skip + * the header and convert the block number to bytes before + * returning. + *) + (offset +^ 1L) *^ 512L, size + ) + ) else + raise (Failure (sprintf + "failed to parse line returned by tar: %S" line)) + ) + in + loop lines diff --git a/v2v/utils.mli b/v2v/utils.mli index a7f8b6e84..9c92d93be 100644 --- a/v2v/utils.mli +++ b/v2v/utils.mli @@ -55,3 +55,10 @@ val qemu_img_version : unit -> int * int (** Returns version of qemu-img as a tuple (major, minor). In case of error (0,9) is returned. *) + +val find_file_in_tar : string -> string -> int64 * int64 +(** [find_file_in_tar tar filename] looks up file in [tar] archive and returns + a tuple containing at which byte it starts and how long the file is. + + Function raises [Not_found] if there is no such file inside [tar] and + [Failure] if there is any error parsing the tar output. *) -- 2.11.0 _______________________________________________ Libguestfs mailing list [email protected] https://www.redhat.com/mailman/listinfo/libguestfs
