summaryrefslogtreecommitdiffstats
path: root/applypatch
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--applypatch/Android.mk4
-rw-r--r--applypatch/Makefile32
-rw-r--r--applypatch/applypatch.cpp107
-rw-r--r--applypatch/applypatch.h13
-rw-r--r--applypatch/bsdiff.cpp1
-rw-r--r--applypatch/bspatch.cpp1
-rw-r--r--applypatch/imgdiff.cpp24
-rw-r--r--applypatch/imgpatch.cpp6
-rw-r--r--applypatch/libimgpatch.pc6
-rw-r--r--applypatch/main.cpp67
10 files changed, 124 insertions, 137 deletions
diff --git a/applypatch/Android.mk b/applypatch/Android.mk
index 887a570db..90a86dcb0 100644
--- a/applypatch/Android.mk
+++ b/applypatch/Android.mk
@@ -55,9 +55,7 @@ LOCAL_CLANG := true
LOCAL_SRC_FILES := main.cpp
LOCAL_MODULE := applypatch
LOCAL_C_INCLUDES += bootable/recovery
-LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz \
- libedify \
-
+LOCAL_STATIC_LIBRARIES += libapplypatch libbase libotafault libmtdutils libcrypto_static libbz libedify
LOCAL_SHARED_LIBRARIES += libz libcutils libc
include $(BUILD_EXECUTABLE)
diff --git a/applypatch/Makefile b/applypatch/Makefile
new file mode 100644
index 000000000..fa6298d46
--- /dev/null
+++ b/applypatch/Makefile
@@ -0,0 +1,32 @@
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# This file is for building imgdiff in Chrome OS.
+
+CPPFLAGS += -iquote..
+CXXFLAGS += -std=c++11 -O3 -Wall -Werror
+LDLIBS += -lbz2 -lz
+
+.PHONY: all clean
+
+all: imgdiff libimgpatch.a
+
+clean:
+ rm -f *.o imgdiff libimgpatch.a
+
+imgdiff: imgdiff.o bsdiff.o utils.o
+ $(CXX) $(CPPFLAGS) $(CXXFLAGS) $(LDLIBS) -o $@ $^
+
+libimgpatch.a: imgpatch.o bspatch.o utils.o
+ ${AR} rcs $@ $^
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 9f5e2f200..f66dbe3bf 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -56,8 +56,6 @@ static bool mtd_partitions_scanned = false;
//
// Return 0 on success.
int LoadFileContents(const char* filename, FileContents* file) {
- file->data = NULL;
-
// A special 'filename' beginning with "MTD:" or "EMMC:" means to
// load the contents of a partition.
if (strncmp(filename, "MTD:", 4) == 0 ||
@@ -70,31 +68,22 @@ int LoadFileContents(const char* filename, FileContents* file) {
return -1;
}
- file->size = file->st.st_size;
- file->data = nullptr;
-
- std::unique_ptr<unsigned char, decltype(&free)> data(
- static_cast<unsigned char*>(malloc(file->size)), free);
- if (data == nullptr) {
- printf("failed to allocate memory: %s\n", strerror(errno));
- return -1;
- }
-
+ std::vector<unsigned char> data(file->st.st_size);
FILE* f = ota_fopen(filename, "rb");
if (f == NULL) {
printf("failed to open \"%s\": %s\n", filename, strerror(errno));
return -1;
}
- size_t bytes_read = ota_fread(data.get(), 1, file->size, f);
- if (bytes_read != static_cast<size_t>(file->size)) {
- printf("short read of \"%s\" (%zu bytes of %zd)\n", filename, bytes_read, file->size);
- fclose(f);
+ size_t bytes_read = ota_fread(data.data(), 1, data.size(), f);
+ if (bytes_read != data.size()) {
+ printf("short read of \"%s\" (%zu bytes of %zu)\n", filename, bytes_read, data.size());
+ ota_fclose(f);
return -1;
}
ota_fclose(f);
- file->data = data.release();
- SHA1(file->data, file->size, file->sha1);
+ file->data = std::move(data);
+ SHA1(file->data.data(), file->data.size(), file->sha1);
return 0;
}
@@ -193,17 +182,17 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
uint8_t parsed_sha[SHA_DIGEST_LENGTH];
// Allocate enough memory to hold the largest size.
- file->data = static_cast<unsigned char*>(malloc(size[index[pairs-1]]));
- char* p = (char*)file->data;
- file->size = 0; // # bytes read so far
+ std::vector<unsigned char> data(size[index[pairs-1]]);
+ char* p = reinterpret_cast<char*>(data.data());
+ size_t data_size = 0; // # bytes read so far
bool found = false;
for (size_t i = 0; i < pairs; ++i) {
// Read enough additional bytes to get us up to the next size. (Again,
// we're trying the possibilities in order of increasing size).
- size_t next = size[index[i]] - file->size;
- size_t read = 0;
+ size_t next = size[index[i]] - data_size;
if (next > 0) {
+ size_t read = 0;
switch (type) {
case MTD:
read = mtd_read_data(ctx, p, next);
@@ -216,12 +205,11 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
if (next != read) {
printf("short read (%zu bytes of %zu) for partition \"%s\"\n",
read, next, partition);
- free(file->data);
- file->data = NULL;
return -1;
}
SHA1_Update(&sha_ctx, p, read);
- file->size += read;
+ data_size += read;
+ p += read;
}
// Duplicate the SHA context and finalize the duplicate so we can
@@ -233,8 +221,6 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
if (ParseSha1(sha1sum[index[i]].c_str(), parsed_sha) != 0) {
printf("failed to parse sha1 %s in %s\n", sha1sum[index[i]].c_str(), filename);
- free(file->data);
- file->data = NULL;
return -1;
}
@@ -246,8 +232,6 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
found = true;
break;
}
-
- p += read;
}
switch (type) {
@@ -264,13 +248,13 @@ static int LoadPartitionContents(const char* filename, FileContents* file) {
if (!found) {
// Ran off the end of the list of (size,sha1) pairs without finding a match.
printf("contents of partition \"%s\" didn't match %s\n", partition, filename);
- free(file->data);
- file->data = NULL;
return -1;
}
SHA1_Final(file->sha1, &sha_ctx);
+ data.resize(data_size);
+ file->data = std::move(data);
// Fake some stat() info.
file->st.st_mode = 0644;
file->st.st_uid = 0;
@@ -289,10 +273,10 @@ int SaveFileContents(const char* filename, const FileContents* file) {
return -1;
}
- ssize_t bytes_written = FileSink(file->data, file->size, &fd);
- if (bytes_written != file->size) {
- printf("short write of \"%s\" (%zd bytes of %zd) (%s)\n",
- filename, bytes_written, file->size, strerror(errno));
+ ssize_t bytes_written = FileSink(file->data.data(), file->data.size(), &fd);
+ if (bytes_written != static_cast<ssize_t>(file->data.size())) {
+ printf("short write of \"%s\" (%zd bytes of %zu) (%s)\n",
+ filename, bytes_written, file->data.size(), strerror(errno));
ota_close(fd);
return -1;
}
@@ -543,7 +527,6 @@ int FindMatchingPatch(uint8_t* sha1, char* const * const patch_sha1_str,
int applypatch_check(const char* filename, int num_patches,
char** const patch_sha1_str) {
FileContents file;
- file.data = NULL;
// It's okay to specify no sha1s; the check will pass if the
// LoadFileContents is successful. (Useful for reading
@@ -555,9 +538,6 @@ int applypatch_check(const char* filename, int num_patches,
printf("file \"%s\" doesn't have any of expected "
"sha1 sums; checking cache\n", filename);
- free(file.data);
- file.data = NULL;
-
// If the source file is missing or corrupted, it might be because
// we were killed in the middle of patching it. A copy of it
// should have been made in CACHE_TEMP_SOURCE. If that file
@@ -571,12 +551,9 @@ int applypatch_check(const char* filename, int num_patches,
if (FindMatchingPatch(file.sha1, patch_sha1_str, num_patches) < 0) {
printf("cache bits don't match any sha1 for \"%s\"\n", filename);
- free(file.data);
return 1;
}
}
-
- free(file.data);
return 0;
}
@@ -674,8 +651,6 @@ int applypatch(const char* source_filename,
FileContents copy_file;
FileContents source_file;
- copy_file.data = NULL;
- source_file.data = NULL;
const Value* source_patch_value = NULL;
const Value* copy_patch_value = NULL;
@@ -685,22 +660,20 @@ int applypatch(const char* source_filename,
// The early-exit case: the patch was already applied, this file
// has the desired hash, nothing for us to do.
printf("already %s\n", short_sha1(target_sha1).c_str());
- free(source_file.data);
return 0;
}
}
- if (source_file.data == NULL ||
+ if (source_file.data.empty() ||
(target_filename != source_filename &&
strcmp(target_filename, source_filename) != 0)) {
// Need to load the source file: either we failed to load the
// target file, or we did but it's different from the source file.
- free(source_file.data);
- source_file.data = NULL;
+ source_file.data.clear();
LoadFileContents(source_filename, &source_file);
}
- if (source_file.data != NULL) {
+ if (!source_file.data.empty()) {
int to_use = FindMatchingPatch(source_file.sha1, patch_sha1_str, num_patches);
if (to_use >= 0) {
source_patch_value = patch_data[to_use];
@@ -708,8 +681,7 @@ int applypatch(const char* source_filename,
}
if (source_patch_value == NULL) {
- free(source_file.data);
- source_file.data = NULL;
+ source_file.data.clear();
printf("source file is bad; trying copy\n");
if (LoadFileContents(CACHE_TEMP_SOURCE, &copy_file) < 0) {
@@ -726,19 +698,14 @@ int applypatch(const char* source_filename,
if (copy_patch_value == NULL) {
// fail.
printf("copy file doesn't match source SHA-1s either\n");
- free(copy_file.data);
return 1;
}
}
- int result = GenerateTarget(&source_file, source_patch_value,
- &copy_file, copy_patch_value,
- source_filename, target_filename,
- target_sha1, target_size, bonus_data);
- free(source_file.data);
- free(copy_file.data);
-
- return result;
+ return GenerateTarget(&source_file, source_patch_value,
+ &copy_file, copy_patch_value,
+ source_filename, target_filename,
+ target_sha1, target_size, bonus_data);
}
/*
@@ -759,7 +726,6 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
}
FileContents source_file;
- source_file.data = NULL;
std::string target_str(target_filename);
std::vector<std::string> pieces = android::base::Split(target_str, ":");
@@ -777,7 +743,6 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
// The early-exit case: the image was already applied, this partition
// has the desired hash, nothing for us to do.
printf("already %s\n", short_sha1(target_sha1).c_str());
- free(source_file.data);
return 0;
}
@@ -787,18 +752,14 @@ int applypatch_flash(const char* source_filename, const char* target_filename,
printf("source \"%s\" doesn't have expected sha1 sum\n", source_filename);
printf("expected: %s, found: %s\n", short_sha1(target_sha1).c_str(),
short_sha1(source_file.sha1).c_str());
- free(source_file.data);
return 1;
}
}
- if (WriteToPartition(source_file.data, target_size, target_filename) != 0) {
+ if (WriteToPartition(source_file.data.data(), target_size, target_filename) != 0) {
printf("write of copied data to %s failed\n", target_filename);
- free(source_file.data);
return 1;
}
-
- free(source_file.data);
return 0;
}
@@ -867,7 +828,7 @@ static int GenerateTarget(FileContents* source_file,
// We still write the original source to cache, in case
// the partition write is interrupted.
- if (MakeFreeSpaceOnCache(source_file->size) < 0) {
+ if (MakeFreeSpaceOnCache(source_file->data.size()) < 0) {
printf("not enough free space on /cache\n");
return 1;
}
@@ -908,7 +869,7 @@ static int GenerateTarget(FileContents* source_file,
return 1;
}
- if (MakeFreeSpaceOnCache(source_file->size) < 0) {
+ if (MakeFreeSpaceOnCache(source_file->data.size()) < 0) {
printf("not enough free space on /cache\n");
return 1;
}
@@ -936,7 +897,7 @@ static int GenerateTarget(FileContents* source_file,
} else {
// We write the decoded output to "<tgt-file>.patch".
output_fd = ota_open(tmp_target_filename.c_str(), O_WRONLY | O_CREAT | O_TRUNC | O_SYNC,
- S_IRUSR | S_IWUSR);
+ S_IRUSR | S_IWUSR);
if (output_fd < 0) {
printf("failed to open output file %s: %s\n", tmp_target_filename.c_str(),
strerror(errno));
@@ -951,10 +912,10 @@ static int GenerateTarget(FileContents* source_file,
int result;
if (use_bsdiff) {
- result = ApplyBSDiffPatch(source_to_use->data, source_to_use->size,
+ result = ApplyBSDiffPatch(source_to_use->data.data(), source_to_use->data.size(),
patch, 0, sink, token, &ctx);
} else {
- result = ApplyImagePatch(source_to_use->data, source_to_use->size,
+ result = ApplyImagePatch(source_to_use->data.data(), source_to_use->data.size(),
patch, sink, token, &ctx, bonus_data);
}
diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h
index 14fb490ba..9ee39d293 100644
--- a/applypatch/applypatch.h
+++ b/applypatch/applypatch.h
@@ -17,6 +17,7 @@
#ifndef _APPLYPATCH_H
#define _APPLYPATCH_H
+#include <stdint.h>
#include <sys/stat.h>
#include <vector>
@@ -24,17 +25,11 @@
#include "openssl/sha.h"
#include "edify/expr.h"
-typedef struct _Patch {
+struct FileContents {
uint8_t sha1[SHA_DIGEST_LENGTH];
- const char* patch_filename;
-} Patch;
-
-typedef struct _FileContents {
- uint8_t sha1[SHA_DIGEST_LENGTH];
- unsigned char* data;
- ssize_t size;
+ std::vector<unsigned char> data;
struct stat st;
-} FileContents;
+};
// When there isn't enough room on the target filesystem to hold the
// patched version of the file, we copy the original here and delete
diff --git a/applypatch/bsdiff.cpp b/applypatch/bsdiff.cpp
index 55dbe5cf1..cca1b32fb 100644
--- a/applypatch/bsdiff.cpp
+++ b/applypatch/bsdiff.cpp
@@ -224,7 +224,6 @@ static void offtout(off_t x,u_char *buf)
int bsdiff(u_char* old, off_t oldsize, off_t** IP, u_char* newdata, off_t newsize,
const char* patch_filename)
{
- int fd;
off_t *I;
off_t scan,pos,len;
off_t lastscan,lastpos,lastoffset;
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index ebb55f1d1..1fc1455a6 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -182,7 +182,6 @@ int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
off_t oldpos = 0, newpos = 0;
off_t ctrl[3];
- off_t len_read;
int i;
unsigned char buf[24];
while (newpos < new_size) {
diff --git a/applypatch/imgdiff.cpp b/applypatch/imgdiff.cpp
index f22502e38..2aa4a6862 100644
--- a/applypatch/imgdiff.cpp
+++ b/applypatch/imgdiff.cpp
@@ -407,7 +407,6 @@ unsigned char* ReadImage(const char* filename,
while (pos < sz) {
unsigned char* p = img+pos;
- bool processed_deflate = false;
if (sz - pos >= 4 &&
p[0] == 0x1f && p[1] == 0x8b &&
p[2] == 0x08 && // deflate compression
@@ -461,28 +460,27 @@ unsigned char* ReadImage(const char* filename,
strm.next_out = curr->data + curr->len;
ret = inflate(&strm, Z_NO_FLUSH);
if (ret < 0) {
- if (!processed_deflate) {
- // This is the first chunk, assume that it's just a spurious
- // gzip header instead of a real one.
- break;
- }
- printf("Error: inflate failed [%s] at file offset [%zu]\n"
- "imgdiff only supports gzip kernel compression,"
- " did you try CONFIG_KERNEL_LZO?\n",
+ printf("Warning: inflate failed [%s] at offset [%zu],"
+ " treating as a normal chunk\n",
strm.msg, chunk_offset);
- free(img);
- return NULL;
+ break;
}
curr->len = allocated - strm.avail_out;
if (strm.avail_out == 0) {
allocated *= 2;
curr->data = reinterpret_cast<unsigned char*>(realloc(curr->data, allocated));
}
- processed_deflate = true;
} while (ret != Z_STREAM_END);
curr->deflate_len = sz - strm.avail_in - pos;
inflateEnd(&strm);
+
+ if (ret < 0) {
+ free(curr->data);
+ *num_chunks -= 2;
+ continue;
+ }
+
pos += curr->deflate_len;
p += curr->deflate_len;
++curr;
@@ -598,7 +596,6 @@ int ReconstructDeflateChunk(ImageChunk* chunk) {
return -1;
}
- size_t p = 0;
unsigned char* out = reinterpret_cast<unsigned char*>(malloc(BUFFER_SIZE));
// We only check two combinations of encoder parameters: level 6
@@ -844,7 +841,6 @@ int main(int argc, char** argv) {
}
if (argc != 4) {
- usage:
printf("usage: %s [-z] [-b <bonus-file>] <src-img> <tgt-img> <patch-file>\n",
argv[0]);
return 2;
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index 8824038ea..0ab995b30 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -130,6 +130,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
size_t src_len = Read8(deflate_header+8);
size_t patch_offset = Read8(deflate_header+16);
size_t expanded_len = Read8(deflate_header+24);
+ size_t target_len = Read8(deflate_header+32);
int level = Read4(deflate_header+40);
int method = Read4(deflate_header+44);
int windowBits = Read4(deflate_header+48);
@@ -195,6 +196,11 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
&uncompressed_target_data) != 0) {
return -1;
}
+ if (uncompressed_target_data.size() != target_len) {
+ printf("expected target len to be %zu, but it's %zu\n",
+ target_len, uncompressed_target_data.size());
+ return -1;
+ }
// Now compress the target data and append it to the output.
diff --git a/applypatch/libimgpatch.pc b/applypatch/libimgpatch.pc
new file mode 100644
index 000000000..e5002934f
--- /dev/null
+++ b/applypatch/libimgpatch.pc
@@ -0,0 +1,6 @@
+# This file is for libimgpatch in Chrome OS.
+
+Name: libimgpatch
+Description: Apply imgdiff patch
+Version: 0.0.1
+Libs: -limgpatch -lbz2 -lz
diff --git a/applypatch/main.cpp b/applypatch/main.cpp
index 7606d5d3c..9013760c4 100644
--- a/applypatch/main.cpp
+++ b/applypatch/main.cpp
@@ -46,40 +46,32 @@ static int SpaceMode(int argc, char** argv) {
return CacheSizeCheck(bytes);
}
-// Parse arguments (which should be of the form "<sha1>" or
-// "<sha1>:<filename>" into the new parallel arrays *sha1s and
-// *patches (loading file contents into the patches). Returns true on
+// Parse arguments (which should be of the form "<sha1>:<filename>"
+// into the new parallel arrays *sha1s and *files.Returns true on
// success.
static bool ParsePatchArgs(int argc, char** argv, std::vector<char*>* sha1s,
- std::vector<std::unique_ptr<Value, decltype(&FreeValue)>>* patches) {
+ std::vector<FileContents>* files) {
uint8_t digest[SHA_DIGEST_LENGTH];
for (int i = 0; i < argc; ++i) {
char* colon = strchr(argv[i], ':');
- if (colon != NULL) {
- *colon = '\0';
- ++colon;
+ if (colon == nullptr) {
+ printf("no ':' in patch argument \"%s\"\n", argv[i]);
+ return false;
}
-
+ *colon = '\0';
+ ++colon;
if (ParseSha1(argv[i], digest) != 0) {
printf("failed to parse sha1 \"%s\"\n", argv[i]);
return false;
}
sha1s->push_back(argv[i]);
- if (colon == NULL) {
- patches->emplace_back(nullptr, FreeValue);
- } else {
- FileContents fc;
- if (LoadFileContents(colon, &fc) != 0) {
- return false;
- }
- std::unique_ptr<Value, decltype(&FreeValue)> value(new Value, FreeValue);
- value->type = VAL_BLOB;
- value->size = fc.size;
- value->data = reinterpret_cast<char*>(fc.data);
- patches->push_back(std::move(value));
+ FileContents fc;
+ if (LoadFileContents(colon, &fc) != 0) {
+ return false;
}
+ files->push_back(std::move(fc));
}
return true;
}
@@ -90,17 +82,19 @@ static int FlashMode(const char* src_filename, const char* tgt_filename,
}
static int PatchMode(int argc, char** argv) {
- std::unique_ptr<Value, decltype(&FreeValue)> bonus(nullptr, FreeValue);
+ FileContents bonusFc;
+ Value bonusValue;
+ Value* bonus = nullptr;
+
if (argc >= 3 && strcmp(argv[1], "-b") == 0) {
- FileContents fc;
- if (LoadFileContents(argv[2], &fc) != 0) {
+ if (LoadFileContents(argv[2], &bonusFc) != 0) {
printf("failed to load bonus file %s\n", argv[2]);
return 1;
}
- bonus.reset(new Value);
+ bonus = &bonusValue;
bonus->type = VAL_BLOB;
- bonus->size = fc.size;
- bonus->data = reinterpret_cast<char*>(fc.data);
+ bonus->size = bonusFc.data.size();
+ bonus->data = reinterpret_cast<char*>(bonusFc.data.data());
argc -= 2;
argv += 2;
}
@@ -118,28 +112,29 @@ static int PatchMode(int argc, char** argv) {
// If no <src-sha1>:<patch> is provided, it is in flash mode.
if (argc == 5) {
- if (bonus != NULL) {
+ if (bonus != nullptr) {
printf("bonus file not supported in flash mode\n");
return 1;
}
return FlashMode(argv[1], argv[2], argv[3], target_size);
}
-
-
std::vector<char*> sha1s;
- std::vector<std::unique_ptr<Value, decltype(&FreeValue)>> patches;
- if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &patches)) {
+ std::vector<FileContents> files;
+ if (!ParsePatchArgs(argc-5, argv+5, &sha1s, &files)) {
printf("failed to parse patch args\n");
return 1;
}
-
- std::vector<Value*> patch_ptrs;
- for (const auto& p : patches) {
- patch_ptrs.push_back(p.get());
+ std::vector<Value> patches(files.size());
+ std::vector<Value*> patch_ptrs(files.size());
+ for (size_t i = 0; i < files.size(); ++i) {
+ patches[i].type = VAL_BLOB;
+ patches[i].size = files[i].data.size();
+ patches[i].data = reinterpret_cast<char*>(files[i].data.data());
+ patch_ptrs[i] = &patches[i];
}
return applypatch(argv[1], argv[2], argv[3], target_size,
patch_ptrs.size(), sha1s.data(),
- patch_ptrs.data(), bonus.get());
+ patch_ptrs.data(), bonus);
}
// This program applies binary patches to files in a way that is safe