Back to index

lightning-sunbird  0.9+nobinonly
bspatch.cpp
Go to the documentation of this file.
00001 /*-
00002  * Copyright 2003,2004 Colin Percival
00003  * All rights reserved
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted providing that the following conditions
00007  * are met:
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  *
00014  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
00015  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00016  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00017  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
00018  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
00019  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
00020  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
00021  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
00022  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
00023  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00024  * POSSIBILITY OF SUCH DAMAGE.
00025  *
00026  * Changelog:
00027  * 2005-04-26 - Define the header as a C structure, add a CRC32 checksum to
00028  *              the header, and make all the types 32-bit.
00029  *                --Benjamin Smedberg <benjamin@smedbergs.us>
00030  */
00031 
00032 #include "bspatch.h"
00033 #include "errors.h"
00034 
00035 #include <sys/stat.h>
00036 #include <stdlib.h>
00037 #include <stdio.h>
00038 #include <fcntl.h>
00039 #include <string.h>
00040 #include <limits.h>
00041 
00042 #if defined(XP_WIN)
00043 # include <io.h>
00044 #else
00045 # include <unistd.h>
00046 #endif
00047 
00048 #ifdef XP_WIN
00049 # include <winsock2.h>
00050 #else
00051 # include <arpa/inet.h>
00052 #endif
00053 
00054 #ifndef SSIZE_MAX
00055 # define SSIZE_MAX LONG_MAX
00056 #endif
00057 
00058 int
00059 MBS_ReadHeader(int fd, MBSPatchHeader *header)
00060 {
00061   int s = read(fd, header, sizeof(MBSPatchHeader));
00062   if (s != sizeof(MBSPatchHeader))
00063     return READ_ERROR;
00064 
00065   header->slen      = ntohl(header->slen);
00066   header->scrc32    = ntohl(header->scrc32);
00067   header->dlen      = ntohl(header->dlen);
00068   header->cblen     = ntohl(header->cblen);
00069   header->difflen   = ntohl(header->difflen);
00070   header->extralen  = ntohl(header->extralen);
00071 
00072   struct stat hs;
00073   s = fstat(fd, &hs);
00074   if (s)
00075     return READ_ERROR;
00076 
00077   if (memcmp(header->tag, "MBDIFF10", 8) != 0)
00078     return UNEXPECTED_ERROR;
00079 
00080   if (sizeof(MBSPatchHeader) +
00081       header->cblen +
00082       header->difflen +
00083       header->extralen != PRUint32(hs.st_size))
00084     return UNEXPECTED_ERROR;
00085 
00086   return OK;
00087 }
00088          
00089 int
00090 MBS_ApplyPatch(const MBSPatchHeader *header, int patchfd,
00091                unsigned char *fbuffer, int filefd)
00092 {
00093   unsigned char *fbufend = fbuffer + header->slen;
00094 
00095   unsigned char *buf = (unsigned char*) malloc(header->cblen +
00096                                                header->difflen +
00097                                                header->extralen);
00098   if (!buf)
00099     return MEM_ERROR;
00100 
00101   int rv = OK;
00102 
00103   int r = header->cblen + header->difflen + header->extralen;
00104   unsigned char *wb = buf;
00105   while (r) {
00106     int c = read(patchfd, wb, (r > SSIZE_MAX) ? SSIZE_MAX : r);
00107     if (c < 0) {
00108       rv = READ_ERROR;
00109       goto end;
00110     }
00111 
00112     r -= c;
00113 
00114     if (c == 0 && r) {
00115       rv = UNEXPECTED_ERROR;
00116       goto end;
00117     }
00118   }
00119 
00120   {
00121     MBSPatchTriple *ctrlsrc = (MBSPatchTriple*) buf;
00122     unsigned char *diffsrc = buf + header->cblen;
00123     unsigned char *extrasrc = diffsrc + header->difflen;
00124 
00125     MBSPatchTriple *ctrlend = (MBSPatchTriple*) diffsrc;
00126     unsigned char *diffend = extrasrc;
00127     unsigned char *extraend = extrasrc + header->extralen;
00128 
00129     do {
00130       ctrlsrc->x = ntohl(ctrlsrc->x);
00131       ctrlsrc->y = ntohl(ctrlsrc->y);
00132       ctrlsrc->z = ntohl(ctrlsrc->z);
00133 
00134 #ifdef DEBUG_bsmedberg
00135       printf("Applying block:\n"
00136              " x: %u\n"
00137              " y: %u\n"
00138              " z: %i\n",
00139              ctrlsrc->x,
00140              ctrlsrc->y,
00141              ctrlsrc->z);
00142 #endif
00143 
00144       /* Add x bytes from oldfile to x bytes from the diff block */
00145 
00146       if (fbuffer + ctrlsrc->x > fbufend ||
00147           diffsrc + ctrlsrc->x > diffend) {
00148         rv = UNEXPECTED_ERROR;
00149         goto end;
00150       }
00151       for (PRUint32 i = 0; i < ctrlsrc->x; ++i) {
00152         diffsrc[i] += fbuffer[i];
00153       }
00154       if ((PRUint32) write(filefd, diffsrc, ctrlsrc->x) != ctrlsrc->x) {
00155         rv = WRITE_ERROR;
00156         goto end;
00157       }
00158       fbuffer += ctrlsrc->x;
00159       diffsrc += ctrlsrc->x;
00160 
00161       /* Copy y bytes from the extra block */
00162 
00163       if (extrasrc + ctrlsrc->y > extraend) {
00164         rv = UNEXPECTED_ERROR;
00165         goto end;
00166       }
00167       if ((PRUint32) write(filefd, extrasrc, ctrlsrc->y) != ctrlsrc->y) {
00168         rv = WRITE_ERROR;
00169         goto end;
00170       }
00171       extrasrc += ctrlsrc->y;
00172 
00173       /* "seek" forwards in oldfile by z bytes */
00174 
00175       if (fbuffer + ctrlsrc->z > fbufend) {
00176         rv = UNEXPECTED_ERROR;
00177         goto end;
00178       }
00179       fbuffer += ctrlsrc->z;
00180 
00181       /* and on to the next control block */
00182 
00183       ++ctrlsrc;
00184     } while (ctrlsrc < ctrlend);
00185   }
00186 
00187 end:
00188   free(buf);
00189   return rv;
00190 }