summaryrefslogtreecommitdiffstats
path: root/applypatch
diff options
context:
space:
mode:
Diffstat (limited to 'applypatch')
-rw-r--r--applypatch/applypatch.cpp45
-rwxr-xr-xapplypatch/applypatch.sh350
-rw-r--r--applypatch/bspatch.cpp14
-rwxr-xr-xapplypatch/imgdiff_test.sh118
-rw-r--r--applypatch/imgpatch.cpp26
-rw-r--r--applypatch/include/applypatch/applypatch.h19
-rw-r--r--applypatch/include/applypatch/imgpatch.h9
-rw-r--r--applypatch/testdata/new.filebin1388877 -> 0 bytes
-rw-r--r--applypatch/testdata/old.filebin1348051 -> 0 bytes
-rw-r--r--applypatch/testdata/patch.bsdiffbin57476 -> 0 bytes
10 files changed, 52 insertions, 529 deletions
diff --git a/applypatch/applypatch.cpp b/applypatch/applypatch.cpp
index 7be3fdbde..51bf3932a 100644
--- a/applypatch/applypatch.cpp
+++ b/applypatch/applypatch.cpp
@@ -27,6 +27,7 @@
#include <sys/types.h>
#include <unistd.h>
+#include <functional>
#include <memory>
#include <string>
#include <utility>
@@ -42,7 +43,7 @@
#include "print_sha1.h"
static int LoadPartitionContents(const std::string& filename, FileContents* file);
-static ssize_t FileSink(const unsigned char* data, ssize_t len, void* token);
+static size_t FileSink(const unsigned char* data, size_t len, int fd);
static int GenerateTarget(const FileContents& source_file, const std::unique_ptr<Value>& patch,
const std::string& target_filename,
const uint8_t target_sha1[SHA_DIGEST_LENGTH], const Value* bonus_data);
@@ -194,8 +195,8 @@ int SaveFileContents(const char* filename, const FileContents* file) {
return -1;
}
- ssize_t bytes_written = FileSink(file->data.data(), file->data.size(), &fd);
- if (bytes_written != static_cast<ssize_t>(file->data.size())) {
+ size_t bytes_written = FileSink(file->data.data(), file->data.size(), fd);
+ if (bytes_written != file->data.size()) {
printf("short write of \"%s\" (%zd bytes of %zu): %s\n", filename, bytes_written,
file->data.size(), strerror(errno));
return -1;
@@ -433,25 +434,17 @@ int ShowLicenses() {
return 0;
}
-ssize_t FileSink(const unsigned char* data, ssize_t len, void* token) {
- int fd = *static_cast<int*>(token);
- ssize_t done = 0;
- ssize_t wrote;
- while (done < len) {
- wrote = TEMP_FAILURE_RETRY(ota_write(fd, data+done, len-done));
- if (wrote == -1) {
- printf("error writing %zd bytes: %s\n", (len-done), strerror(errno));
- return done;
- }
- done += wrote;
+static size_t FileSink(const unsigned char* data, size_t len, int fd) {
+ size_t done = 0;
+ while (done < len) {
+ ssize_t wrote = TEMP_FAILURE_RETRY(ota_write(fd, data + done, len - done));
+ if (wrote == -1) {
+ printf("error writing %zd bytes: %s\n", (len - done), strerror(errno));
+ return done;
}
- return done;
-}
-
-ssize_t MemorySink(const unsigned char* data, ssize_t len, void* token) {
- std::string* s = static_cast<std::string*>(token);
- s->append(reinterpret_cast<const char*>(data), len);
- return len;
+ done += wrote;
+ }
+ return done;
}
// Return the amount of free space (in bytes) on the filesystem
@@ -647,9 +640,11 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
}
// We store the decoded output in memory.
- SinkFn sink = MemorySink;
std::string memory_sink_str; // Don't need to reserve space.
- void* token = &memory_sink_str;
+ SinkFn sink = [&memory_sink_str](const unsigned char* data, size_t len) {
+ memory_sink_str.append(reinterpret_cast<const char*>(data), len);
+ return len;
+ };
SHA_CTX ctx;
SHA1_Init(&ctx);
@@ -657,10 +652,10 @@ static int GenerateTarget(const FileContents& source_file, const std::unique_ptr
int result;
if (use_bsdiff) {
result = ApplyBSDiffPatch(source_file.data.data(), source_file.data.size(), patch.get(), 0,
- sink, token, &ctx);
+ sink, &ctx);
} else {
result = ApplyImagePatch(source_file.data.data(), source_file.data.size(), patch.get(), sink,
- token, &ctx, bonus_data);
+ &ctx, bonus_data);
}
if (result != 0) {
diff --git a/applypatch/applypatch.sh b/applypatch/applypatch.sh
deleted file mode 100755
index 8ea68a1a9..000000000
--- a/applypatch/applypatch.sh
+++ /dev/null
@@ -1,350 +0,0 @@
-#!/bin/bash
-#
-# A test suite for applypatch. Run in a client where you have done
-# envsetup, choosecombo, etc.
-#
-# DO NOT RUN THIS ON A DEVICE YOU CARE ABOUT. It will mess up your
-# system partition.
-#
-#
-# TODO: find some way to get this run regularly along with the rest of
-# the tests.
-
-EMULATOR_PORT=5580
-DATA_DIR=$ANDROID_BUILD_TOP/bootable/recovery/applypatch/testdata
-
-# This must be the filename that applypatch uses for its copies.
-CACHE_TEMP_SOURCE=/cache/saved.file
-
-# Put all binaries and files here. We use /cache because it's a
-# temporary filesystem in the emulator; it's created fresh each time
-# the emulator starts.
-WORK_DIR=/system
-
-# partition that WORK_DIR is located on, without the leading slash
-WORK_FS=system
-
-# set to 0 to use a device instead
-USE_EMULATOR=1
-
-# ------------------------
-
-tmpdir=$(mktemp -d)
-
-if [ "$USE_EMULATOR" == 1 ]; then
- emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
- pid_emulator=$!
- ADB="adb -s emulator-$EMULATOR_PORT "
-else
- ADB="adb -d "
-fi
-
-echo "waiting to connect to device"
-$ADB wait-for-device
-echo "device is available"
-$ADB remount
-# free up enough space on the system partition for the test to run.
-$ADB shell rm -r /system/media
-
-# run a command on the device; exit with the exit status of the device
-# command.
-run_command() {
- $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
-}
-
-testname() {
- echo
- echo "$1"...
- testname="$1"
-}
-
-fail() {
- echo
- echo FAIL: $testname
- echo
- [ "$open_pid" == "" ] || kill $open_pid
- [ "$pid_emulator" == "" ] || kill $pid_emulator
- exit 1
-}
-
-sha1() {
- sha1sum $1 | awk '{print $1}'
-}
-
-free_space() {
- run_command df | awk "/$1/ {print gensub(/K/, \"\", \"g\", \$6)}"
-}
-
-cleanup() {
- # not necessary if we're about to kill the emulator, but nice for
- # running on real devices or already-running emulators.
- testname "removing test files"
- run_command rm $WORK_DIR/bloat.dat
- run_command rm $WORK_DIR/old.file
- run_command rm $WORK_DIR/foo
- run_command rm $WORK_DIR/patch.bsdiff
- run_command rm $WORK_DIR/applypatch
- run_command rm $CACHE_TEMP_SOURCE
- run_command rm /cache/bloat*.dat
-
- [ "$pid_emulator" == "" ] || kill $pid_emulator
-
- if [ $# == 0 ]; then
- rm -rf $tmpdir
- fi
-}
-
-cleanup leave_tmp
-
-$ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch
-
-BAD1_SHA1=$(printf "%040x" $RANDOM)
-BAD2_SHA1=$(printf "%040x" $RANDOM)
-OLD_SHA1=$(sha1 $DATA_DIR/old.file)
-NEW_SHA1=$(sha1 $DATA_DIR/new.file)
-NEW_SIZE=$(stat -c %s $DATA_DIR/new.file)
-
-# --------------- basic execution ----------------------
-
-testname "usage message"
-run_command $WORK_DIR/applypatch && fail
-
-testname "display license"
-run_command $WORK_DIR/applypatch -l | grep -q -i copyright || fail
-
-
-# --------------- check mode ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-
-testname "check mode single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "check mode cache (corrupted) single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode cache (corrupted) multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode cache (corrupted) failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-# remove the old file entirely
-run_command rm $WORK_DIR/old.file
-
-testname "check mode cache (missing) single"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $OLD_SHA1 || fail
-
-testname "check mode cache (missing) multiple"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD1_SHA1 $OLD_SHA1 $BAD2_SHA1|| fail
-
-testname "check mode cache (missing) failure"
-run_command $WORK_DIR/applypatch -c $WORK_DIR/old.file $BAD2_SHA1 $BAD1_SHA1 && fail
-
-
-# --------------- apply patch ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-echo hello > $tmpdir/foo
-$ADB push $tmpdir/foo $WORK_DIR
-
-# Check that the partition has enough space to apply the patch without
-# copying. If it doesn't, we'll be testing the low-space condition
-# when we intend to test the not-low-space condition.
-testname "apply patches (with enough space)"
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS."
-if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then
- echo "Not enough space on /$WORK_FS to patch test file."
- echo
- echo "This doesn't mean that applypatch is necessarily broken;"
- echo "just that /$WORK_FS doesn't have enough free space to"
- echo "properly run this test."
- exit 1
-fi
-
-testname "apply bsdiff patch"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-
-# --------------- apply patch in new location ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-# Check that the partition has enough space to apply the patch without
-# copying. If it doesn't, we'll be testing the low-space condition
-# when we intend to test the not-low-space condition.
-testname "apply patch to new location (with enough space)"
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS."
-if (( free_kb * 1024 < NEW_SIZE * 3 / 2 )); then
- echo "Not enough space on /$WORK_FS to patch test file."
- echo
- echo "This doesn't mean that applypatch is necessarily broken;"
- echo "just that /$WORK_FS doesn't have enough free space to"
- echo "properly run this test."
- exit 1
-fi
-
-run_command rm $WORK_DIR/new.file
-run_command rm $CACHE_TEMP_SOURCE
-
-testname "apply bsdiff patch to new location"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch to new location"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch to new location with corrupted source"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo || fail
-$ADB pull $WORK_DIR/new.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-# put some junk in the cache copy, too
-run_command dd if=/dev/urandom of=$CACHE_TEMP_SOURCE count=100 bs=1024 || fail
-
-run_command rm $WORK_DIR/new.file
-testname "apply bsdiff patch to new location with corrupted source and copy (no new file)"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail
-
-# put some junk in the new file
-run_command dd if=/dev/urandom of=$WORK_DIR/new.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch to new location with corrupted source and copy (bad new file)"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file $WORK_DIR/new.file $NEW_SHA1 $NEW_SIZE $OLD_SHA1:$WORK_DIR/patch.bsdiff $BAD1_SHA1:$WORK_DIR/foo && fail
-
-# --------------- apply patch with low space on /system ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS; we'll soon fix that."
-echo run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
-run_command dd if=/dev/zero of=$WORK_DIR/bloat.dat count=$((free_kb-512)) bs=1024 || fail
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS now."
-
-testname "apply bsdiff patch with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-testname "reapply bsdiff patch with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-# --------------- apply patch with low space on /system and /cache ----------------------
-
-$ADB push $DATA_DIR/old.file $WORK_DIR
-$ADB push $DATA_DIR/patch.bsdiff $WORK_DIR
-
-free_kb=$(free_space $WORK_FS)
-echo "${free_kb}kb free on /$WORK_FS"
-
-run_command mkdir /cache/subdir
-run_command 'echo > /cache/subdir/a.file'
-run_command 'echo > /cache/a.file'
-run_command mkdir /cache/recovery /cache/recovery/otatest
-run_command 'echo > /cache/recovery/otatest/b.file'
-run_command "echo > $CACHE_TEMP_SOURCE"
-free_kb=$(free_space cache)
-echo "${free_kb}kb free on /cache; we'll soon fix that."
-run_command dd if=/dev/zero of=/cache/bloat_small.dat count=128 bs=1024 || fail
-run_command dd if=/dev/zero of=/cache/bloat_large.dat count=$((free_kb-640)) bs=1024 || fail
-free_kb=$(free_space cache)
-echo "${free_kb}kb free on /cache now."
-
-testname "apply bsdiff patch with low space, full cache, can't delete enough"
-$ADB shell 'cat >> /cache/bloat_large.dat' & open_pid=$!
-echo "open_pid is $open_pid"
-
-# size check should fail even though it deletes some stuff
-run_command $WORK_DIR/applypatch -s $NEW_SIZE && fail
-run_command ls /cache/bloat_small.dat && fail # was deleted
-run_command ls /cache/a.file && fail # was deleted
-run_command ls /cache/recovery/otatest/b.file && fail # was deleted
-run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open
-run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
-
-# should fail; not enough files can be deleted
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff && fail
-run_command ls /cache/bloat_large.dat || fail # wasn't deleted because it was open
-run_command ls /cache/subdir/a.file || fail # wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
-
-kill $open_pid # /cache/bloat_large.dat is no longer open
-
-testname "apply bsdiff patch with low space, full cache, can delete enough"
-
-# should succeed after deleting /cache/bloat_large.dat
-run_command $WORK_DIR/applypatch -s $NEW_SIZE || fail
-run_command ls /cache/bloat_large.dat && fail # was deleted
-run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE || fail # wasn't deleted because it's the source file copy
-
-# should succeed
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-run_command ls /cache/subdir/a.file || fail # still wasn't deleted because it's in a subdir
-run_command ls $CACHE_TEMP_SOURCE && fail # was deleted because patching overwrote it, then deleted it
-
-# --------------- apply patch from cache ----------------------
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# put some junk in the old file
-run_command dd if=/dev/urandom of=$WORK_DIR/old.file count=100 bs=1024 || fail
-
-testname "apply bsdiff patch from cache (corrupted source) with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-$ADB push $DATA_DIR/old.file $CACHE_TEMP_SOURCE
-# remove the old file entirely
-run_command rm $WORK_DIR/old.file
-
-testname "apply bsdiff patch from cache (missing source) with low space"
-run_command $WORK_DIR/applypatch $WORK_DIR/old.file - $NEW_SHA1 $NEW_SIZE $BAD1_SHA1:$WORK_DIR/foo $OLD_SHA1:$WORK_DIR/patch.bsdiff || fail
-$ADB pull $WORK_DIR/old.file $tmpdir/patched
-diff -q $DATA_DIR/new.file $tmpdir/patched || fail
-
-
-# --------------- cleanup ----------------------
-
-cleanup
-
-echo
-echo PASS
-echo
-
diff --git a/applypatch/bspatch.cpp b/applypatch/bspatch.cpp
index 9920c2be1..f75a2c680 100644
--- a/applypatch/bspatch.cpp
+++ b/applypatch/bspatch.cpp
@@ -24,9 +24,9 @@
#include <sys/types.h>
#include <bspatch.h>
+#include <openssl/sha.h>
#include "applypatch/applypatch.h"
-#include "openssl/sha.h"
void ShowBSDiffLicense() {
puts("The bsdiff library used herein is:\n"
@@ -60,10 +60,10 @@ void ShowBSDiffLicense() {
);
}
-int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, const Value* patch,
- ssize_t patch_offset, SinkFn sink, void* token, SHA_CTX* ctx) {
- auto sha_sink = [&](const uint8_t* data, size_t len) {
- len = sink(data, len, token);
+int ApplyBSDiffPatch(const unsigned char* old_data, size_t old_size, const Value* patch,
+ size_t patch_offset, SinkFn sink, SHA_CTX* ctx) {
+ auto sha_sink = [&sink, &ctx](const uint8_t* data, size_t len) {
+ len = sink(data, len);
if (ctx) SHA1_Update(ctx, data, len);
return len;
};
@@ -72,8 +72,8 @@ int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size, const Valu
patch->data.size(), sha_sink);
}
-int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size, const Value* patch,
- ssize_t patch_offset, std::vector<unsigned char>* new_data) {
+int ApplyBSDiffPatchMem(const unsigned char* old_data, size_t old_size, const Value* patch,
+ size_t patch_offset, std::vector<unsigned char>* new_data) {
auto vector_sink = [new_data](const uint8_t* data, size_t len) {
new_data->insert(new_data->end(), data, data + len);
return len;
diff --git a/applypatch/imgdiff_test.sh b/applypatch/imgdiff_test.sh
deleted file mode 100755
index dcdb922b4..000000000
--- a/applypatch/imgdiff_test.sh
+++ /dev/null
@@ -1,118 +0,0 @@
-#!/bin/bash
-#
-# A script for testing imgdiff/applypatch. It takes two full OTA
-# packages as arguments. It generates (on the host) patches for all
-# the zip/jar/apk files they have in common, as well as boot and
-# recovery images. It then applies the patches on the device (or
-# emulator) and checks that the resulting file is correct.
-
-EMULATOR_PORT=5580
-
-# set to 0 to use a device instead
-USE_EMULATOR=0
-
-# where on the device to do all the patching.
-WORK_DIR=/data/local/tmp
-
-START_OTA_PACKAGE=$1
-END_OTA_PACKAGE=$2
-
-# ------------------------
-
-tmpdir=$(mktemp -d)
-
-if [ "$USE_EMULATOR" == 1 ]; then
- emulator -wipe-data -noaudio -no-window -port $EMULATOR_PORT &
- pid_emulator=$!
- ADB="adb -s emulator-$EMULATOR_PORT "
-else
- ADB="adb -d "
-fi
-
-echo "waiting to connect to device"
-$ADB wait-for-device
-
-# run a command on the device; exit with the exit status of the device
-# command.
-run_command() {
- $ADB shell "$@" \; echo \$? | awk '{if (b) {print a}; a=$0; b=1} END {exit a}'
-}
-
-testname() {
- echo
- echo "$1"...
- testname="$1"
-}
-
-fail() {
- echo
- echo FAIL: $testname
- echo
- [ "$open_pid" == "" ] || kill $open_pid
- [ "$pid_emulator" == "" ] || kill $pid_emulator
- exit 1
-}
-
-sha1() {
- sha1sum $1 | awk '{print $1}'
-}
-
-size() {
- stat -c %s $1 | tr -d '\n'
-}
-
-cleanup() {
- # not necessary if we're about to kill the emulator, but nice for
- # running on real devices or already-running emulators.
- testname "removing test files"
- run_command rm $WORK_DIR/applypatch
- run_command rm $WORK_DIR/source
- run_command rm $WORK_DIR/target
- run_command rm $WORK_DIR/patch
-
- [ "$pid_emulator" == "" ] || kill $pid_emulator
-
- rm -rf $tmpdir
-}
-
-$ADB push $ANDROID_PRODUCT_OUT/system/bin/applypatch $WORK_DIR/applypatch
-
-patch_and_apply() {
- local fn=$1
- shift
-
- unzip -p $START_OTA_PACKAGE $fn > $tmpdir/source
- unzip -p $END_OTA_PACKAGE $fn > $tmpdir/target
- imgdiff "$@" $tmpdir/source $tmpdir/target $tmpdir/patch
- bsdiff $tmpdir/source $tmpdir/target $tmpdir/patch.bs
- echo "patch for $fn is $(size $tmpdir/patch) [of $(size $tmpdir/target)] ($(size $tmpdir/patch.bs) with bsdiff)"
- echo "$fn $(size $tmpdir/patch) of $(size $tmpdir/target) bsdiff $(size $tmpdir/patch.bs)" >> /tmp/stats.txt
- $ADB push $tmpdir/source $WORK_DIR/source || fail "source push failed"
- run_command rm /data/local/tmp/target
- $ADB push $tmpdir/patch $WORK_DIR/patch || fail "patch push failed"
- run_command /data/local/tmp/applypatch /data/local/tmp/source \
- /data/local/tmp/target $(sha1 $tmpdir/target) $(size $tmpdir/target) \
- $(sha1 $tmpdir/source):/data/local/tmp/patch \
- || fail "applypatch of $fn failed"
- $ADB pull /data/local/tmp/target $tmpdir/result
- diff -q $tmpdir/target $tmpdir/result || fail "patch output not correct!"
-}
-
-# --------------- basic execution ----------------------
-
-for i in $((zipinfo -1 $START_OTA_PACKAGE; zipinfo -1 $END_OTA_PACKAGE) | \
- sort | uniq -d | egrep -e '[.](apk|jar|zip)$'); do
- patch_and_apply $i -z
-done
-patch_and_apply boot.img
-patch_and_apply system/recovery.img
-
-
-# --------------- cleanup ----------------------
-
-cleanup
-
-echo
-echo PASS
-echo
-
diff --git a/applypatch/imgpatch.cpp b/applypatch/imgpatch.cpp
index adcc61fd6..7d8b7361c 100644
--- a/applypatch/imgpatch.cpp
+++ b/applypatch/imgpatch.cpp
@@ -43,12 +43,11 @@ static inline int32_t Read4(const void *address) {
return android::base::get_unaligned<int32_t>(address);
}
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
- const unsigned char* patch_data, ssize_t patch_size,
- SinkFn sink, void* token) {
+int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
+ size_t patch_size, SinkFn sink) {
Value patch(VAL_BLOB, std::string(reinterpret_cast<const char*>(patch_data), patch_size));
- return ApplyImagePatch(old_data, old_size, &patch, sink, token, nullptr, nullptr);
+ return ApplyImagePatch(old_data, old_size, &patch, sink, nullptr, nullptr);
}
/*
@@ -57,8 +56,8 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
* file, and update the SHA context with the output data as well.
* Return 0 on success.
*/
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value* patch,
- SinkFn sink, void* token, SHA_CTX* ctx, const Value* bonus_data) {
+int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value* patch, SinkFn sink,
+ SHA_CTX* ctx, const Value* bonus_data) {
if (patch->data.size() < 12) {
printf("patch too short to contain header\n");
return -1;
@@ -97,11 +96,11 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
size_t src_len = static_cast<size_t>(Read8(normal_header + 8));
size_t patch_offset = static_cast<size_t>(Read8(normal_header + 16));
- if (src_start + src_len > static_cast<size_t>(old_size)) {
+ if (src_start + src_len > old_size) {
printf("source data too short\n");
return -1;
}
- ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, token, ctx);
+ ApplyBSDiffPatch(old_data + src_start, src_len, patch, patch_offset, sink, ctx);
} else if (type == CHUNK_RAW) {
const char* raw_header = &patch->data[pos];
pos += 4;
@@ -110,15 +109,14 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
return -1;
}
- ssize_t data_len = Read4(raw_header);
+ size_t data_len = static_cast<size_t>(Read4(raw_header));
if (pos + data_len > patch->data.size()) {
printf("failed to read chunk %d raw data\n", i);
return -1;
}
if (ctx) SHA1_Update(ctx, &patch->data[pos], data_len);
- if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len, token) !=
- data_len) {
+ if (sink(reinterpret_cast<const unsigned char*>(&patch->data[pos]), data_len) != data_len) {
printf("failed to write chunk %d raw data\n", i);
return -1;
}
@@ -143,7 +141,7 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
int memLevel = Read4(deflate_header + 52);
int strategy = Read4(deflate_header + 56);
- if (src_start + src_len > static_cast<size_t>(old_size)) {
+ if (src_start + src_len > old_size) {
printf("source data too short\n");
return -1;
}
@@ -240,9 +238,9 @@ int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size, const Value
strm.avail_out = temp_data.size();
strm.next_out = temp_data.data();
ret = deflate(&strm, Z_FINISH);
- ssize_t have = temp_data.size() - strm.avail_out;
+ size_t have = temp_data.size() - strm.avail_out;
- if (sink(temp_data.data(), have, token) != have) {
+ if (sink(temp_data.data(), have) != have) {
printf("failed to write %zd compressed bytes to output\n", have);
return -1;
}
diff --git a/applypatch/include/applypatch/applypatch.h b/applypatch/include/applypatch/applypatch.h
index 4489decb6..da55432d5 100644
--- a/applypatch/include/applypatch/applypatch.h
+++ b/applypatch/include/applypatch/applypatch.h
@@ -20,6 +20,7 @@
#include <stdint.h>
#include <sys/stat.h>
+#include <functional>
#include <memory>
#include <string>
#include <vector>
@@ -41,7 +42,7 @@ struct FileContents {
// and use it as the source instead.
#define CACHE_TEMP_SOURCE "/cache/saved.file"
-typedef ssize_t (*SinkFn)(const unsigned char*, ssize_t, void*);
+using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
// applypatch.cpp
int ShowLicenses();
@@ -66,18 +67,14 @@ int SaveFileContents(const char* filename, const FileContents* file);
// bspatch.cpp
void ShowBSDiffLicense();
-int ApplyBSDiffPatch(const unsigned char* old_data, ssize_t old_size,
- const Value* patch, ssize_t patch_offset,
- SinkFn sink, void* token, SHA_CTX* ctx);
-int ApplyBSDiffPatchMem(const unsigned char* old_data, ssize_t old_size,
- const Value* patch, ssize_t patch_offset,
- std::vector<unsigned char>* new_data);
+int ApplyBSDiffPatch(const unsigned char* old_data, size_t old_size, const Value* patch,
+ size_t patch_offset, SinkFn sink, SHA_CTX* ctx);
+int ApplyBSDiffPatchMem(const unsigned char* old_data, size_t old_size, const Value* patch,
+ size_t patch_offset, std::vector<unsigned char>* new_data);
// imgpatch.cpp
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
- const Value* patch,
- SinkFn sink, void* token, SHA_CTX* ctx,
- const Value* bonus_data);
+int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const Value* patch, SinkFn sink,
+ SHA_CTX* ctx, const Value* bonus_data);
// freecache.cpp
int MakeFreeSpaceOnCache(size_t bytes_needed);
diff --git a/applypatch/include/applypatch/imgpatch.h b/applypatch/include/applypatch/imgpatch.h
index 6549f79f0..07c66094f 100644
--- a/applypatch/include/applypatch/imgpatch.h
+++ b/applypatch/include/applypatch/imgpatch.h
@@ -19,10 +19,11 @@
#include <sys/types.h>
-using SinkFn = ssize_t (*)(const unsigned char*, ssize_t, void*);
+#include <functional>
-int ApplyImagePatch(const unsigned char* old_data, ssize_t old_size,
- const unsigned char* patch_data, ssize_t patch_size,
- SinkFn sink, void* token);
+using SinkFn = std::function<size_t(const unsigned char*, size_t)>;
+
+int ApplyImagePatch(const unsigned char* old_data, size_t old_size, const unsigned char* patch_data,
+ size_t patch_size, SinkFn sink);
#endif // _APPLYPATCH_IMGPATCH_H
diff --git a/applypatch/testdata/new.file b/applypatch/testdata/new.file
deleted file mode 100644
index cdeb8fd50..000000000
--- a/applypatch/testdata/new.file
+++ /dev/null
Binary files differ
diff --git a/applypatch/testdata/old.file b/applypatch/testdata/old.file
deleted file mode 100644
index 166c8732e..000000000
--- a/applypatch/testdata/old.file
+++ /dev/null
Binary files differ
diff --git a/applypatch/testdata/patch.bsdiff b/applypatch/testdata/patch.bsdiff
deleted file mode 100644
index b78d38573..000000000
--- a/applypatch/testdata/patch.bsdiff
+++ /dev/null
Binary files differ