diff --git a/v2v/input_ova.ml b/v2v/input_ova.ml
index 4f848e2..492b934 100644
--- a/v2v/input_ova.ml
+++ b/v2v/input_ova.ml
@@ -39,11 +39,11 @@ object
 
   method source () =
     (* Extract ova file. *)
-    let exploded =
+    let exploded, partial =
       (* The spec allows a directory to be specified as an ova.  This
        * is also pretty convenient.
        *)
-      if is_directory ova then ova
+      if is_directory ova then ova, false
       else (
         let uncompress_head zcat file =
           let cmd = sprintf "%s %s" zcat (quote file) in
@@ -66,11 +66,18 @@ object
           if run_command cmd <> 0 then
             error (f_"error unpacking %s, see earlier error messages") ova in
 
+        let untar_partial file outdir =
+          let cmd1 = [ "tar"; "-tf" ; file ] in
+          let cmd2 = [ "grep"; "\\.\\(ovf\\|mf\\)$" ] in
+          let cmd3 = [ "xargs"; "tar"; "-xf" ; file; "-C"; outdir ] in
+          if shell_command ((stringify_args cmd1) ^ " | " ^ (stringify_args cmd2) ^ " | " ^ (stringify_args cmd3)) <> 0 then
+            error (f_"error unpacking %s, see earlier error messages") ova in
+
         match detect_file_type ova with
         | `Tar ->
           (* Normal ovas are tar file (not compressed). *)
-          untar ova tmpdir;
-          tmpdir
+          untar_partial ova tmpdir;
+          tmpdir, true
         | `Zip ->
           (* However, although not permitted by the spec, people ship
            * zip files as ova too.
@@ -80,7 +87,7 @@ object
             [ "-j"; "-d"; tmpdir; ova ] in
           if run_command cmd <> 0 then
             error (f_"error unpacking %s, see earlier error messages") ova;
-          tmpdir
+          tmpdir, false
         | (`GZip|`XZ) as format ->
           let zcat, tar_fmt =
             match format with
@@ -93,7 +100,7 @@ object
           (match tmpfiletype with
           | `Tar ->
             untar ~format:tar_fmt ova tmpdir;
-            tmpdir
+            tmpdir, false
           | `Zip | `GZip | `XZ | `Unknown ->
             error (f_"%s: unsupported file format\n\nFormats which we currently understand for '-i ova' are: tar (uncompressed, compress with gzip or xz), zip") ova
           )
@@ -121,6 +128,40 @@ object
       loop [dir]
     in
 
+    (* Find file in [tar] archive and return at which byte it starts and how
+     * long it is.
+     *)
+    let find_file_in_tar tar filename =
+      let cmd1 = [ "tar"; "tRvf"; tar ] in
+      let cmd2 = [ "awk"; sprintf
+        "$8 == \"%s\" {print substr($2, 1, index($2, \":\")-1), $5}"
+        filename ]
+      in
+      let lines =
+        external_command ((stringify_args cmd1) ^ " | " ^ (stringify_args cmd2))
+      in
+      if (List.length lines < 1) then
+        raise Not_found
+      else
+        let soffset, ssize = String.split " " (List.hd lines) in
+        let offset =
+          try int_of_string soffset
+          with Failure "int_of_string" ->
+            error (f_"Invalid offset returned by `tar`: %s") soffset
+        in
+        let size =
+          try int_of_string ssize
+          with Failure "int_of_string" ->
+            error (f_"Invalid size returend by `tar': %s") ssize
+        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+1)*512, size
+    in
+
+
     (* Search for the ovf file. *)
     let ovf = find_files exploded ".ovf" in
     let ovf =
@@ -132,6 +173,8 @@ object
         error (f_"more than one .ovf file was found in %s") ova in
 
     (* Read any .mf (manifest) files and verify sha1. *)
+    (* TODO: this won't work once the code is fixed and actualy starts
+     * verifying hashes. *)
     let mf = find_files exploded ".mf" in
     let rex = Str.regexp "SHA1(\\(.*\\))=\\([0-9a-fA-F]+\\)\r?" in
     List.iter (
@@ -264,14 +307,30 @@ object
             | Some s -> s in
 
           (* Does the file exist and is it readable? *)
-          let filename = ovf_folder // filename in
-          Unix.access filename [Unix.R_OK];
+          let filename =
+            if not partial then (
+              let filename = ovf_folder // filename in
+              Unix.access filename [Unix.R_OK];
+              filename
+            )
+            else (
+              let start, offset =
+                try find_file_in_tar ova filename
+                with Not_found ->
+                  error "File '%s' not found in the tar archive" filename
+              in
+              sprintf
+                "json:{ \"file.filename\":\"%s\", \"file.offset\":\"%d\", \"file.size\":\"%d\"}"
+                ova start offset
+            )
+          in
 
           (* The spec allows the file to be gzip-compressed, in which case
            * we must uncompress it into the tmpdir.
            *)
           let filename =
-            if detect_file_type filename = `GZip then (
+            (* TODO: partial + compressed? *)
+            if not partial && (detect_file_type filename = `GZip) then (
               let new_filename = tmpdir // String.random8 () ^ ".vmdk" in
               let cmd =
                 sprintf "zcat %s > %s" (quote filename) (quote new_filename) in
