diff options
author | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
---|---|---|
committer | Zeno Albisser <zeno.albisser@digia.com> | 2013-08-15 21:46:11 +0200 |
commit | 679147eead574d186ebf3069647b4c23e8ccace6 (patch) | |
tree | fc247a0ac8ff119f7c8550879ebb6d3dd8d1ff69 /chromium/third_party/bspatch/mbspatch.cc | |
download | qtwebengine-chromium-679147eead574d186ebf3069647b4c23e8ccace6.tar.gz |
Initial import.
Diffstat (limited to 'chromium/third_party/bspatch/mbspatch.cc')
-rw-r--r-- | chromium/third_party/bspatch/mbspatch.cc | 274 |
1 files changed, 274 insertions, 0 deletions
diff --git a/chromium/third_party/bspatch/mbspatch.cc b/chromium/third_party/bspatch/mbspatch.cc new file mode 100644 index 00000000000..164cc3caed0 --- /dev/null +++ b/chromium/third_party/bspatch/mbspatch.cc @@ -0,0 +1,274 @@ +/*- + * 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 <benjamin@smedbergs.us> + * 2007-11-14 - Added CalculateCrc() and ApplyBinaryPatch() methods. + * --Rahul Kuchhal + */ + +#include "mbspatch.h" + +#include <sys/stat.h> +#include <stdlib.h> +#include <stdio.h> +#include <fcntl.h> +#include <string.h> +#include <limits.h> + +#ifdef _WIN32 +# include <io.h> +# include <winsock2.h> +#else +# include <unistd.h> +# include <arpa/inet.h> +#endif + +extern "C" { +#include <7zCrc.h> +} + +#ifndef SSIZE_MAX +# define SSIZE_MAX LONG_MAX +#endif + +int +MBS_ReadHeader(int fd, MBSPatchHeader *header) +{ + int s = read(fd, header, sizeof(MBSPatchHeader)); + 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(fd, &hs); + if (s) + return READ_ERROR; + + if (memcmp(header->tag, "MBDIFF10", 8) != 0) + return UNEXPECTED_ERROR; + + if (sizeof(MBSPatchHeader) + + header->cblen + + header->difflen + + header->extralen != int(hs.st_size)) + return UNEXPECTED_ERROR; + + return OK; +} + +int +MBS_ApplyPatch(const MBSPatchHeader *header, int patchfd, + unsigned char *fbuffer, int filefd) +{ + unsigned char *fbufend = fbuffer + header->slen; + + unsigned char *buf = (unsigned char*) malloc(header->cblen + + header->difflen + + header->extralen); + if (!buf) + return MEM_ERROR; + + int rv = OK; + + int r = header->cblen + header->difflen + header->extralen; + unsigned char *wb = buf; + while (r) { + int c = read(patchfd, wb, (r > SSIZE_MAX) ? SSIZE_MAX : r); + if (c < 0) { + rv = READ_ERROR; + goto end; + } + + r -= c; + + if (c == 0 && r) { + rv = UNEXPECTED_ERROR; + goto end; + } + } + + { + 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_ERROR; + goto end; + } + for (unsigned int i = 0; i < ctrlsrc->x; ++i) { + diffsrc[i] += fbuffer[i]; + } + if ((int) write(filefd, diffsrc, ctrlsrc->x) != ctrlsrc->x) { + rv = WRITE_ERROR; + goto end; + } + fbuffer += ctrlsrc->x; + diffsrc += ctrlsrc->x; + + /* Copy y bytes from the extra block */ + + if (extrasrc + ctrlsrc->y > extraend) { + rv = UNEXPECTED_ERROR; + goto end; + } + if ((int) write(filefd, extrasrc, ctrlsrc->y) != ctrlsrc->y) { + rv = WRITE_ERROR; + goto end; + } + extrasrc += ctrlsrc->y; + + /* "seek" forwards in oldfile by z bytes */ + + if (fbuffer + ctrlsrc->z > fbufend) { + rv = UNEXPECTED_ERROR; + goto end; + } + fbuffer += ctrlsrc->z; + + /* and on to the next control block */ + + ++ctrlsrc; + } while (ctrlsrc < ctrlend); + } + +end: + free(buf); + return rv; +} + +int CalculateCrc(const unsigned char *buf, int size) { + CrcGenerateTable(); + unsigned int crc = 0xffffffffL; + crc = ~CrcCalc(buf, size); + return crc; +} + +/* _O_BINARY is a MSWindows open() mode flag. When absent, MSWindows + * open() translates CR+LF to LF; when present, it passes bytes + * through faithfully. Under *nix, we are always in binary mode, so + * the following #define turns this flag into a no-op w.r.t. bitwise + * OR. Note that this would be DANGEROUS AND UNSOUND if we used + * _O_BINARY other than as a bitwise OR mask (e.g., as a bitwise AND + * mask to check for binary mode), but it seems OK in the limited + * context of the following small function. */ +#ifndef _O_BINARY +# define _O_BINARY 0 +#endif + +int ApplyBinaryPatch(const wchar_t *old_file, const wchar_t *patch_file, + const wchar_t *new_file) { + int ret = OK; + int ofd = -1; + int nfd = -1; + unsigned char *buf = NULL; + + int pfd = _wopen(patch_file, O_RDONLY | _O_BINARY); + if (pfd < 0) return READ_ERROR; + + do { + MBSPatchHeader header; + if ((ret = MBS_ReadHeader(pfd, &header))) + break; + + ofd = _wopen(old_file, O_RDONLY | _O_BINARY); + if (ofd < 0) { + ret = READ_ERROR; + break; + } + + struct stat os; + if ((ret = fstat(ofd, &os))) { + ret = READ_ERROR; + break; + } + + if (os.st_size != header.slen) { + ret = UNEXPECTED_ERROR; + break; + } + + buf = (unsigned char*) malloc(header.slen); + if (!buf) { + ret = MEM_ERROR; + break; + } + + if (read(ofd, buf, header.slen) != header.slen) { + ret = READ_ERROR; + break; + } + + if (CalculateCrc(buf, header.slen) != header.scrc32) { + ret = CRC_ERROR; + break; + } + + nfd = _wopen(new_file, O_WRONLY | O_TRUNC | O_CREAT | _O_BINARY); + if (nfd < 0) { + ret = READ_ERROR; + break; + } + + MBS_ApplyPatch(&header, pfd, buf, nfd); + } while (0); + + free(buf); + close(pfd); + if (ofd >= 0) close(ofd); + if (nfd >= 0) close(nfd); + return ret; +} |