adb: add interfaces for Encoder/Decoder.
More groundwork to support more compression algorithms.
Bug: https://issuetracker.google.com/150827486
Test: python3 -m unittest test_device.FileOperationsTest{Uncompressed,Brotli}
Change-Id: I638493083b83e3f6c6854b631471e9d6b50bd79f
diff --git a/adb/client/adb_install.cpp b/adb/client/adb_install.cpp
index 092a866..f022b8b 100644
--- a/adb/client/adb_install.cpp
+++ b/adb/client/adb_install.cpp
@@ -290,7 +290,7 @@
}
}
- if (do_sync_push(apk_file, apk_dest.c_str(), false, true)) {
+ if (do_sync_push(apk_file, apk_dest.c_str(), false, CompressionType::Any)) {
result = pm_command(argc, argv);
delete_device_file(apk_dest);
}
diff --git a/adb/client/bugreport.cpp b/adb/client/bugreport.cpp
index ab93f7d..e162aaa 100644
--- a/adb/client/bugreport.cpp
+++ b/adb/client/bugreport.cpp
@@ -282,5 +282,5 @@
bool Bugreport::DoSyncPull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
const char* name) {
- return do_sync_pull(srcs, dst, copy_attrs, false, name);
+ return do_sync_pull(srcs, dst, copy_attrs, CompressionType::None, name);
}
diff --git a/adb/client/commandline.cpp b/adb/client/commandline.cpp
index 04b250d..9078ae9 100644
--- a/adb/client/commandline.cpp
+++ b/adb/client/commandline.cpp
@@ -129,20 +129,20 @@
" reverse --remove-all remove all reverse socket connections from device\n"
"\n"
"file transfer:\n"
- " push [--sync] [-zZ] LOCAL... REMOTE\n"
+ " push [--sync] [-z ALGORITHM] [-Z] LOCAL... REMOTE\n"
" copy local files/directories to device\n"
" --sync: only push files that are newer on the host than the device\n"
- " -z: enable compression\n"
+ " -z: enable compression with a specified algorithm (any, none, brotli)\n"
" -Z: disable compression\n"
- " pull [-azZ] REMOTE... LOCAL\n"
+ " pull [-a] [-z ALGORITHM] [-Z] REMOTE... LOCAL\n"
" copy files/dirs from device\n"
" -a: preserve file timestamp and mode\n"
- " -z: enable compression\n"
+ " -z: enable compression with a specified algorithm (any, none, brotli)\n"
" -Z: disable compression\n"
- " sync [-lzZ] [all|data|odm|oem|product|system|system_ext|vendor]\n"
+ " sync [-l] [-z ALGORITHM] [-Z] [all|data|odm|oem|product|system|system_ext|vendor]\n"
" sync a local build from $ANDROID_PRODUCT_OUT to the device (default all)\n"
" -l: list files that would be copied, but don't copy them\n"
- " -z: enable compression\n"
+ " -z: enable compression with a specified algorithm (any, none, brotli)\n"
" -Z: disable compression\n"
"\n"
"shell:\n"
@@ -1314,12 +1314,34 @@
return 0;
}
+static CompressionType parse_compression_type(const std::string& str, bool allow_numbers) {
+ if (allow_numbers) {
+ if (str == "0") {
+ return CompressionType::None;
+ } else if (str == "1") {
+ return CompressionType::Any;
+ }
+ }
+
+ if (str == "any") {
+ return CompressionType::Any;
+ } else if (str == "none") {
+ return CompressionType::None;
+ }
+
+ if (str == "brotli") {
+ return CompressionType::Brotli;
+ }
+
+ error_exit("unexpected compression type %s", str.c_str());
+}
+
static void parse_push_pull_args(const char** arg, int narg, std::vector<const char*>* srcs,
- const char** dst, bool* copy_attrs, bool* sync, bool* compressed) {
+ const char** dst, bool* copy_attrs, bool* sync,
+ CompressionType* compression) {
*copy_attrs = false;
- const char* adb_compression = getenv("ADB_COMPRESSION");
- if (adb_compression && strcmp(adb_compression, "0") == 0) {
- *compressed = false;
+ if (const char* adb_compression = getenv("ADB_COMPRESSION")) {
+ *compression = parse_compression_type(adb_compression, true);
}
srcs->clear();
@@ -1333,13 +1355,13 @@
} else if (!strcmp(*arg, "-a")) {
*copy_attrs = true;
} else if (!strcmp(*arg, "-z")) {
- if (compressed != nullptr) {
- *compressed = true;
+ if (narg < 2) {
+ error_exit("-z requires an argument");
}
+ *compression = parse_compression_type(*++arg, false);
+ --narg;
} else if (!strcmp(*arg, "-Z")) {
- if (compressed != nullptr) {
- *compressed = false;
- }
+ *compression = CompressionType::None;
} else if (!strcmp(*arg, "--sync")) {
if (sync != nullptr) {
*sync = true;
@@ -1894,22 +1916,22 @@
} else if (!strcmp(argv[0], "push")) {
bool copy_attrs = false;
bool sync = false;
- bool compressed = true;
+ CompressionType compression = CompressionType::Any;
std::vector<const char*> srcs;
const char* dst = nullptr;
- parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compressed);
+ parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, &sync, &compression);
if (srcs.empty() || !dst) error_exit("push requires an argument");
- return do_sync_push(srcs, dst, sync, compressed) ? 0 : 1;
+ return do_sync_push(srcs, dst, sync, compression) ? 0 : 1;
} else if (!strcmp(argv[0], "pull")) {
bool copy_attrs = false;
- bool compressed = true;
+ CompressionType compression = CompressionType::Any;
std::vector<const char*> srcs;
const char* dst = ".";
- parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compressed);
+ parse_push_pull_args(&argv[1], argc - 1, &srcs, &dst, ©_attrs, nullptr, &compression);
if (srcs.empty()) error_exit("pull requires an argument");
- return do_sync_pull(srcs, dst, copy_attrs, compressed) ? 0 : 1;
+ return do_sync_pull(srcs, dst, copy_attrs, compression) ? 0 : 1;
} else if (!strcmp(argv[0], "install")) {
if (argc < 2) error_exit("install requires an argument");
return install_app(argc, argv);
@@ -1925,27 +1947,26 @@
} else if (!strcmp(argv[0], "sync")) {
std::string src;
bool list_only = false;
- bool compressed = true;
+ CompressionType compression = CompressionType::Any;
- const char* adb_compression = getenv("ADB_COMPRESSION");
- if (adb_compression && strcmp(adb_compression, "0") == 0) {
- compressed = false;
+ if (const char* adb_compression = getenv("ADB_COMPRESSION"); adb_compression) {
+ compression = parse_compression_type(adb_compression, true);
}
int opt;
- while ((opt = getopt(argc, const_cast<char**>(argv), "lzZ")) != -1) {
+ while ((opt = getopt(argc, const_cast<char**>(argv), "lz:Z")) != -1) {
switch (opt) {
case 'l':
list_only = true;
break;
case 'z':
- compressed = true;
+ compression = parse_compression_type(optarg, false);
break;
case 'Z':
- compressed = false;
+ compression = CompressionType::None;
break;
default:
- error_exit("usage: adb sync [-lzZ] [PARTITION]");
+ error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]");
}
}
@@ -1954,7 +1975,7 @@
} else if (optind + 1 == argc) {
src = argv[optind];
} else {
- error_exit("usage: adb sync [-lzZ] [PARTITION]");
+ error_exit("usage: adb sync [-l] [-z ALGORITHM] [-Z] [PARTITION]");
}
std::vector<std::string> partitions{"data", "odm", "oem", "product",
@@ -1965,7 +1986,7 @@
std::string src_dir{product_file(partition)};
if (!directory_exists(src_dir)) continue;
found = true;
- if (!do_sync_sync(src_dir, "/" + partition, list_only, compressed)) return 1;
+ if (!do_sync_sync(src_dir, "/" + partition, list_only, compression)) return 1;
}
}
if (!found) error_exit("don't know how to sync %s partition", src.c_str());
diff --git a/adb/client/fastdeploy.cpp b/adb/client/fastdeploy.cpp
index de82e14..37f1a90 100644
--- a/adb/client/fastdeploy.cpp
+++ b/adb/client/fastdeploy.cpp
@@ -112,7 +112,7 @@
// but can't be removed until after the push.
unix_close(tf.release());
- if (!do_sync_push(srcs, dst, sync, true)) {
+ if (!do_sync_push(srcs, dst, sync, CompressionType::Any)) {
error_exit("Failed to push fastdeploy agent to device.");
}
}
diff --git a/adb/client/file_sync_client.cpp b/adb/client/file_sync_client.cpp
index 2ed58b2..c71880c 100644
--- a/adb/client/file_sync_client.cpp
+++ b/adb/client/file_sync_client.cpp
@@ -34,6 +34,7 @@
#include <memory>
#include <sstream>
#include <string>
+#include <variant>
#include <vector>
#include "sysdeps.h"
@@ -262,6 +263,18 @@
bool HaveSendRecv2() const { return have_sendrecv_v2_; }
bool HaveSendRecv2Brotli() const { return have_sendrecv_v2_brotli_; }
+ // Resolve a compression type which might be CompressionType::Any to a specific compression
+ // algorithm.
+ CompressionType ResolveCompressionType(CompressionType compression) const {
+ if (compression == CompressionType::Any) {
+ if (HaveSendRecv2Brotli()) {
+ return CompressionType::Brotli;
+ }
+ return CompressionType::None;
+ }
+ return compression;
+ }
+
const FeatureSet& Features() const { return features_; }
bool IsValid() { return fd >= 0; }
@@ -323,7 +336,7 @@
return WriteFdExactly(fd, buf.data(), buf.size());
}
- bool SendSend2(std::string_view path, mode_t mode, bool compressed) {
+ bool SendSend2(std::string_view path, mode_t mode, CompressionType compression) {
if (path.length() > 1024) {
Error("SendRequest failed: path too long: %zu", path.length());
errno = ENAMETOOLONG;
@@ -339,7 +352,18 @@
syncmsg msg;
msg.send_v2_setup.id = ID_SEND_V2;
msg.send_v2_setup.mode = mode;
- msg.send_v2_setup.flags = compressed ? kSyncFlagBrotli : kSyncFlagNone;
+ msg.send_v2_setup.flags = 0;
+ switch (compression) {
+ case CompressionType::None:
+ break;
+
+ case CompressionType::Brotli:
+ msg.send_v2_setup.flags = kSyncFlagBrotli;
+ break;
+
+ case CompressionType::Any:
+ LOG(FATAL) << "unexpected CompressionType::Any";
+ }
buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.send_v2_setup));
@@ -352,7 +376,7 @@
return WriteFdExactly(fd, buf.data(), buf.size());
}
- bool SendRecv2(const std::string& path) {
+ bool SendRecv2(const std::string& path, CompressionType compression) {
if (path.length() > 1024) {
Error("SendRequest failed: path too long: %zu", path.length());
errno = ENAMETOOLONG;
@@ -367,7 +391,18 @@
syncmsg msg;
msg.recv_v2_setup.id = ID_RECV_V2;
- msg.recv_v2_setup.flags = kSyncFlagBrotli;
+ msg.recv_v2_setup.flags = 0;
+ switch (compression) {
+ case CompressionType::None:
+ break;
+
+ case CompressionType::Brotli:
+ msg.recv_v2_setup.flags |= kSyncFlagBrotli;
+ break;
+
+ case CompressionType::Any:
+ LOG(FATAL) << "unexpected CompressionType::Any";
+ }
buf.resize(sizeof(SyncRequest) + path.length() + sizeof(msg.recv_v2_setup));
@@ -533,9 +568,15 @@
return true;
}
- bool SendLargeFileCompressed(const std::string& path, mode_t mode, const std::string& lpath,
- const std::string& rpath, unsigned mtime) {
- if (!SendSend2(path, mode, true)) {
+ bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath,
+ const std::string& rpath, unsigned mtime, CompressionType compression) {
+ if (!HaveSendRecv2()) {
+ return SendLargeFileLegacy(path, mode, lpath, rpath, mtime);
+ }
+
+ compression = ResolveCompressionType(compression);
+
+ if (!SendSend2(path, mode, compression)) {
Error("failed to send ID_SEND_V2 message '%s': %s", path.c_str(), strerror(errno));
return false;
}
@@ -558,7 +599,21 @@
syncsendbuf sbuf;
sbuf.id = ID_DATA;
- BrotliEncoder<SYNC_DATA_MAX> encoder;
+ std::variant<std::monostate, NullEncoder, BrotliEncoder> encoder_storage;
+ Encoder* encoder = nullptr;
+ switch (compression) {
+ case CompressionType::None:
+ encoder = &encoder_storage.emplace<NullEncoder>(SYNC_DATA_MAX);
+ break;
+
+ case CompressionType::Brotli:
+ encoder = &encoder_storage.emplace<BrotliEncoder>(SYNC_DATA_MAX);
+ break;
+
+ case CompressionType::Any:
+ LOG(FATAL) << "unexpected CompressionType::Any";
+ }
+
bool sending = true;
while (sending) {
Block input(SYNC_DATA_MAX);
@@ -569,10 +624,10 @@
}
if (r == 0) {
- encoder.Finish();
+ encoder->Finish();
} else {
input.resize(r);
- encoder.Append(std::move(input));
+ encoder->Append(std::move(input));
RecordBytesTransferred(r);
bytes_copied += r;
ReportProgress(rpath, bytes_copied, total_size);
@@ -580,7 +635,7 @@
while (true) {
Block output;
- EncodeResult result = encoder.Encode(&output);
+ EncodeResult result = encoder->Encode(&output);
if (result == EncodeResult::Error) {
Error("compressing '%s' locally failed", lpath.c_str());
return false;
@@ -610,12 +665,8 @@
return WriteOrDie(lpath, rpath, &msg.data, sizeof(msg.data));
}
- bool SendLargeFile(const std::string& path, mode_t mode, const std::string& lpath,
- const std::string& rpath, unsigned mtime, bool compressed) {
- if (compressed && HaveSendRecv2Brotli()) {
- return SendLargeFileCompressed(path, mode, lpath, rpath, mtime);
- }
-
+ bool SendLargeFileLegacy(const std::string& path, mode_t mode, const std::string& lpath,
+ const std::string& rpath, unsigned mtime) {
std::string path_and_mode = android::base::StringPrintf("%s,%d", path.c_str(), mode);
if (!SendRequest(ID_SEND_V1, path_and_mode)) {
Error("failed to send ID_SEND_V1 message '%s': %s", path_and_mode.c_str(),
@@ -921,7 +972,7 @@
}
static bool sync_send(SyncConnection& sc, const std::string& lpath, const std::string& rpath,
- unsigned mtime, mode_t mode, bool sync, bool compressed) {
+ unsigned mtime, mode_t mode, bool sync, CompressionType compression) {
if (sync) {
struct stat st;
if (sync_lstat(sc, rpath, &st)) {
@@ -964,7 +1015,7 @@
return false;
}
} else {
- if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compressed)) {
+ if (!sc.SendLargeFile(rpath, mode, lpath, rpath, mtime, compression)) {
return false;
}
}
@@ -1027,8 +1078,10 @@
}
static bool sync_recv_v2(SyncConnection& sc, const char* rpath, const char* lpath, const char* name,
- uint64_t expected_size) {
- if (!sc.SendRecv2(rpath)) return false;
+ uint64_t expected_size, CompressionType compression) {
+ compression = sc.ResolveCompressionType(compression);
+
+ if (!sc.SendRecv2(rpath, compression)) return false;
adb_unlink(lpath);
unique_fd lfd(adb_creat(lpath, 0644));
@@ -1040,9 +1093,24 @@
uint64_t bytes_copied = 0;
Block buffer(SYNC_DATA_MAX);
- BrotliDecoder decoder(std::span(buffer.data(), buffer.size()));
- bool reading = true;
- while (reading) {
+ std::variant<std::monostate, NullDecoder, BrotliDecoder> decoder_storage;
+ Decoder* decoder = nullptr;
+
+ std::span buffer_span(buffer.data(), buffer.size());
+ switch (compression) {
+ case CompressionType::None:
+ decoder = &decoder_storage.emplace<NullDecoder>(buffer_span);
+ break;
+
+ case CompressionType::Brotli:
+ decoder = &decoder_storage.emplace<BrotliDecoder>(buffer_span);
+ break;
+
+ case CompressionType::Any:
+ LOG(FATAL) << "unexpected CompressionType::Any";
+ }
+
+ while (true) {
syncmsg msg;
if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
adb_unlink(lpath);
@@ -1050,33 +1118,32 @@
}
if (msg.data.id == ID_DONE) {
- adb_unlink(lpath);
- sc.Error("unexpected ID_DONE");
- return false;
- }
-
- if (msg.data.id != ID_DATA) {
+ if (!decoder->Finish()) {
+ sc.Error("unexpected ID_DONE");
+ return false;
+ }
+ } else if (msg.data.id != ID_DATA) {
adb_unlink(lpath);
sc.ReportCopyFailure(rpath, lpath, msg);
return false;
- }
+ } else {
+ if (msg.data.size > sc.max) {
+ sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
+ adb_unlink(lpath);
+ return false;
+ }
- if (msg.data.size > sc.max) {
- sc.Error("msg.data.size too large: %u (max %zu)", msg.data.size, sc.max);
- adb_unlink(lpath);
- return false;
+ Block block(msg.data.size);
+ if (!ReadFdExactly(sc.fd, block.data(), msg.data.size)) {
+ adb_unlink(lpath);
+ return false;
+ }
+ decoder->Append(std::move(block));
}
- Block block(msg.data.size);
- if (!ReadFdExactly(sc.fd, block.data(), msg.data.size)) {
- adb_unlink(lpath);
- return false;
- }
- decoder.Append(std::move(block));
-
while (true) {
std::span<char> output;
- DecodeResult result = decoder.Decode(&output);
+ DecodeResult result = decoder->Decode(&output);
if (result == DecodeResult::Error) {
sc.Error("decompress failed");
@@ -1102,33 +1169,19 @@
} else if (result == DecodeResult::MoreOutput) {
continue;
} else if (result == DecodeResult::Done) {
- reading = false;
- break;
+ sc.RecordFilesTransferred(1);
+ return true;
} else {
LOG(FATAL) << "invalid DecodeResult: " << static_cast<int>(result);
}
}
}
-
- syncmsg msg;
- if (!ReadFdExactly(sc.fd, &msg.data, sizeof(msg.data))) {
- sc.Error("failed to read ID_DONE");
- return false;
- }
-
- if (msg.data.id != ID_DONE) {
- sc.Error("unexpected message after transfer: id = %d (expected ID_DONE)", msg.data.id);
- return false;
- }
-
- sc.RecordFilesTransferred(1);
- return true;
}
static bool sync_recv(SyncConnection& sc, const char* rpath, const char* lpath, const char* name,
- uint64_t expected_size, bool compressed) {
- if (sc.HaveSendRecv2() && compressed) {
- return sync_recv_v2(sc, rpath, lpath, name, expected_size);
+ uint64_t expected_size, CompressionType compression) {
+ if (sc.HaveSendRecv2()) {
+ return sync_recv_v2(sc, rpath, lpath, name, expected_size, compression);
} else {
return sync_recv_v1(sc, rpath, lpath, name, expected_size);
}
@@ -1210,7 +1263,8 @@
}
static bool copy_local_dir_remote(SyncConnection& sc, std::string lpath, std::string rpath,
- bool check_timestamps, bool list_only, bool compressed) {
+ bool check_timestamps, bool list_only,
+ CompressionType compression) {
sc.NewTransfer();
// Make sure that both directory paths end in a slash.
@@ -1292,7 +1346,7 @@
if (list_only) {
sc.Println("would push: %s -> %s", ci.lpath.c_str(), ci.rpath.c_str());
} else {
- if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compressed)) {
+ if (!sync_send(sc, ci.lpath, ci.rpath, ci.time, ci.mode, false, compression)) {
return false;
}
}
@@ -1308,7 +1362,7 @@
}
bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync,
- bool compressed) {
+ CompressionType compression) {
SyncConnection sc;
if (!sc.IsValid()) return false;
@@ -1373,7 +1427,7 @@
dst_dir.append(android::base::Basename(src_path));
}
- success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compressed);
+ success &= copy_local_dir_remote(sc, src_path, dst_dir, sync, false, compression);
continue;
} else if (!should_push_file(st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, st.st_mode);
@@ -1394,7 +1448,7 @@
sc.NewTransfer();
sc.SetExpectedTotalBytes(st.st_size);
- success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compressed);
+ success &= sync_send(sc, src_path, dst_path, st.st_mtime, st.st_mode, sync, compression);
sc.ReportTransferRate(src_path, TransferDirection::push);
}
@@ -1480,7 +1534,7 @@
}
static bool copy_remote_dir_local(SyncConnection& sc, std::string rpath, std::string lpath,
- bool copy_attrs, bool compressed) {
+ bool copy_attrs, CompressionType compression) {
sc.NewTransfer();
// Make sure that both directory paths end in a slash.
@@ -1510,7 +1564,7 @@
continue;
}
- if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compressed)) {
+ if (!sync_recv(sc, ci.rpath.c_str(), ci.lpath.c_str(), nullptr, ci.size, compression)) {
return false;
}
@@ -1528,7 +1582,7 @@
}
bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
- bool compressed, const char* name) {
+ CompressionType compression, const char* name) {
SyncConnection sc;
if (!sc.IsValid()) return false;
@@ -1602,7 +1656,7 @@
dst_dir.append(android::base::Basename(src_path));
}
- success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compressed);
+ success &= copy_remote_dir_local(sc, src_path, dst_dir, copy_attrs, compression);
continue;
} else if (!should_pull_file(src_st.st_mode)) {
sc.Warning("skipping special file '%s' (mode = 0o%o)", src_path, src_st.st_mode);
@@ -1621,7 +1675,7 @@
sc.NewTransfer();
sc.SetExpectedTotalBytes(src_st.st_size);
- if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compressed)) {
+ if (!sync_recv(sc, src_path, dst_path, name, src_st.st_size, compression)) {
success = false;
continue;
}
@@ -1638,11 +1692,11 @@
}
bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only,
- bool compressed) {
+ CompressionType compression) {
SyncConnection sc;
if (!sc.IsValid()) return false;
- bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compressed);
+ bool success = copy_local_dir_remote(sc, lpath, rpath, true, list_only, compression);
if (!list_only) {
sc.ReportOverallTransferRate(TransferDirection::push);
}
diff --git a/adb/client/file_sync_client.h b/adb/client/file_sync_client.h
index de3f192..aab2e3f 100644
--- a/adb/client/file_sync_client.h
+++ b/adb/client/file_sync_client.h
@@ -19,11 +19,13 @@
#include <string>
#include <vector>
+#include "file_sync_protocol.h"
+
bool do_sync_ls(const char* path);
bool do_sync_push(const std::vector<const char*>& srcs, const char* dst, bool sync,
- bool compressed);
+ CompressionType compression);
bool do_sync_pull(const std::vector<const char*>& srcs, const char* dst, bool copy_attrs,
- bool compressed, const char* name = nullptr);
+ CompressionType compression, const char* name = nullptr);
bool do_sync_sync(const std::string& lpath, const std::string& rpath, bool list_only,
- bool compressed);
+ CompressionType compression);