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
This commit is contained in:
parent
557359863c
commit
a456c21348
2 changed files with 17 additions and 6 deletions
|
@ -195,7 +195,8 @@ void EndIteration(void* cookie);
|
|||
* 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.
|
||||
*/
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue