/*-
* 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 >
*/
#include "bspatch.h"
#include "updatererrors.h"
#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>
#if defined (XP_WIN)
# include <io.h>
#endif
#ifdef XP_WIN
# include <winsock2.h>
#else
# include <arpa/inet.h>
#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 != 0 ) {
return READ_ERROR;
}
if (memcmp(header->tag, "MBDIFF10" , 8 ) != 0 ) {
return UNEXPECTED_BSPATCH_ERROR;
}
if (hs.st_size > INT_MAX) {
return UNEXPECTED_BSPATCH_ERROR;
}
size_t size = static_cast <size_t>(hs.st_size);
if (size < sizeof (MBSPatchHeader)) {
return UNEXPECTED_BSPATCH_ERROR;
}
size -= sizeof (MBSPatchHeader);
if (size < header->cblen) {
return UNEXPECTED_BSPATCH_ERROR;
}
size -= header->cblen;
if (size < header->difflen) {
return UNEXPECTED_BSPATCH_ERROR;
}
size -= header->difflen;
if (size < header->extralen) {
return UNEXPECTED_BSPATCH_ERROR;
}
size -= header->extralen;
if (size != 0 ) {
return UNEXPECTED_BSPATCH_ERROR;
}
return OK;
}
int MBS_ApplyPatch(const MBSPatchHeader* header, FILE* patchFile,
const unsigned char* fbuffer, FILE* file) {
const unsigned char* fbufstart = fbuffer;
const 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 = (r > SSIZE_MAX) ? SSIZE_MAX : r;
size_t c = fread(wb, 1 , count, patchFile);
if (c != count) {
rv = READ_ERROR;
goto end;
}
r -= c;
wb += c;
if (c == 0 && r) {
rv = UNEXPECTED_BSPATCH_ERROR;
goto end;
}
}
{
MBSPatchTriple* ctrlsrc = (MBSPatchTriple*)buf;
if (header->cblen % sizeof (MBSPatchTriple) != 0 ) {
rv = UNEXPECTED_BSPATCH_ERROR;
goto end;
}
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;
while (ctrlsrc < ctrlend) {
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 (ctrlsrc->x > static_cast <size_t>(fbufend - fbuffer) ||
ctrlsrc->x > static_cast <size_t>(diffend - diffsrc)) {
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 (ctrlsrc->y > static_cast <size_t>(extraend - extrasrc)) {
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 (ctrlsrc->z < fbufstart - fbuffer || ctrlsrc->z > fbufend - fbuffer) {
rv = UNEXPECTED_BSPATCH_ERROR;
goto end;
}
fbuffer += ctrlsrc->z;
/* and on to the next control block */
++ctrlsrc;
}
}
end:
free(buf);
return rv;
}
Messung V0.5 in Prozent C=98 H=90 G=94
¤ Dauer der Verarbeitung: 0.7 Sekunden
¤
*© Formatika GbR, Deutschland