13 #include <sys/types.h> 23 #include <zypp/base/Logger.h> 24 #include <zypp/base/String.h> 31 MediaBlockList::MediaBlockList(off_t size)
42 MediaBlockList::addBlock(off_t off,
size_t size)
46 return blocks.size() - 1;
50 MediaBlockList::setFileChecksum(std::string ctype,
int cl,
unsigned char *c)
56 memcpy(&fsum[0], c, cl);
59 std::string MediaBlockList::fileChecksumType()
const 70 MediaBlockList::createFileDigest(
Digest &digest)
const 72 return digest.
create(fsumtype);
76 MediaBlockList::verifyFileDigest(
Digest &digest)
const 78 if (!haveFileChecksum())
81 if (dig.empty() || dig.size() < fsum.size())
83 return memcmp(&dig[0], &fsum[0], fsum.size()) ?
false :
true;
87 MediaBlockList::setChecksum(
size_t blkno, std::string cstype,
int csl,
unsigned char *cs,
size_t cspad)
99 if (csl != chksumlen || cstype != chksumtype || cspad != chksumpad || blkno != chksums.size() / chksumlen)
101 chksums.resize(chksums.size() + csl);
102 memcpy(&chksums[csl * blkno], cs, csl);
106 MediaBlockList::setRsum(
size_t blkno,
int rsl,
unsigned int rs,
size_t rspad)
117 if (rsl != rsumlen || rspad != rsumpad || blkno != rsums.size())
123 MediaBlockList::createDigest(
Digest &digest)
const 125 return digest.
create(chksumtype);
129 MediaBlockList::verifyDigest(
size_t blkno,
Digest &digest)
const 131 if (!haveChecksum(blkno))
133 size_t size = blocks[blkno].size;
136 if (chksumpad > size)
138 char pad[chksumpad - size];
139 memset(pad, 0, chksumpad - size);
140 digest.
update(pad, chksumpad - size);
143 if (dig.empty() || dig.size() < size_t(chksumlen))
145 return memcmp(&dig[0], &chksums[chksumlen * blkno], chksumlen) ? false :
true;
149 MediaBlockList::updateRsum(
unsigned int rs,
const char* bytes,
size_t len)
const 154 s = (rs >> 16) & 65535;
156 for (; len > 0 ; len--)
158 unsigned short c = (
unsigned char)*bytes++;
162 return (s & 65535) << 16 | (m & 65535);
166 MediaBlockList::verifyRsum(
size_t blkno,
unsigned int rs)
const 168 if (!haveRsum(blkno))
170 size_t size = blocks[blkno].size;
176 s = (rs >> 16) & 65535;
178 m += s * (rsumpad - size);
179 rs = (s & 65535) << 16 | (m & 65535);
192 return rs == rsums[blkno];
196 MediaBlockList::checkRsum(
size_t blkno,
const unsigned char *buf,
size_t bufl)
const 198 if (blkno >= blocks.size() || bufl < blocks[blkno].size)
200 unsigned int rs = updateRsum(0, (
const char *)buf, blocks[blkno].size);
201 return verifyRsum(blkno, rs);
205 MediaBlockList::checkChecksum(
size_t blkno,
const unsigned char *buf,
size_t bufl)
const 207 if (blkno >= blocks.size() || bufl < blocks[blkno].size)
210 if (!createDigest(dig))
212 dig.
update((
const char *)buf, blocks[blkno].size);
213 return verifyDigest(blkno, dig);
218 if ( !haveChecksum(blkno) )
222 memcpy( buf.data(), chksums.data()+(chksumlen * blkno), chksumlen );
226 std::string MediaBlockList::getChecksumType()
const 233 MediaBlockList::checkChecksumRotated(
size_t blkno,
const unsigned char *buf,
size_t bufl,
size_t start)
const 235 if (blkno >= blocks.size() || bufl < blocks[blkno].size)
240 if (!createDigest(dig))
242 size_t size = blocks[blkno].size;
243 size_t len = bufl - start > size ? size : bufl - start;
244 dig.
update((
const char *)buf + start, len);
246 dig.
update((
const char *)buf, size - len);
247 return verifyDigest(blkno, dig);
252 MediaBlockList::writeBlock(
size_t blkno, FILE *fp,
const unsigned char *buf,
size_t bufl,
size_t start, std::vector<bool> &found)
const 254 if (blkno >= blocks.size() || bufl < blocks[blkno].size)
256 off_t off = blocks[blkno].off;
257 size_t size = blocks[blkno].size;
258 if (fseeko(fp, off, SEEK_SET))
262 size_t len = bufl - start > size ? size : bufl - start;
263 if (fwrite(buf + start, len, 1, fp) != 1)
265 if (size > len && fwrite(buf, size - len, 1, fp) != 1)
268 found[blocks.size()] =
true;
272 fetchnext(FILE *fp,
unsigned char *bp,
size_t blksize,
size_t pushback,
unsigned char *pushbackp)
280 memmove(bp, pushbackp, pushback);
299 MediaBlockList::reuseBlocks(FILE *wfp, std::string filename)
303 if (!chksumlen || (fp = fopen(filename.c_str(),
"r")) == 0)
305 size_t nblks = blocks.size();
306 std::vector<bool> found;
307 found.resize(nblks + 1);
308 if (rsumlen && !rsums.empty())
310 size_t blksize = blocks[0].size;
311 if (nblks == 1 && rsumpad && rsumpad > blksize)
314 unsigned int hm = rsums.size() * 2;
315 while (hm & (hm - 1))
320 unsigned int *ht =
new unsigned int[hm + 1];
321 memset(ht, 0, (hm + 1) *
sizeof(
unsigned int));
322 for (
unsigned int i = 0; i < rsums.size(); i++)
324 if (blocks[i].size != blksize && (i != nblks - 1 || rsumpad != blksize))
326 unsigned int r = rsums[i];
327 unsigned int h = r & hm;
334 unsigned char *buf =
new unsigned char[blksize];
335 unsigned char *buf2 =
new unsigned char[blksize];
337 unsigned char *pushbackp = 0;
339 if ((blksize & (blksize - 1)) == 0)
340 for (bshift = 0; size_t(1 << bshift) != blksize; bshift++)
344 memset(buf, 0, blksize);
347 int sql = nblks > 1 && chksumlen < 16 ? 2 : 1;
350 for (
size_t i = 0; i < blksize; i++)
376 b += a - (oc << bshift);
378 b += a - oc * blksize;
381 if (
size_t(i) != blksize - 1)
387 r = ((
unsigned int)b & 255);
388 else if (rsumlen == 2)
389 r = ((
unsigned int)b & 65535);
390 else if (rsumlen == 3)
391 r = ((
unsigned int)a & 255) << 16 | ((
unsigned int)b & 65535);
393 r = ((
unsigned int)a & 65535) << 16 | ((
unsigned int)b & 65535);
394 unsigned int h = r & hm;
396 for (; ht[h]; h = (h + hh++) & hm)
398 size_t blkno = ht[h] - 1;
399 if (rsums[blkno] != r)
405 if (eof || blkno + 1 >= nblks)
407 pushback =
fetchnext(fp, buf2, blksize, pushback, pushbackp);
411 if (!checkRsum(blkno + 1, buf2, blksize))
414 if (!checkChecksumRotated(blkno, buf, blksize, i + 1))
416 if (sql == 2 && !checkChecksum(blkno + 1, buf2, blksize))
418 writeBlock(blkno, wfp, buf, blksize, i + 1, found);
421 writeBlock(blkno + 1, wfp, buf2, blksize, 0, found);
428 pushback =
fetchnext(fp, buf2, blksize, pushback, pushbackp);
432 if (!checkRsum(blkno, buf2, blksize))
434 if (!checkChecksum(blkno, buf2, blksize))
436 writeBlock(blkno, wfp, buf2, blksize, 0, found);
440 memset(buf, 0, blksize);
451 else if (chksumlen >= 16)
456 unsigned char *buf =
new unsigned char[bufl];
457 for (
size_t blkno = 0; blkno < blocks.size(); ++blkno)
459 if (off > blocks[blkno].off)
461 size_t blksize = blocks[blkno].size;
466 buf =
new unsigned char[bufl];
468 size_t skip = blocks[blkno].off - off;
471 size_t l = skip > bufl ? bufl : skip;
472 if (fread(buf, l, 1, fp) != 1)
477 if (fread(buf, blksize, 1, fp) != 1)
479 if (checkChecksum(blkno, buf, blksize))
480 writeBlock(blkno, wfp, buf, blksize, 0, found);
487 std::vector<MediaBlock> nblocks;
488 std::vector<unsigned char> nchksums;
489 std::vector<unsigned int> nrsums;
491 for (
size_t blkno = 0; blkno < blocks.size(); ++blkno)
496 nblocks.push_back(blocks[blkno]);
497 if (chksumlen && (blkno + 1) * chksumlen <= chksums.size())
499 nchksums.resize(nblocks.size() * chksumlen);
500 memcpy(&nchksums[(nblocks.size() - 1) * chksumlen], &chksums[blkno * chksumlen], chksumlen);
502 if (rsumlen && (blkno + 1) <= rsums.size())
503 nrsums.push_back(rsums[blkno]);
517 if (filesize != off_t(-1))
519 long long size = filesize;
523 s =
"[ BlockList, filesize unknown\n";
525 s +=
" No block information\n";
530 for (i = 0; i < blocks.size(); ++i)
532 long long off=blocks[i].off;
533 long long size=blocks[i].size;
535 if (chksumlen && chksums.size() >= (i + 1) * chksumlen)
537 s +=
" " + chksumtype +
":";
538 for (j = 0; j < size_t(chksumlen); j++)
541 if (rsumlen && rsums.size() > i)
UByteArray digestVector()
get vector of unsigned char representation of the digest
std::string asString(const DefaultIntegral< Tp, TInitial > &obj)
Compute Message Digests (MD5, SHA1 etc)
std::string form(const char *format,...) __attribute__((format(printf
Printf style construction of std::string.
bool create(const std::string &name)
initialize creation of a new message digest
Easy-to use interface to the ZYPP dependency resolver.
bool update(const char *bytes, size_t len)
feed data into digest computation algorithm