wasmer_cli/utils/
unpack.rs1#![allow(unused)]
2
3use crate::common::normalize_path;
4use std::path::{Path, PathBuf};
5
6pub fn try_unpack_targz<P: AsRef<Path>>(
9 target_targz_path: P,
10 target_path: P,
11 strip_toplevel: bool,
12) -> Result<PathBuf, anyhow::Error> {
13 let target_targz_path = target_targz_path.as_ref().to_string_lossy().to_string();
14 let target_targz_path = normalize_path(&target_targz_path);
15 let target_targz_path = Path::new(&target_targz_path);
16
17 let target_path = target_path.as_ref().to_string_lossy().to_string();
18 let target_path = normalize_path(&target_path);
19 let target_path = Path::new(&target_path);
20
21 let open_file = || {
22 std::fs::File::open(target_targz_path)
23 .map_err(|e| anyhow::anyhow!("failed to open {}: {e}", target_targz_path.display()))
24 };
25
26 let try_decode_gz = || {
27 let file = open_file()?;
28 let gz_decoded = flate2::read::GzDecoder::new(&file);
29 let ar = tar::Archive::new(gz_decoded);
30 if strip_toplevel {
31 unpack_sans_parent(ar, target_path).map_err(|e| {
32 anyhow::anyhow!(
33 "failed to unpack (gz_ar_unpack_sans_parent) {}: {e}",
34 target_targz_path.display()
35 )
36 })
37 } else {
38 unpack_with_parent(ar, target_path).map_err(|e| {
39 anyhow::anyhow!(
40 "failed to unpack (gz_ar_unpack) {}: {e}",
41 target_targz_path.display()
42 )
43 })
44 }
45 };
46
47 let try_decode_xz = || {
48 let file = open_file()?;
49 let mut decomp: Vec<u8> = Vec::new();
50 let mut bufread = std::io::BufReader::new(&file);
51 lzma_rs::xz_decompress(&mut bufread, &mut decomp).map_err(|e| {
52 anyhow::anyhow!(
53 "failed to unpack (try_decode_xz) {}: {e}",
54 target_targz_path.display()
55 )
56 })?;
57
58 let cursor = std::io::Cursor::new(decomp);
59 let mut ar = tar::Archive::new(cursor);
60 if strip_toplevel {
61 unpack_sans_parent(ar, target_path).map_err(|e| {
62 anyhow::anyhow!(
63 "failed to unpack (sans parent) {}: {e}",
64 target_targz_path.display()
65 )
66 })
67 } else {
68 ar.unpack(target_path).map_err(|e| {
69 anyhow::anyhow!(
70 "failed to unpack (with parent) {}: {e}",
71 target_targz_path.display()
72 )
73 })
74 }
75 };
76
77 try_decode_gz().or_else(|e1| {
78 try_decode_xz()
79 .map_err(|e2| anyhow::anyhow!("could not decode gz: {e1}, could not decode xz: {e2}"))
80 })?;
81
82 Ok(Path::new(&target_targz_path).to_path_buf())
83}
84
85pub fn unpack_with_parent<R>(mut archive: tar::Archive<R>, dst: &Path) -> Result<(), anyhow::Error>
86where
87 R: std::io::Read,
88{
89 use std::path::Component::Normal;
90
91 let dst_normalized = normalize_path(dst.to_string_lossy().as_ref());
92
93 for entry in archive.entries()? {
94 let mut entry = entry?;
95 let path: PathBuf = entry
96 .path()?
97 .components()
98 .skip(1) .filter(|c| matches!(c, Normal(_))) .collect();
101 if entry.header().entry_type().is_file() {
102 entry.unpack_in(&dst_normalized)?;
103 } else if entry.header().entry_type() == tar::EntryType::Directory {
104 std::fs::create_dir_all(Path::new(&dst_normalized).join(&path))?;
105 }
106 }
107 Ok(())
108}
109
110pub fn unpack_sans_parent<R>(mut archive: tar::Archive<R>, dst: &Path) -> std::io::Result<()>
111where
112 R: std::io::Read,
113{
114 use std::path::Component::Normal;
115
116 let dst_normalized = normalize_path(dst.to_string_lossy().as_ref());
117
118 for entry in archive.entries()? {
119 let mut entry = entry?;
120 let path: PathBuf = entry
121 .path()?
122 .components()
123 .skip(1) .filter(|c| matches!(c, Normal(_))) .collect();
126 entry.unpack(Path::new(&dst_normalized).join(path))?;
127 }
128 Ok(())
129}