summaryrefslogtreecommitdiffstats
path: root/libziparchive
diff options
context:
space:
mode:
authorTao Bao <tbao@google.com>2016-11-15 10:08:07 -0800
committerTao Bao <tbao@google.com>2016-11-15 10:19:04 -0800
commita456c2134882c7cede4d0f617a20ce0f8f8f3358 (patch)
tree79aa2cd87055714284e2cce447210695c128e060 /libziparchive
parent557359863c0d1fcda9a85e3b7fb275cb12a3eb70 (diff)
downloadcore-a456c2134882c7cede4d0f617a20ce0f8f8f3358.tar.gz
core-a456c2134882c7cede4d0f617a20ce0f8f8f3358.tar.bz2
core-a456c2134882c7cede4d0f617a20ce0f8f8f3358.zip
ziparchive: Allow ExtractEntryToFile() to work with block device.
FileWriter::Create() calls ftruncate(2) to truncate the destination file, which doesn't work with FD that references a block device. It leads to kIoError when calling ExtractEntryToFile() to extract an entry to block device FD. As a result, it fails the package_extract_file() command in OTA updates (e.g. 'package_extract_file("boot.img", "/dev/block/platform/soc.0/f9824900.sdhci/by-name/boot")'). This CL skips the call to ftruncate(2) if FD references a block device. Bug: 32903624 Test: ziparchive-tests works. Test: Build an OTA updater (m updater) and call package_extract_file(). Change-Id: Ia81116f1a8d7cab802396bdc32c6096b4cb56a3c
Diffstat (limited to 'libziparchive')
-rw-r--r--libziparchive/zip_archive.cc20
1 files changed, 15 insertions, 5 deletions
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index d36cc3fe5..e6e0276a3 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -781,7 +781,8 @@ class FileWriter : public Writer {
// Creates a FileWriter for |fd| and prepare to write |entry| to it,
// guaranteeing that the file descriptor is valid and that there's enough
// space on the volume to write out the entry completely and that the file
- // is truncated to the correct length.
+ // is truncated to the correct length (no truncation if |fd| references a
+ // block device).
//
// Returns a valid FileWriter on success, |nullptr| if an error occurred.
static std::unique_ptr<FileWriter> Create(int fd, const ZipEntry* entry) {
@@ -814,13 +815,22 @@ class FileWriter : public Writer {
}
#endif // __linux__
- result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
- if (result == -1) {
- ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
- static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+ struct stat sb;
+ if (fstat(fd, &sb) == -1) {
+ ALOGW("Zip: unable to fstat file: %s", strerror(errno));
return std::unique_ptr<FileWriter>(nullptr);
}
+ // Block device doesn't support ftruncate(2).
+ if (!S_ISBLK(sb.st_mode)) {
+ result = TEMP_FAILURE_RETRY(ftruncate(fd, declared_length + current_offset));
+ if (result == -1) {
+ ALOGW("Zip: unable to truncate file to %" PRId64 ": %s",
+ static_cast<int64_t>(declared_length + current_offset), strerror(errno));
+ return std::unique_ptr<FileWriter>(nullptr);
+ }
+ }
+
return std::unique_ptr<FileWriter>(new FileWriter(fd, declared_length));
}