Merge "ziparchive: Allow ExtractEntryToFile() to work with block device."
am: 787482ecd9
Change-Id: Icdce4207cb64e084e200b6f7f8ae194831d5c4f0
diff --git a/include/ziparchive/zip_archive.h b/include/ziparchive/zip_archive.h
index fc845a4..54946fc 100644
--- a/include/ziparchive/zip_archive.h
+++ b/include/ziparchive/zip_archive.h
@@ -195,7 +195,8 @@
* Uncompress and write an entry to an open file identified by |fd|.
* |entry->uncompressed_length| bytes will be written to the file at
* its current offset, and the file will be truncated at the end of
- * the uncompressed data.
+ * the uncompressed data (no truncation if |fd| references a block
+ * device).
*
* Returns 0 on success and negative values on failure.
*/
diff --git a/libziparchive/zip_archive.cc b/libziparchive/zip_archive.cc
index a07df30..0ac6f2c 100644
--- a/libziparchive/zip_archive.cc
+++ b/libziparchive/zip_archive.cc
@@ -786,7 +786,8 @@
// 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) {
@@ -819,13 +820,22 @@
}
#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));
}