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ý <tgolembi(a)redhat.com>
---
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