diff options
Diffstat (limited to 'applypatch')
-rw-r--r-- | applypatch/NOTICE | 41 | ||||
-rw-r--r-- | applypatch/applypatch.c | 64 | ||||
-rw-r--r-- | applypatch/applypatch.h | 4 |
3 files changed, 88 insertions, 21 deletions
diff --git a/applypatch/NOTICE b/applypatch/NOTICE new file mode 100644 index 000000000..6156a0ca3 --- /dev/null +++ b/applypatch/NOTICE @@ -0,0 +1,41 @@ +Copyright (C) 2009 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. + + +bsdiff.c +bspatch.c + +Copyright 2003-2005 Colin Percival +All rights reserved + +Redistribution and use in source and binary forms, with or without +modification, are permitted providing that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY +DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, +STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING +IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. diff --git a/applypatch/applypatch.c b/applypatch/applypatch.c index 106091386..00004e9a8 100644 --- a/applypatch/applypatch.c +++ b/applypatch/applypatch.c @@ -30,10 +30,16 @@ #include "mtdutils/mtdutils.h" #include "edify/expr.h" -int SaveFileContents(const char* filename, FileContents file); static int LoadPartitionContents(const char* filename, FileContents* file); -int ParseSha1(const char* str, uint8_t* digest); static ssize_t FileSink(unsigned char* data, ssize_t len, void* token); +static int GenerateTarget(FileContents* source_file, + const Value* source_patch_value, + FileContents* copy_file, + const Value* copy_patch_value, + const char* source_filename, + const char* target_filename, + const uint8_t target_sha1[SHA_DIGEST_SIZE], + size_t target_size); static int mtd_partitions_scanned = 0; @@ -113,11 +119,6 @@ static int compare_size_indices(const void* a, const void* b) { } } -void FreeFileContents(FileContents* file) { - if (file) free(file->data); - free(file); -} - // Load the contents of an MTD or EMMC partition into the provided // FileContents. filename should be a string of the form // "MTD:<partition_name>:<size_1>:<sha1_1>:<size_2>:<sha1_2>:..." (or @@ -322,7 +323,7 @@ static int LoadPartitionContents(const char* filename, FileContents* file) { // Save the contents of the given FileContents object under the given // filename. Return 0 on success. -int SaveFileContents(const char* filename, FileContents file) { +int SaveFileContents(const char* filename, const FileContents* file) { int fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC); if (fd < 0) { printf("failed to open \"%s\" for write: %s\n", @@ -330,10 +331,10 @@ int SaveFileContents(const char* filename, FileContents file) { return -1; } - ssize_t bytes_written = FileSink(file.data, file.size, &fd); - if (bytes_written != file.size) { + ssize_t bytes_written = FileSink(file->data, file->size, &fd); + if (bytes_written != file->size) { printf("short write of \"%s\" (%ld bytes of %ld) (%s)\n", - filename, (long)bytes_written, (long)file.size, + filename, (long)bytes_written, (long)file->size, strerror(errno)); close(fd); return -1; @@ -341,11 +342,11 @@ int SaveFileContents(const char* filename, FileContents file) { fsync(fd); close(fd); - if (chmod(filename, file.st.st_mode) != 0) { + if (chmod(filename, file->st.st_mode) != 0) { printf("chmod of \"%s\" failed: %s\n", filename, strerror(errno)); return -1; } - if (chown(filename, file.st.st_uid, file.st.st_gid) != 0) { + if (chown(filename, file->st.st_uid, file->st.st_gid) != 0) { printf("chown of \"%s\" failed: %s\n", filename, strerror(errno)); return -1; } @@ -471,7 +472,7 @@ int ParseSha1(const char* str, uint8_t* digest) { // Search an array of sha1 strings for one matching the given sha1. // Return the index of the match on success, or -1 if no match is // found. -int FindMatchingPatch(uint8_t* sha1, char** const patch_sha1_str, +int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str, int num_patches) { int i; uint8_t patch_sha1[SHA_DIGEST_SIZE]; @@ -503,6 +504,7 @@ int applypatch_check(const char* filename, "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 @@ -631,9 +633,10 @@ 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; - int made_copy = 0; // We try to load the target file into the source_file object. if (LoadFileContents(target_filename, &source_file, @@ -643,6 +646,7 @@ int applypatch(const char* source_filename, // has the desired hash, nothing for us to do. printf("\"%s\" is already target; no patch needed\n", target_filename); + free(source_file.data); return 0; } } @@ -653,6 +657,7 @@ int applypatch(const char* source_filename, // 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; LoadFileContents(source_filename, &source_file, RETOUCH_DO_MASK); } @@ -667,6 +672,7 @@ int applypatch(const char* source_filename, if (source_patch_value == NULL) { free(source_file.data); + source_file.data = NULL; printf("source file is bad; trying copy\n"); if (LoadFileContents(CACHE_TEMP_SOURCE, ©_file, @@ -685,16 +691,36 @@ 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, + ©_file, copy_patch_value, + source_filename, target_filename, + target_sha1, target_size); + free(source_file.data); + free(copy_file.data); + + return result; +} + +static int GenerateTarget(FileContents* source_file, + const Value* source_patch_value, + FileContents* copy_file, + const Value* copy_patch_value, + const char* source_filename, + const char* target_filename, + const uint8_t target_sha1[SHA_DIGEST_SIZE], + size_t target_size) { int retry = 1; SHA_CTX ctx; int output; MemorySinkInfo msi; FileContents* source_to_use; char* outname; + int made_copy = 0; // assume that target_filename (eg "/system/app/Foo.apk") is located // on the same filesystem as its top-level directory ("/system"). @@ -723,7 +749,7 @@ int applypatch(const char* source_filename, // 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->size) < 0) { printf("not enough free space on /cache\n"); return 1; } @@ -763,7 +789,7 @@ int applypatch(const char* source_filename, return 1; } - if (MakeFreeSpaceOnCache(source_file.size) < 0) { + if (MakeFreeSpaceOnCache(source_file->size) < 0) { printf("not enough free space on /cache\n"); return 1; } @@ -782,10 +808,10 @@ int applypatch(const char* source_filename, const Value* patch; if (source_patch_value != NULL) { - source_to_use = &source_file; + source_to_use = source_file; patch = source_patch_value; } else { - source_to_use = ©_file; + source_to_use = copy_file; patch = copy_patch_value; } diff --git a/applypatch/applypatch.h b/applypatch/applypatch.h index a78c89bfe..fb58843ba 100644 --- a/applypatch/applypatch.h +++ b/applypatch/applypatch.h @@ -62,9 +62,9 @@ int applypatch_check(const char* filename, int LoadFileContents(const char* filename, FileContents* file, int retouch_flag); -int SaveFileContents(const char* filename, FileContents file); +int SaveFileContents(const char* filename, const FileContents* file); void FreeFileContents(FileContents* file); -int FindMatchingPatch(uint8_t* sha1, char** const patch_sha1_str, +int FindMatchingPatch(uint8_t* sha1, const char** patch_sha1_str, int num_patches); // bsdiff.c |