/*- * Copyright 2003,2004 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. * * Changelog: * 2005-04-26 - Define the header as a C structure, add a CRC32 checksum to * the header, and make all the types 32-bit. * --Benjamin Smedberg */ #include "bspatch.h" #include "errors.h" #include #include #include #include #include #include #include #if defined(_WIN32) # include #else # include #endif #ifdef _WIN32 # include #else # include #endif #ifndef SSIZE_MAX # define SSIZE_MAX LONG_MAX #endif int MBS_ReadHeader(FILE* file, MBSPatchHeader *header) { size_t s = fread(header, 1, sizeof(MBSPatchHeader), file); if (s != sizeof(MBSPatchHeader)) return READ_ERROR; header->slen = ntohl(header->slen); header->scrc32 = ntohl(header->scrc32); header->dlen = ntohl(header->dlen); header->cblen = ntohl(header->cblen); header->difflen = ntohl(header->difflen); header->extralen = ntohl(header->extralen); struct stat hs; s = fstat(fileno(file), &hs); if (s) return READ_ERROR; if (memcmp(header->tag, "MBDIFF10", 8) != 0) return UNEXPECTED_BSPATCH_ERROR; if (sizeof(MBSPatchHeader) + header->cblen + header->difflen + header->extralen != uint32_t(hs.st_size)) return UNEXPECTED_BSPATCH_ERROR; return OK; } int MBS_ApplyPatch(const MBSPatchHeader *header, FILE* patchFile, unsigned char *fbuffer, FILE* file) { unsigned char *fbufend = fbuffer + header->slen; unsigned char *buf = (unsigned char*) malloc(header->cblen + header->difflen + header->extralen); if (!buf) return BSPATCH_MEM_ERROR; int rv = OK; size_t r = header->cblen + header->difflen + header->extralen; unsigned char *wb = buf; while (r) { const size_t count = std::min(r, size_t(SSIZE_MAX)); size_t c = fread(wb, 1, count, patchFile); if (c != count) { rv = READ_ERROR; goto end; } r -= c; wb += c; } { MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf; unsigned char *diffsrc = buf + header->cblen; unsigned char *extrasrc = diffsrc + header->difflen; MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc; unsigned char *diffend = extrasrc; unsigned char *extraend = extrasrc + header->extralen; do { ctrlsrc->x = ntohl(ctrlsrc->x); ctrlsrc->y = ntohl(ctrlsrc->y); ctrlsrc->z = ntohl(ctrlsrc->z); #ifdef DEBUG_bsmedberg printf("Applying block:\n" " x: %u\n" " y: %u\n" " z: %i\n", ctrlsrc->x, ctrlsrc->y, ctrlsrc->z); #endif /* Add x bytes from oldfile to x bytes from the diff block */ if (fbuffer + ctrlsrc->x > fbufend || diffsrc + ctrlsrc->x > diffend) { rv = UNEXPECTED_BSPATCH_ERROR; goto end; } for (uint32_t i = 0; i < ctrlsrc->x; ++i) { diffsrc[i] += fbuffer[i]; } if ((uint32_t) fwrite(diffsrc, 1, ctrlsrc->x, file) != ctrlsrc->x) { rv = WRITE_ERROR_PATCH_FILE; goto end; } fbuffer += ctrlsrc->x; diffsrc += ctrlsrc->x; /* Copy y bytes from the extra block */ if (extrasrc + ctrlsrc->y > extraend) { rv = UNEXPECTED_BSPATCH_ERROR; goto end; } if ((uint32_t) fwrite(extrasrc, 1, ctrlsrc->y, file) != ctrlsrc->y) { rv = WRITE_ERROR_PATCH_FILE; goto end; } extrasrc += ctrlsrc->y; /* "seek" forwards in oldfile by z bytes */ if (fbuffer + ctrlsrc->z > fbufend) { rv = UNEXPECTED_BSPATCH_ERROR; goto end; } fbuffer += ctrlsrc->z; /* and on to the next control block */ ++ctrlsrc; } while (ctrlsrc < ctrlend); } end: free(buf); return rv; }