Annotation of libaitsync/src/aitsync.c, revision 1.5

1.1       misho       1: /*************************************************************************
                      2: * (C) 2010 AITNET ltd - Sofia/Bulgaria - <misho@aitbg.com>
                      3: *  by Michael Pounov <misho@openbsd-bg.org>
                      4: *
                      5: * $Author: misho $
1.5     ! misho       6: * $Id: aitsync.c,v 1.4.4.1 2013/05/30 09:23:51 misho Exp $
1.1       misho       7: *
1.2       misho       8: **************************************************************************
                      9: The ELWIX and AITNET software is distributed under the following
                     10: terms:
                     11: 
                     12: All of the documentation and software included in the ELWIX and AITNET
                     13: Releases is copyrighted by ELWIX - Sofia/Bulgaria <info@elwix.org>
                     14: 
1.5     ! misho      15: Copyright 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
1.2       misho      16:        by Michael Pounov <misho@elwix.org>.  All rights reserved.
                     17: 
                     18: Redistribution and use in source and binary forms, with or without
                     19: modification, are permitted provided that the following conditions
                     20: are met:
                     21: 1. Redistributions of source code must retain the above copyright
                     22:    notice, this list of conditions and the following disclaimer.
                     23: 2. Redistributions in binary form must reproduce the above copyright
                     24:    notice, this list of conditions and the following disclaimer in the
                     25:    documentation and/or other materials provided with the distribution.
                     26: 3. All advertising materials mentioning features or use of this software
                     27:    must display the following acknowledgement:
                     28: This product includes software developed by Michael Pounov <misho@elwix.org>
                     29: ELWIX - Embedded LightWeight unIX and its contributors.
                     30: 4. Neither the name of AITNET nor the names of its contributors
                     31:    may be used to endorse or promote products derived from this software
                     32:    without specific prior written permission.
                     33: 
                     34: THIS SOFTWARE IS PROVIDED BY AITNET AND CONTRIBUTORS ``AS IS'' AND
                     35: ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     36: IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     37: ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     38: FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     39: DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     40: OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     41: HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     42: LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     43: OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     44: SUCH DAMAGE.
                     45: */
1.1       misho      46: #include "global.h"
                     47: #include "tool.h"
                     48: #include "zc.h"
                     49: #include "patch.h"
                     50: #include "file.h"
                     51: 
                     52: 
                     53: static int sync_Errno;
                     54: static char sync_Error[STRSIZ];
                     55: 
                     56: 
1.3       misho      57: static inline int
                     58: func_comp(sync_tag_t const *t1, sync_tag_t const *t2)
1.1       misho      59: {
                     60:        return t1->st_tag - t2->st_tag;
                     61: }
                     62: 
1.4       misho      63: /*
                     64:  * Error maintenance functions ...
                     65:  */
1.1       misho      66: 
                     67: // sync_GetErrno() Get error code of last operation
1.5     ! misho      68: int
1.3       misho      69: sync_GetErrno()
1.1       misho      70: {
                     71:        return sync_Errno;
                     72: }
                     73: 
                     74: // sync_GetError() Get error text of last operation
1.5     ! misho      75: const char *
1.3       misho      76: sync_GetError()
1.1       misho      77: {
                     78:        return sync_Error;
                     79: }
                     80: 
                     81: // sync_SetErr() Set error to variables for internal use!!!
1.5     ! misho      82: void
1.4       misho      83: sync_SetErr(int eno, char *estr, ...)
1.1       misho      84: {
                     85:        va_list lst;
                     86: 
                     87:        sync_Errno = eno;
1.4       misho      88:        memset(sync_Error, 0, sizeof sync_Error);
1.1       misho      89:        va_start(lst, estr);
1.4       misho      90:        vsnprintf(sync_Error, sizeof sync_Error, estr, lst);
1.1       misho      91:        va_end(lst);
                     92: }
                     93: 
1.4       misho      94: /* ---------------------------------------------------------- */
1.1       misho      95: 
                     96: /*
1.4       misho      97:  * syncSignature() - Calculate and create signature for diff
                     98:  *
                     99:  * @csInput = Input target file name for calculating check sums
1.1       misho     100:  * @csSig = Output Signature file name
1.2       misho     101:  * @compress = 2 compress signatures output, 0 not compressed
1.1       misho     102:  * return: -1 error, 0 ok
                    103:  */
1.3       misho     104: int
                    105: syncSignature(const char *csInput, const char *csSig, int compress)
1.1       misho     106: {
1.2       misho     107:        int inf, outf, f, ret;
1.1       misho     108:        u_char buf[CHUNK_MAX];
                    109:        register int i = 0;
                    110:        off_t off = 0ll;
                    111:        sync_chunk_t sc;
1.2       misho     112:        char szTemp[MAXPATHLEN];
1.1       misho     113: 
1.4       misho     114:        /* open work files */
                    115:        inf = sync_Open(csInput, O_RDONLY, 0);
1.1       misho     116:        if (inf == -1)
                    117:                return inf;
1.2       misho     118:        if (compress & 2)
1.4       misho     119:                f = sync_Temp(szTemp, sizeof szTemp);
1.2       misho     120:        else
1.4       misho     121:                f = sync_Open(csSig, O_WRONLY, 0);
1.2       misho     122:        if (f == -1) {
1.4       misho     123:                sync_Close(inf);
1.2       misho     124:                return f;
1.1       misho     125:        }
                    126: 
                    127:        for (i = 0, off = 0ll, ret = -1; ret; i++, off += ret) {
                    128:                memset(buf, 0, CHUNK_MAX);
                    129:                ret = read(inf, buf, CHUNK_MAX);
                    130:                if (ret == -1) {
1.4       misho     131:                        LOGERR;
1.1       misho     132:                        break;
                    133:                }
                    134: 
1.4       misho     135:                /* fill chunk */
1.1       misho     136:                sync_mksig(i, off, buf, ret, &sc);
                    137: 
1.2       misho     138:                if (write(f, &sc, sizeof sc) == -1) {
1.4       misho     139:                        LOGERR;
1.1       misho     140:                        break;
                    141:                }
                    142:        }
                    143: 
1.4       misho     144:        /* Signatures are READY */
1.2       misho     145: 
                    146:        if (compress & 2) {
1.4       misho     147:                /* build compressed delta file */
                    148:                outf = sync_Open(csSig, O_WRONLY, 0);
1.2       misho     149:                if (outf == -1) {
                    150:                        ret = outf;
                    151:                        goto end;
                    152:                }
                    153:                if (sync_Deflate(f, outf, Z_DEFAULT_COMPRESSION) == -1) {
1.4       misho     154:                        sync_Close(outf);
1.2       misho     155:                        unlink(csSig);
                    156:                        ret = -1;
                    157:                        goto end;
                    158:                }
1.4       misho     159:                sync_Close(outf);
1.2       misho     160:        }
                    161: end:
1.4       misho     162:        sync_Close(f);
1.2       misho     163:        if (compress & 2)
                    164:                unlink(szTemp);
1.4       misho     165:        sync_Close(inf);
1.1       misho     166:        return ret;
                    167: }
                    168: 
                    169: /*
1.4       misho     170:  * syncDelta() - Create Delta patch file
                    171:  *
1.1       misho     172:  * @csInput = Input original source file name for make delta patch file
1.4       misho     173:  * @csSig = Input target Signature file name
1.1       misho     174:  * @csDelta = Output Delta patch file name
1.2       misho     175:  * @compress = 3 everything compress, 2 compressed signatures, 1 compress delta output, 0 not compressed
1.1       misho     176:  * return: -1 error, 0 ok
                    177:  */
1.3       misho     178: int
                    179: syncDelta(const char *csInput, const char *csSig, const char *csDelta, int compress)
1.1       misho     180: {
                    181:        int inf, outf, f, sigf, ret, cnt;
                    182:        size_t blk;
                    183:        register int i, j, c, cx;
                    184:        struct stat sb, sb_f;
                    185:        u_long tags[TABLESIZ];
                    186:        sync_tag_t *tag_table;
                    187:        sync_chunk_t *chunks, *find, sc;
                    188:        u_char buf[CHUNK_MAX];
                    189:        off_t off;
                    190:        char szTemp[MAXPATHLEN];
                    191: 
                    192:        /* load signatures */
                    193: 
1.2       misho     194:        if (compress & 2) {
1.4       misho     195:                f = sync_Open(csSig, O_RDONLY, 0);
1.2       misho     196:                if (-1 == f)
                    197:                        return f;
1.4       misho     198:                sigf = sync_Temp(szTemp, sizeof szTemp);
1.2       misho     199:                if (-1 == sigf) {
1.4       misho     200:                        sync_Close(f);
1.2       misho     201:                        return sigf;
                    202:                }
                    203: 
                    204:                if (sync_Inflate(f, sigf) == -1) {
1.4       misho     205:                        sync_Close(sigf);
                    206:                        sync_Close(f);
1.2       misho     207:                        unlink(szTemp);
                    208:                        return -1;
                    209:                } else
1.4       misho     210:                        sync_Close(f);
1.2       misho     211:        } else {
1.4       misho     212:                sigf = sync_Open(csSig, O_RDONLY, 0);
1.2       misho     213:                if (-1 == sigf)
                    214:                        return sigf;
1.1       misho     215:        }
1.2       misho     216: 
1.1       misho     217:        if (fstat(sigf, &sb) == -1) {
1.4       misho     218:                LOGERR;
                    219:                sync_Close(sigf);
1.2       misho     220:                if (compress & 2)
                    221:                        unlink(szTemp);
1.1       misho     222:                return -1;
                    223:        } else {
                    224:                if (!sb.st_size) {
1.4       misho     225:                        sync_Close(sigf);
1.2       misho     226:                        if (compress & 2)
                    227:                                unlink(szTemp);
1.1       misho     228:                        return 1;
                    229:                }
                    230: 
                    231:                cnt = sb.st_size / sizeof(sync_chunk_t);
                    232:                if (sb.st_size % sizeof(sync_chunk_t)) {
1.4       misho     233:                        sync_SetErr(ENOEXEC, "Error:: signature file is broken!\n");
                    234:                        sync_Close(sigf);
1.2       misho     235:                        if (compress & 2)
                    236:                                unlink(szTemp);
1.1       misho     237:                        return -1;
                    238:                }
                    239:        }
                    240:        chunks = (sync_chunk_t*) mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, sigf, 0);
                    241:        if (MAP_FAILED == chunks) {
1.4       misho     242:                LOGERR;
                    243:                sync_Close(sigf);
1.2       misho     244:                if (compress & 2)
                    245:                        unlink(szTemp);
1.1       misho     246:                return -1;
1.2       misho     247:        } else {
1.4       misho     248:                sync_Close(sigf);
1.2       misho     249:                if (compress & 2)
                    250:                        unlink(szTemp);
1.1       misho     251:        }
                    252: 
                    253:        /* build from signatures sorted index and hashes */
                    254: 
1.4       misho     255:        /* init first stage tags array index */
1.1       misho     256:        for (i = 0; i < TABLESIZ; i++)
                    257:                tags[i] = NULL_TAG;
                    258: 
1.4       misho     259:        /* build second index from signature blocks */
1.1       misho     260:        tag_table = (sync_tag_t*) calloc(cnt, sizeof(sync_tag_t));
                    261:        if (!tag_table) {
1.4       misho     262:                LOGERR;
1.1       misho     263:                munmap(chunks, sb.st_size);
                    264:                return -1;
                    265:        } else {
                    266:                for (i = 0; i < cnt; i++) {
                    267:                        tag_table[i].st_id = i;
                    268:                        tag_table[i].st_tag = GETTAG(chunks[i].sc_roll);
                    269:                }
                    270: 
1.4       misho     271:                qsort(tag_table, cnt, sizeof(sync_tag_t), 
                    272:                                (int (*)(const void *, const void *)) func_comp);
1.1       misho     273:        }
1.4       misho     274:        /* assign less id position in tag_table to tags. 
                    275:         * It made relation between 1st & 2nd indexes */
1.1       misho     276:        for (i = cnt - 1; i > -1; i--)
                    277:                tags[tag_table[i].st_tag] = i;
                    278: 
1.4       misho     279: 
1.1       misho     280:        /* build delta patch */
                    281: 
1.4       misho     282:        inf = sync_Open(csInput, O_RDONLY, 0);
1.1       misho     283:        if (inf == -1) {
                    284:                free(tag_table);
                    285:                munmap(chunks, sb.st_size);
                    286:                return inf;
                    287:        }
1.2       misho     288:        if (compress & 1)
1.4       misho     289:                f = sync_Temp(szTemp, sizeof szTemp);
1.1       misho     290:        else
1.4       misho     291:                f = sync_Open(csDelta, O_WRONLY, 0);
1.1       misho     292:        if (f == -1) {
1.4       misho     293:                sync_Close(inf);
1.1       misho     294:                free(tag_table);
                    295:                munmap(chunks, sb.st_size);
                    296:                return f;
                    297:        }
                    298: 
1.4       misho     299:        for (i = 0, off = 0ll, ret = -1, blk = 0; 
                    300:                        (ret = read(inf, buf, CHUNK_MAX)); i++, off += ret) {
1.1       misho     301:                if (ret == -1) {
1.4       misho     302:                        LOGERR;
1.1       misho     303:                        break;
                    304:                }
                    305:                find = NULL;
                    306: 
1.4       misho     307: #if 0
                    308:                printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk);
                    309: #endif
1.1       misho     310: 
1.4       misho     311:                /* check chunk for differences with signature */
1.1       misho     312:                sync_mksig(i, off, buf, ret, &sc);
                    313:                cx = GETTAG(sc.sc_roll);
1.4       misho     314:                /* find in hash -> hash_sorted_table */
1.1       misho     315:                if (NULL_TAG != tags[cx] && tag_table[tags[cx]].st_tag == cx) {
1.4       misho     316:                        /* find in hash_sorted_table crc == -> real chunks id */
                    317:                        for (j = 0, c = tag_table[tags[cx]].st_id; 
                    318:                                        tag_table[tags[cx] + j].st_tag == cx; 
1.1       misho     319:                                        j++, c = tag_table[tags[cx] + j].st_id) {
1.4       misho     320:                                if (chunks[c].sc_magic == sc.sc_magic && 
                    321:                                                chunks[c].sc_len == sc.sc_len && 
1.1       misho     322:                                                chunks[c].sc_roll == sc.sc_roll && 
                    323:                                                !memcmp(chunks[c].sc_cksum, sc.sc_cksum, MD5_DIGEST_LENGTH)) {
                    324:                                        find = &chunks[c];
                    325:                                        break;
                    326:                                }
                    327:                        }
                    328:                }
                    329: 
1.4       misho     330: #if 0
                    331:                printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk);
                    332: #endif
1.1       misho     333: 
1.4       misho     334:                /* if match chunk, check for previous match */
1.1       misho     335:                if (!blk && find)
                    336:                        continue;
1.4       misho     337:                /* if not find chunk in signature skip write to delta patch */
1.1       misho     338:                if (!find) {
1.4       misho     339:                        /* different piece, write it! 
                    340:                         * Write signature of current chunk */
1.1       misho     341:                        ret = write(f, &sc, sizeof sc);
                    342:                        if (-1 == ret) {
1.4       misho     343:                                LOGERR;
1.1       misho     344:                                break;
                    345:                        }
1.4       misho     346:                        /* if write chunk len is differnt from requested len */
1.1       misho     347:                        if (ret != sizeof sc) {
1.4       misho     348:                                sync_SetErr(ENOEXEC, "Error:: delta file signature is broken!\n");
1.1       misho     349:                                ret = -1;
                    350:                                break;
                    351:                        }
1.4       misho     352:                        /* write current chunk data ... */
1.1       misho     353:                        ret = write(f, buf, sc.sc_len);
                    354:                        if (-1 == ret) {
1.4       misho     355:                                LOGERR;
1.1       misho     356:                                break;
                    357:                        }
1.4       misho     358:                        /* if write chunk len is differnt from requested len */
1.1       misho     359:                        if (ret != sc.sc_len) {
1.4       misho     360:                                sync_SetErr(ENOEXEC, "Error:: delta file data is broken!\n");
1.1       misho     361:                                ret = -1;
                    362:                                break;
                    363:                        }
                    364:                        blk += sc.sc_len;
                    365: 
                    366:                        continue;
                    367:                }
1.4       misho     368:                /* match 1st block after difference and copy signature from B */
1.1       misho     369:                memcpy(&sc, find, sizeof sc);
                    370:                sc.sc_magic = SIGSYNC_MAGIC;
                    371:                sc.sc_len = blk;
                    372: 
1.4       misho     373:                /* write signature from chunk B */
1.1       misho     374:                blk = write(f, &sc, sizeof sc);
                    375:                if (-1 == blk) {
1.4       misho     376:                        LOGERR;
1.1       misho     377:                        break;
                    378:                }
1.4       misho     379:                /* if write chunk len is differnt from requested len */
1.1       misho     380:                if (blk != sizeof sc) {
1.4       misho     381:                        sync_SetErr(ENOEXEC, "Error:: delta file end signature is broken!\n");
1.1       misho     382:                        ret = -1;
                    383:                        break;
                    384:                }
                    385: 
                    386:                blk ^= blk;
                    387:        }
                    388: 
1.4       misho     389:        /* check for error or empty delta file */
1.1       misho     390:        if (ret == -1)
                    391:                goto end;
                    392:        fsync(f);
                    393:        if (fstat(f, &sb_f) == -1) {
1.4       misho     394:                LOGERR;
1.1       misho     395:                ret = -1;
                    396:                goto end;
                    397:        }
                    398: 
1.4       misho     399:        /* No deferences, not needed delta.patch !!! */
1.1       misho     400:        if (!sb_f.st_size) {
                    401:                ret = 1;
                    402:                goto end;
                    403:        }
                    404: 
                    405:        /* Delta patch is READY */
                    406: 
1.4       misho     407:        /* build compressed delta file */
1.2       misho     408:        if (compress & 1) {
1.4       misho     409:                outf = sync_Open(csDelta, O_WRONLY, 0);
1.1       misho     410:                if (outf == -1) {
                    411:                        ret = outf;
                    412:                        goto end;
                    413:                }
                    414:                if (sync_Deflate(f, outf, Z_DEFAULT_COMPRESSION) == -1) {
1.4       misho     415:                        sync_Close(outf);
1.1       misho     416:                        unlink(csDelta);
                    417:                        ret = -1;
                    418:                        goto end;
                    419:                }
1.4       misho     420:                sync_Close(outf);
1.1       misho     421:        }
                    422: 
                    423: end:
1.4       misho     424:        sync_Close(f);
1.2       misho     425:        if (compress & 1)
                    426:                unlink(szTemp);
1.4       misho     427:        sync_Close(inf);
1.1       misho     428:        free(tag_table);
                    429:        munmap(chunks, sb.st_size);
                    430:        return ret;
                    431: }
                    432: 
                    433: /*
1.4       misho     434:  * syncPatch() - Apply delta patch file to target
                    435:  *
1.1       misho     436:  * @csInput = Input target file name for patch
                    437:  * @csDelta = Input Delta patch file name
                    438:  * @csPatch = After applied patch create new alternate target file, if != NULL
1.2       misho     439:  * @compress = 1 compress delta input, 0 not compressed
1.1       misho     440:  * return: -1 error, 0 ok, create delta patch, 1 ok, no differences and not create patch
                    441:  */
1.3       misho     442: int
                    443: syncPatch(const char *csInput, const char *csDelta, const char *csPatch, int compress)
1.1       misho     444: {
                    445:        int inf, outf, f, d, ret, readlen;
                    446:        char szTemp[MAXPATHLEN];
                    447:        u_char *buffer, buf[CHUNK_MAX];
                    448:        struct stat sb;
                    449:        void *delta;
                    450:        struct tagPiece *piece, *pieces = NULL;
                    451:        register int i;
                    452:        off_t off;
                    453:        sync_chunk_t sc, *suffix;
                    454: 
1.2       misho     455:        if (compress & 1) {
1.4       misho     456:                f = sync_Open(csDelta, O_RDONLY, 0);
1.1       misho     457:                if (f == -1)
                    458:                        return f;
1.4       misho     459:                d = sync_Temp(szTemp, sizeof szTemp);
1.1       misho     460:                if (d == -1) {
1.4       misho     461:                        sync_Close(f);
1.1       misho     462:                        return d;
                    463:                }
                    464:                
                    465:                if (sync_Inflate(f, d) == -1) {
1.4       misho     466:                        sync_Close(d);
                    467:                        sync_Close(f);
1.1       misho     468:                        unlink(szTemp);
                    469:                        return -1;
                    470:                } else
1.4       misho     471:                        sync_Close(f);
1.1       misho     472:        } else {
1.4       misho     473:                d = sync_Open(csDelta, O_RDONLY, 0);
1.1       misho     474:                if (d == -1)
                    475:                        return d;
                    476:        }
                    477: 
                    478:        if (fstat(d, &sb) == -1) {
1.4       misho     479:                LOGERR;
                    480:                sync_Close(d);
1.2       misho     481:                if (compress & 1)
1.1       misho     482:                        unlink(szTemp);
                    483:                return -1;
                    484:        }
                    485:        delta = mmap(0, sb.st_size, PROT_READ, MAP_PRIVATE, d, 0);
                    486:        if (MAP_FAILED == delta) {
1.4       misho     487:                LOGERR;
                    488:                sync_Close(d);
1.2       misho     489:                if (compress & 1)
1.1       misho     490:                        unlink(szTemp);
                    491:                return -1;
                    492:        } else {
1.4       misho     493:                sync_Close(d);
1.2       misho     494:                if (compress & 1)
1.1       misho     495:                        unlink(szTemp);
                    496:        }
                    497: 
                    498:        if (sync_buildPatch(delta, sb.st_size, &pieces) == -1 || !pieces) {
1.4       misho     499:                sync_SetErr(ENOEXEC, "Error:: patch file is broken!\n");
1.1       misho     500:                munmap(delta, sb.st_size);
                    501:                return -1;
                    502:        }
                    503: 
1.4       misho     504:        inf = sync_Open(csInput, O_RDONLY, 0);
1.1       misho     505:        if (inf == -1) {
                    506:                if (pieces)
                    507:                        free(pieces);
                    508:                munmap(delta, sb.st_size);
                    509:                return inf;
                    510:        }
1.4       misho     511:        outf = sync_Open(csPatch, O_WRONLY, 0);
1.1       misho     512:        if (outf == -1) {
1.4       misho     513:                sync_Close(inf);
1.1       misho     514:                if (pieces)
                    515:                        free(pieces);
                    516:                munmap(delta, sb.st_size);
                    517:                return outf;
                    518:        }
                    519: 
                    520:        if (fstat(inf, &sb) == -1) {
1.4       misho     521:                LOGERR;
1.1       misho     522:                ret = -1;
                    523:                goto end;
                    524:        } else {
                    525:                if (!sb.st_size) {
                    526:                        ret = -1;
                    527:                        goto end;
                    528:                }
                    529:        }
                    530: 
                    531:        ret = readlen = 0;
                    532:        buffer = NULL;
1.4       misho     533:        for (i = 0, off = 0ll, suffix = NULL, piece = pieces; piece->pfx; 
                    534:                        i++, off += readlen) {
                    535: #if 0
                    536:                printf("i=%d off=%llu sfx=%p piece=%p\n", i, off, suffix, piece);
                    537: #endif
1.1       misho     538: 
1.4       misho     539:                /* if input offset is less then input file size */
1.1       misho     540:                if (off < sb.st_size) {
                    541:                        readlen = read(inf, buf, CHUNK_MAX);
                    542:                        if (readlen == -1) {
1.4       misho     543:                                LOGERR;
1.1       misho     544:                                ret = -1;
                    545:                                break;
                    546:                        }
1.4       misho     547:                        /* if suffix find, check for correct patch */
1.1       misho     548:                        if (suffix) {
1.4       misho     549:                                if (suffix->sc_len != readlen || 
                    550:                                                suffix->sc_off != off) {
                    551:                                        sync_SetErr(ENOEXEC, "Error:: patch file is broken! "
                    552:                                                        "(wrong suffix pos)\n");
1.1       misho     553:                                        ret = -1;
                    554:                                        break;
                    555:                                }
                    556:                                sync_mksig(i, off, buf, readlen, &sc);
                    557:                                if (sc.sc_roll != suffix->sc_roll || 
1.4       misho     558:                                                memcmp(sc.sc_cksum, suffix->sc_cksum, 
                    559:                                                        MD5_DIGEST_LENGTH)) {
                    560:                                        sync_SetErr(ENOEXEC, "Error:: patch file is broken! "
                    561:                                                        "(wrong suffix crc)\n");
1.1       misho     562:                                        ret = -1;
                    563:                                        break;
                    564:                                }
                    565: 
                    566:                                suffix = NULL;
                    567:                        }
                    568: 
                    569:                        buffer = buf;
                    570:                }
                    571: 
1.4       misho     572: #if 0
                    573:                printf("i=%d off=%llu sfx=%p piece=%p pfx=%p pfx_off=%llu\n", i, off, 
                    574:                                suffix, piece, piece ? piece->pfx : 0l, 
                    575:                                piece->pfx ? piece->pfx->sc_off : 0l);
                    576: #endif
1.1       misho     577: 
1.4       misho     578:                /* if delta chunk match! */
1.1       misho     579:                if (piece->pfx && piece->pfx->sc_off == off) {
                    580:                        if (!piece->buf) {
1.4       misho     581:                                sync_SetErr(ENOEXEC, "Error:: patch file is broken! "
                    582:                                                "(missing data)\n");
1.1       misho     583:                                ret = -1;
                    584:                                break;
                    585:                        }
                    586: 
                    587:                        buffer = piece->buf;
                    588:                        readlen = piece->pfx->sc_len;
                    589:                        suffix = piece->sfx ? piece->sfx : NULL;
                    590: 
                    591:                        piece++;
                    592: 
                    593:                        if (suffix && off >= sb.st_size) {
1.4       misho     594:                                sync_SetErr(ENOEXEC, "Error:: patch file is broken! "
                    595:                                                "(after eof find suffix)\n");
1.1       misho     596:                                ret = -1;
                    597:                                break;
                    598:                        }
1.4       misho     599:                } else if (off >= sb.st_size) {
                    600:                       if (piece->pfx) {
                    601:                                sync_SetErr(ENOEXEC, "Error:: patch file is broken! "
                    602:                                                "(after eof find prefix)\n");
                    603:                                ret = -1;
                    604:                        }
1.1       misho     605: 
1.4       misho     606:                        break;
                    607:                }
1.1       misho     608: 
                    609:                ret = write(outf, buffer, readlen);
                    610:                if (ret == -1 || ret != readlen) {
1.4       misho     611:                        LOGERR;
1.1       misho     612:                        break;
                    613:                }
                    614:        }
                    615: 
                    616: end:
1.4       misho     617:        sync_Close(inf);
                    618:        sync_Close(outf);
1.1       misho     619:        if (pieces)
                    620:                free(pieces);
                    621:        munmap(delta, sb.st_size);
                    622:        return ret;
                    623: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>