|
version 1.3.2.2, 2012/11/13 10:30:44
|
version 1.3.2.3, 2012/11/13 13:19:15
|
|
Line 96 sync_SetErr(int eno, char *estr, ...)
|
Line 96 sync_SetErr(int eno, char *estr, ...)
|
| /* |
/* |
| * syncSignature() - Calculate and create signature for diff |
* syncSignature() - Calculate and create signature for diff |
| * |
* |
| * @csInput = Input file name for calculating check sums | * @csInput = Input target file name for calculating check sums |
| * @csSig = Output Signature file name |
* @csSig = Output Signature file name |
| * @compress = 2 compress signatures output, 0 not compressed |
* @compress = 2 compress signatures output, 0 not compressed |
| * return: -1 error, 0 ok |
* return: -1 error, 0 ok |
|
Line 141 syncSignature(const char *csInput, const char *csSig,
|
Line 141 syncSignature(const char *csInput, const char *csSig,
|
| } |
} |
| } |
} |
| |
|
| /* Signatures is READY */ | /* Signatures are READY */ |
| |
|
| if (compress & 2) { |
if (compress & 2) { |
| /* build compressed delta file */ |
/* build compressed delta file */ |
|
Line 167 end:
|
Line 167 end:
|
| } |
} |
| |
|
| /* |
/* |
| * syncDelta() Create Delta patch file | * syncDelta() - Create Delta patch file |
| | * |
| * @csInput = Input original source file name for make delta patch file |
* @csInput = Input original source file name for make delta patch file |
| * @csSig = Input Signature file name | * @csSig = Input target Signature file name |
| * @csDelta = Output Delta patch file name |
* @csDelta = Output Delta patch file name |
| * @compress = 3 everything compress, 2 compressed signatures, 1 compress delta output, 0 not compressed |
* @compress = 3 everything compress, 2 compressed signatures, 1 compress delta output, 0 not compressed |
| * return: -1 error, 0 ok |
* return: -1 error, 0 ok |
|
Line 251 syncDelta(const char *csInput, const char *csSig, cons
|
Line 252 syncDelta(const char *csInput, const char *csSig, cons
|
| |
|
| /* build from signatures sorted index and hashes */ |
/* build from signatures sorted index and hashes */ |
| |
|
| // init tags array | /* init first stage tags array index */ |
| for (i = 0; i < TABLESIZ; i++) |
for (i = 0; i < TABLESIZ; i++) |
| tags[i] = NULL_TAG; |
tags[i] = NULL_TAG; |
| |
|
| // build index from signature blocks | /* build second index from signature blocks */ |
| tag_table = (sync_tag_t*) calloc(cnt, sizeof(sync_tag_t)); |
tag_table = (sync_tag_t*) calloc(cnt, sizeof(sync_tag_t)); |
| if (!tag_table) { |
if (!tag_table) { |
| LOGERR; |
LOGERR; |
|
Line 267 syncDelta(const char *csInput, const char *csSig, cons
|
Line 268 syncDelta(const char *csInput, const char *csSig, cons
|
| tag_table[i].st_tag = GETTAG(chunks[i].sc_roll); |
tag_table[i].st_tag = GETTAG(chunks[i].sc_roll); |
| } |
} |
| |
|
| qsort(tag_table, cnt, sizeof(sync_tag_t), (int (*)(const void *, const void *)) func_comp); | qsort(tag_table, cnt, sizeof(sync_tag_t), |
| | (int (*)(const void *, const void *)) func_comp); |
| } |
} |
| // assign less id position in tag_table to tags | /* assign less id position in tag_table to tags. |
| | * It made relation between 1st & 2nd indexes */ |
| for (i = cnt - 1; i > -1; i--) |
for (i = cnt - 1; i > -1; i--) |
| tags[tag_table[i].st_tag] = i; |
tags[tag_table[i].st_tag] = i; |
| |
|
| |
|
| /* build delta patch */ |
/* build delta patch */ |
| |
|
| inf = sync_Open(csInput, O_RDONLY, 0); |
inf = sync_Open(csInput, O_RDONLY, 0); |
|
Line 292 syncDelta(const char *csInput, const char *csSig, cons
|
Line 296 syncDelta(const char *csInput, const char *csSig, cons
|
| return f; |
return f; |
| } |
} |
| |
|
| for (i = 0, off = 0ll, ret = -1, blk = 0; (ret = read(inf, buf, CHUNK_MAX)); i++, off += ret) { | for (i = 0, off = 0ll, ret = -1, blk = 0; |
| | (ret = read(inf, buf, CHUNK_MAX)); i++, off += ret) { |
| if (ret == -1) { |
if (ret == -1) { |
| LOGERR; |
LOGERR; |
| break; |
break; |
| } |
} |
| find = NULL; |
find = NULL; |
| |
|
| // printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk); | #if 0 |
| | printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk); |
| | #endif |
| |
|
| // check chunk for differences with signature | /* check chunk for differences with signature */ |
| sync_mksig(i, off, buf, ret, &sc); |
sync_mksig(i, off, buf, ret, &sc); |
| cx = GETTAG(sc.sc_roll); |
cx = GETTAG(sc.sc_roll); |
| // find in hash -> hash_sorted_table | /* find in hash -> hash_sorted_table */ |
| if (NULL_TAG != tags[cx] && tag_table[tags[cx]].st_tag == cx) { |
if (NULL_TAG != tags[cx] && tag_table[tags[cx]].st_tag == cx) { |
| // find in hash_sorted_table crc == -> real chunks id | /* find in hash_sorted_table crc == -> real chunks id */ |
| for (j = 0, c = tag_table[tags[cx]].st_id; tag_table[tags[cx] + j].st_tag == cx; | for (j = 0, c = tag_table[tags[cx]].st_id; |
| | tag_table[tags[cx] + j].st_tag == cx; |
| j++, c = tag_table[tags[cx] + j].st_id) { |
j++, c = tag_table[tags[cx] + j].st_id) { |
| if (chunks[c].sc_magic == sc.sc_magic && chunks[c].sc_len == sc.sc_len && | if (chunks[c].sc_magic == sc.sc_magic && |
| | chunks[c].sc_len == sc.sc_len && |
| chunks[c].sc_roll == sc.sc_roll && |
chunks[c].sc_roll == sc.sc_roll && |
| !memcmp(chunks[c].sc_cksum, sc.sc_cksum, MD5_DIGEST_LENGTH)) { |
!memcmp(chunks[c].sc_cksum, sc.sc_cksum, MD5_DIGEST_LENGTH)) { |
| find = &chunks[c]; |
find = &chunks[c]; |
|
Line 318 syncDelta(const char *csInput, const char *csSig, cons
|
Line 327 syncDelta(const char *csInput, const char *csSig, cons
|
| } |
} |
| } |
} |
| |
|
| // printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk); | #if 0 |
| | printf("+ find=%p off=%llu i=%d blk=%d\n", find, off, i, blk); |
| | #endif |
| |
|
| // if match chunk, check for previous match | /* if match chunk, check for previous match */ |
| if (!blk && find) |
if (!blk && find) |
| continue; |
continue; |
| // if not find chunk in signature skip write to delta patch | /* if not find chunk in signature skip write to delta patch */ |
| if (!find) { |
if (!find) { |
| /* different piece, write it! */ | /* different piece, write it! |
| // write signature of current chunk | * Write signature of current chunk */ |
| ret = write(f, &sc, sizeof sc); |
ret = write(f, &sc, sizeof sc); |
| if (-1 == ret) { |
if (-1 == ret) { |
| LOGERR; |
LOGERR; |
| break; |
break; |
| } |
} |
| // if write chunk len is differnt from requested len | /* if write chunk len is differnt from requested len */ |
| if (ret != sizeof sc) { |
if (ret != sizeof sc) { |
| sync_SetErr(ENOEXEC, "Error:: delta file signature is broken!\n"); |
sync_SetErr(ENOEXEC, "Error:: delta file signature is broken!\n"); |
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
| // write current chunk ... | /* write current chunk data ... */ |
| ret = write(f, buf, sc.sc_len); |
ret = write(f, buf, sc.sc_len); |
| if (-1 == ret) { |
if (-1 == ret) { |
| LOGERR; |
LOGERR; |
| break; |
break; |
| } |
} |
| // if write chunk len is differnt from requested len | /* if write chunk len is differnt from requested len */ |
| if (ret != sc.sc_len) { |
if (ret != sc.sc_len) { |
| sync_SetErr(ENOEXEC, "Error:: delta file data is broken!\n"); |
sync_SetErr(ENOEXEC, "Error:: delta file data is broken!\n"); |
| ret = -1; |
ret = -1; |
|
Line 354 syncDelta(const char *csInput, const char *csSig, cons
|
Line 365 syncDelta(const char *csInput, const char *csSig, cons
|
| |
|
| continue; |
continue; |
| } |
} |
| // match 1st block after difference and copy signature from B | /* match 1st block after difference and copy signature from B */ |
| memcpy(&sc, find, sizeof sc); |
memcpy(&sc, find, sizeof sc); |
| sc.sc_magic = SIGSYNC_MAGIC; |
sc.sc_magic = SIGSYNC_MAGIC; |
| sc.sc_len = blk; |
sc.sc_len = blk; |
| |
|
| // write signature from chunk B | /* write signature from chunk B */ |
| blk = write(f, &sc, sizeof sc); |
blk = write(f, &sc, sizeof sc); |
| if (-1 == blk) { |
if (-1 == blk) { |
| LOGERR; |
LOGERR; |
| break; |
break; |
| } |
} |
| // if write chunk len is differnt from requested len | /* if write chunk len is differnt from requested len */ |
| if (blk != sizeof sc) { |
if (blk != sizeof sc) { |
| sync_SetErr(ENOEXEC, "Error:: delta file end signature is broken!\n"); |
sync_SetErr(ENOEXEC, "Error:: delta file end signature is broken!\n"); |
| ret = -1; |
ret = -1; |
|
Line 375 syncDelta(const char *csInput, const char *csSig, cons
|
Line 386 syncDelta(const char *csInput, const char *csSig, cons
|
| blk ^= blk; |
blk ^= blk; |
| } |
} |
| |
|
| // check for error or empty delta file | /* check for error or empty delta file */ |
| if (ret == -1) |
if (ret == -1) |
| goto end; |
goto end; |
| fsync(f); |
fsync(f); |
|
Line 385 syncDelta(const char *csInput, const char *csSig, cons
|
Line 396 syncDelta(const char *csInput, const char *csSig, cons
|
| goto end; |
goto end; |
| } |
} |
| |
|
| // No deferences, not needed delta.patch !!! | /* No deferences, not needed delta.patch !!! */ |
| if (!sb_f.st_size) { |
if (!sb_f.st_size) { |
| ret = 1; |
ret = 1; |
| goto end; |
goto end; |
|
Line 393 syncDelta(const char *csInput, const char *csSig, cons
|
Line 404 syncDelta(const char *csInput, const char *csSig, cons
|
| |
|
| /* Delta patch is READY */ |
/* Delta patch is READY */ |
| |
|
| // build compressed delta file | /* build compressed delta file */ |
| if (compress & 1) { |
if (compress & 1) { |
| outf = sync_Open(csDelta, O_WRONLY, 0); |
outf = sync_Open(csDelta, O_WRONLY, 0); |
| if (outf == -1) { |
if (outf == -1) { |
|
Line 413 end:
|
Line 424 end:
|
| sync_Close(f); |
sync_Close(f); |
| if (compress & 1) |
if (compress & 1) |
| unlink(szTemp); |
unlink(szTemp); |
| |
|
| sync_Close(inf); |
sync_Close(inf); |
| free(tag_table); |
free(tag_table); |
| munmap(chunks, sb.st_size); |
munmap(chunks, sb.st_size); |
|
Line 421 end:
|
Line 431 end:
|
| } |
} |
| |
|
| /* |
/* |
| * syncPatch() Apply delta patch file to target | * syncPatch() - Apply delta patch file to target |
| | * |
| * @csInput = Input target file name for patch |
* @csInput = Input target file name for patch |
| * @csDelta = Input Delta patch file name |
* @csDelta = Input Delta patch file name |
| * @csPatch = After applied patch create new alternate target file, if != NULL |
* @csPatch = After applied patch create new alternate target file, if != NULL |
|
Line 519 syncPatch(const char *csInput, const char *csDelta, co
|
Line 530 syncPatch(const char *csInput, const char *csDelta, co
|
| |
|
| ret = readlen = 0; |
ret = readlen = 0; |
| buffer = NULL; |
buffer = NULL; |
| for (i = 0, off = 0ll, suffix = NULL, piece = pieces; piece->pfx; i++, off += readlen) { | for (i = 0, off = 0ll, suffix = NULL, piece = pieces; piece->pfx; |
| | i++, off += readlen) { |
| | #if 0 |
| | printf("i=%d off=%llu sfx=%p piece=%p\n", i, off, suffix, piece); |
| | #endif |
| |
|
| // printf("i=%d off=%llu sfx=%p piece=%p\n", i, off, suffix, piece); | /* if input offset is less then input file size */ |
| |
| // if input offset is less then input file size | |
| if (off < sb.st_size) { |
if (off < sb.st_size) { |
| readlen = read(inf, buf, CHUNK_MAX); |
readlen = read(inf, buf, CHUNK_MAX); |
| if (readlen == -1) { |
if (readlen == -1) { |
|
Line 531 syncPatch(const char *csInput, const char *csDelta, co
|
Line 544 syncPatch(const char *csInput, const char *csDelta, co
|
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
| // if suffix find, check for correct patch | /* if suffix find, check for correct patch */ |
| if (suffix) { |
if (suffix) { |
| if (suffix->sc_len != readlen || suffix->sc_off != off) { | if (suffix->sc_len != readlen || |
| sync_SetErr(ENOEXEC, "Error:: patch file is broken! (wrong suffix pos)\n"); | suffix->sc_off != off) { |
| | sync_SetErr(ENOEXEC, "Error:: patch file is broken! " |
| | "(wrong suffix pos)\n"); |
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
| sync_mksig(i, off, buf, readlen, &sc); |
sync_mksig(i, off, buf, readlen, &sc); |
| if (sc.sc_roll != suffix->sc_roll || |
if (sc.sc_roll != suffix->sc_roll || |
| memcmp(sc.sc_cksum, suffix->sc_cksum, MD5_DIGEST_LENGTH)) { | memcmp(sc.sc_cksum, suffix->sc_cksum, |
| sync_SetErr(ENOEXEC, "Error:: patch file is broken! (wrong suffix crc)\n"); | MD5_DIGEST_LENGTH)) { |
| | sync_SetErr(ENOEXEC, "Error:: patch file is broken! " |
| | "(wrong suffix crc)\n"); |
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
|
Line 552 syncPatch(const char *csInput, const char *csDelta, co
|
Line 569 syncPatch(const char *csInput, const char *csDelta, co
|
| buffer = buf; |
buffer = buf; |
| } |
} |
| |
|
| // printf("i=%d off=%llu sfx=%p piece=%p pfx=%p pfx_off=%llu\n", i, off, suffix, piece, | #if 0 |
| // piece ? piece->pfx : 0l, piece->pfx ? piece->pfx->sc_off : 0l); | printf("i=%d off=%llu sfx=%p piece=%p pfx=%p pfx_off=%llu\n", i, off, |
| | suffix, piece, piece ? piece->pfx : 0l, |
| | piece->pfx ? piece->pfx->sc_off : 0l); |
| | #endif |
| |
|
| // if delta chunk match! | /* if delta chunk match! */ |
| if (piece->pfx && piece->pfx->sc_off == off) { |
if (piece->pfx && piece->pfx->sc_off == off) { |
| if (!piece->buf) { |
if (!piece->buf) { |
| sync_SetErr(ENOEXEC, "Error:: patch file is broken! (missing data)\n"); | sync_SetErr(ENOEXEC, "Error:: patch file is broken! " |
| | "(missing data)\n"); |
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
|
Line 570 syncPatch(const char *csInput, const char *csDelta, co
|
Line 591 syncPatch(const char *csInput, const char *csDelta, co
|
| piece++; |
piece++; |
| |
|
| if (suffix && off >= sb.st_size) { |
if (suffix && off >= sb.st_size) { |
| sync_SetErr(ENOEXEC, "Error:: patch file is broken! (after eof find suffix)\n"); | sync_SetErr(ENOEXEC, "Error:: patch file is broken! " |
| | "(after eof find suffix)\n"); |
| ret = -1; |
ret = -1; |
| break; |
break; |
| } |
} |
| } else | } else if (off >= sb.st_size) { |
| if (off >= sb.st_size) { | if (piece->pfx) { |
| if (piece->pfx) { | sync_SetErr(ENOEXEC, "Error:: patch file is broken! " |
| sync_SetErr(ENOEXEC, "Error:: patch file is broken! (after eof find prefix)\n"); | "(after eof find prefix)\n"); |
| ret = -1; | ret = -1; |
| } | |
| |
| break; | |
| } |
} |
| |
|
| |
break; |
| |
} |
| |
|
| ret = write(outf, buffer, readlen); |
ret = write(outf, buffer, readlen); |
| if (ret == -1 || ret != readlen) { |
if (ret == -1 || ret != readlen) { |