summaryrefslogtreecommitdiff
path: root/adb/client/incremental_utils.cpp
diff options
context:
space:
mode:
authorYurii Zubrytskyi <zyy@google.com>2020-03-18 15:49:45 -0700
committerYurii Zubrytskyi <zyy@google.com>2020-03-24 10:28:03 -0700
commit2488c21d8bb8b4e58b6b482ad1167c97cbd859e1 (patch)
treed1057ae25b06abc95041b6f62e91bf9b6c75c2cc /adb/client/incremental_utils.cpp
parentc3eb3014f6b58fef7ef7a6ab5522859d86e11c6d (diff)
[adb] Fix incremental installation on Windows
Use only the syscalls that work with the wrapped ADB fds, or extract the native handles for the case when need to call one not wrapped. Bug: 151239696 Test: adb install --incremental <apk> on Windows Change-Id: Ia6de620171ab696b8136dcb60a2b63af6f86419f Merged-In: Ia6de620171ab696b8136dcb60a2b63af6f86419f
Diffstat (limited to 'adb/client/incremental_utils.cpp')
-rw-r--r--adb/client/incremental_utils.cpp76
1 files changed, 71 insertions, 5 deletions
diff --git a/adb/client/incremental_utils.cpp b/adb/client/incremental_utils.cpp
index 316480c57..caadb26f6 100644
--- a/adb/client/incremental_utils.cpp
+++ b/adb/client/incremental_utils.cpp
@@ -18,6 +18,7 @@
#include "incremental_utils.h"
+#include <android-base/mapped_file.h>
#include <android-base/strings.h>
#include <ziparchive/zip_archive.h>
#include <ziparchive/zip_writer.h>
@@ -26,6 +27,7 @@
#include <numeric>
#include <unordered_set>
+#include "adb_trace.h"
#include "sysdeps.h"
static constexpr int kBlockSize = 4096;
@@ -155,18 +157,81 @@ static std::vector<int32_t> ZipPriorityBlocks(off64_t signerBlockOffset, int64_t
return zipPriorityBlocks;
}
-// TODO(b/151676293): avoid using OpenArchiveFd that reads local file headers
+[[maybe_unused]] static ZipArchiveHandle openZipArchiveFd(int fd) {
+ bool transferFdOwnership = false;
+#ifdef _WIN32
+ //
+ // Need to create a special CRT FD here as the current one is not compatible with
+ // normal read()/write() calls that libziparchive uses.
+ // To make this work we have to create a copy of the file handle, as CRT doesn't care
+ // and closes it together with the new descriptor.
+ //
+ // Note: don't move this into a helper function, it's better to be hard to reuse because
+ // the code is ugly and won't work unless it's a last resort.
+ //
+ auto handle = adb_get_os_handle(fd);
+ HANDLE dupedHandle;
+ if (!::DuplicateHandle(::GetCurrentProcess(), handle, ::GetCurrentProcess(), &dupedHandle, 0,
+ false, DUPLICATE_SAME_ACCESS)) {
+ D("%s failed at DuplicateHandle: %d", __func__, (int)::GetLastError());
+ return {};
+ }
+ fd = _open_osfhandle((intptr_t)dupedHandle, _O_RDONLY | _O_BINARY);
+ if (fd < 0) {
+ D("%s failed at _open_osfhandle: %d", __func__, errno);
+ ::CloseHandle(handle);
+ return {};
+ }
+ transferFdOwnership = true;
+#endif
+ ZipArchiveHandle zip;
+ if (OpenArchiveFd(fd, "apk_fd", &zip, transferFdOwnership) != 0) {
+ D("%s failed at OpenArchiveFd: %d", __func__, errno);
+#ifdef _WIN32
+ // "_close()" is a secret WinCRT name for the regular close() function.
+ _close(fd);
+#endif
+ return {};
+ }
+ return zip;
+}
+
+static std::pair<ZipArchiveHandle, std::unique_ptr<android::base::MappedFile>> openZipArchive(
+ int fd, int64_t fileSize) {
+#ifndef __LP64__
+ if (fileSize >= INT_MAX) {
+ return {openZipArchiveFd(fd), nullptr};
+ }
+#endif
+ auto mapping =
+ android::base::MappedFile::FromOsHandle(adb_get_os_handle(fd), 0, fileSize, PROT_READ);
+ if (!mapping) {
+ D("%s failed at FromOsHandle: %d", __func__, errno);
+ return {};
+ }
+ ZipArchiveHandle zip;
+ if (OpenArchiveFromMemory(mapping->data(), mapping->size(), "apk_mapping", &zip) != 0) {
+ D("%s failed at OpenArchiveFromMemory: %d", __func__, errno);
+ return {};
+ }
+ return {zip, std::move(mapping)};
+}
+
+// TODO(b/151676293): avoid using libziparchive as it reads local file headers
// which causes additional performance cost. Instead, only read from central directory.
static std::vector<int32_t> InstallationPriorityBlocks(int fd, int64_t fileSize) {
- std::vector<int32_t> installationPriorityBlocks;
- ZipArchiveHandle zip;
- if (OpenArchiveFd(fd, "", &zip, false) != 0) {
+ auto [zip, _] = openZipArchive(fd, fileSize);
+ if (!zip) {
return {};
}
+
void* cookie = nullptr;
if (StartIteration(zip, &cookie) != 0) {
+ D("%s failed at StartIteration: %d", __func__, errno);
return {};
}
+
+ std::vector<int32_t> installationPriorityBlocks;
ZipEntry entry;
std::string_view entryName;
while (Next(cookie, &entry, &entryName) == 0) {
@@ -183,6 +248,7 @@ static std::vector<int32_t> InstallationPriorityBlocks(int fd, int64_t fileSize)
int32_t endBlockIndex = offsetToBlockIndex(entryEndOffset);
int32_t numNewBlocks = endBlockIndex - startBlockIndex + 1;
appendBlocks(startBlockIndex, numNewBlocks, &installationPriorityBlocks);
+ D("\tadding to priority blocks: '%.*s'", (int)entryName.size(), entryName.data());
} else if (entryName == "classes.dex") {
// Only the head is needed for installation
int32_t startBlockIndex = offsetToBlockIndex(entry.offset);
@@ -213,4 +279,4 @@ std::vector<int32_t> PriorityBlocksForFile(const std::string& filepath, int fd,
unduplicate(priorityBlocks);
return priorityBlocks;
}
-} // namespace incremental \ No newline at end of file
+} // namespace incremental