aboutsummaryrefslogtreecommitdiff
path: root/bpkg/pkg-unpack.cxx
diff options
context:
space:
mode:
authorBoris Kolpackov <boris@codesynthesis.com>2017-05-01 11:02:36 +0200
committerBoris Kolpackov <boris@codesynthesis.com>2017-05-01 11:02:36 +0200
commit5fb0df6f63e02c141e8a0e5ad4543dea525df3fc (patch)
tree5063cce50ab142650ae8090f95bc5a4ed6f308bf /bpkg/pkg-unpack.cxx
parent7263a091971f42a611f5b03239135e8c3ef9bb47 (diff)
Reimplement tar invocations to do manual decompression
This is needed to prevent tar from forking, which doesn't work reliably on MSYS2.
Diffstat (limited to 'bpkg/pkg-unpack.cxx')
-rw-r--r--bpkg/pkg-unpack.cxx56
1 files changed, 48 insertions, 8 deletions
diff --git a/bpkg/pkg-unpack.cxx b/bpkg/pkg-unpack.cxx
index d4a255c..9aead38 100644
--- a/bpkg/pkg-unpack.cxx
+++ b/bpkg/pkg-unpack.cxx
@@ -163,7 +163,30 @@ namespace bpkg
//
auto_rm_r arm (d);
- cstrings args {co.tar ().string ().c_str ()};
+ cstrings args;
+
+ // See if we need to decompress.
+ //
+ {
+ string e (a.extension ());
+
+ if (e == "gz") args.push_back ("gzip");
+ else if (e == "bzip2") args.push_back ("bzip2");
+ else if (e == "xz") args.push_back ("xz");
+ else if (e != "tar")
+ fail << "unknown compression method in package " << a;
+ }
+
+ size_t i (0); // The tar command line start.
+ if (!args.empty ())
+ {
+ args.push_back ("-dc");
+ args.push_back (a.string ().c_str ());
+ args.push_back (nullptr);
+ i = args.size ();
+ }
+
+ args.push_back (co.tar ().string ().c_str ());
// Add extra options.
//
@@ -185,28 +208,45 @@ namespace bpkg
#endif
args.push_back ("-xf");
- args.push_back (a.string ().c_str ());
+ args.push_back (i == 0 ? a.string ().c_str () : "-");
args.push_back (nullptr);
+ args.push_back (nullptr); // Pipe end.
+ size_t what;
try
{
- process_path pp (process::path_search (args[0]));
+ process_path dpp;
+ process_path tpp;
+
+ process dpr;
+ process tpr;
+
+ if (i != 0)
+ dpp = process::path_search (args[what = 0]);
+
+ tpp = process::path_search (args[what = i]);
if (verb >= 2)
print_process (args);
- process pr (pp, args.data ());
+ if (i != 0)
+ {
+ dpr = process (dpp, &args[what = 0], 0, -1);
+ tpr = process (tpp, &args[what = i], dpr);
+ }
+ else
+ tpr = process (tpp, &args[what = 0]);
// While it is reasonable to assuming the child process issued
- // diagnostics, tar, specifically, doesn't mention the archive
- // name.
+ // diagnostics, tar, specifically, doesn't mention the archive name.
//
- if (!pr.wait ())
+ if (!(what = i, tpr.wait ()) ||
+ !(what = 0, dpr.wait ()))
fail << "unable to extract package archive " << a;
}
catch (const process_error& e)
{
- error << "unable to execute " << args[0] << ": " << e;
+ error << "unable to execute " << args[what] << ": " << e;
if (e.child)
exit (1);