diff options
author | Yurii Zubrytskyi <zyy@google.com> | 2020-03-18 15:49:45 -0700 |
---|---|---|
committer | Yurii Zubrytskyi <zyy@google.com> | 2020-03-24 10:28:03 -0700 |
commit | 2488c21d8bb8b4e58b6b482ad1167c97cbd859e1 (patch) | |
tree | d1057ae25b06abc95041b6f62e91bf9b6c75c2cc /adb/client/incremental_utils.cpp | |
parent | c3eb3014f6b58fef7ef7a6ab5522859d86e11c6d (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.cpp | 76 |
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 |