/* zsync_receive_data_uncompressed(self, buf[], offset, buflen) * Adds the data in buf (buflen bytes) to this file at the given offset. * Returns 0 unless there's an error (e.g. the submitted data doesn't match the * expected checksum for the corresponding blocks) */ static int zsync_receive_data_uncompressed(struct zsync_receiver *zr, const unsigned char *buf, off_t offset, size_t len) { int ret = 0; size_t blocksize = zr->zs->blocksize; if (0 != (offset % blocksize)) { size_t x = len; if (x > blocksize - (offset % blocksize)) x = blocksize - (offset % blocksize); if (zr->outoffset == offset) { /* Half-way through a block, so let's try and complete it */ if (len) memcpy(zr->outbuf + offset % blocksize, buf, x); else { // Pad with 0s to length. memset(zr->outbuf + offset % blocksize, 0, len = x = blocksize - (offset % blocksize)); } if ((x + offset) % blocksize == 0) if (zsync_submit_data(zr->zs, zr->outbuf, zr->outoffset + x - blocksize, 1)) ret = 1; } buf += x; len -= x; offset += x; } /* Now we are block-aligned */ if (len >= blocksize) { int w = len / blocksize; if (zsync_submit_data(zr->zs, buf, offset, w)) ret = 1; else ret = 0; w *= blocksize; buf += w; len -= w; offset += w; } /* Store incomplete block */ if (len) { memcpy(zr->outbuf, buf, len); // try pad data with zero and submit memset(zr->outbuf + len, 0, blocksize-len); if (zsync_submit_data(zr->zs, zr->outbuf, offset, 1)) offset += len; /* not needed: buf += len; len -= len; */ else offset += blocksize; } zr->outoffset = offset; return ret; }
/* zsync_receive_data_compressed(self, buf[], offset, buflen) * Passes data received corresponding to the compressed version of this file at * the given offset; data in buf, buflen bytes. * Returns 0 unless there's an error (e.g. the submitted data doesn't match the * expected checksum for the corresponding blocks) */ static int zsync_receive_data_compressed(struct zsync_receiver *zr, const unsigned char *buf, off_t offset, size_t len) { int ret = 0; int eoz = 0; size_t blocksize = zr->zs->blocksize; if (!len) return 0; /* Now set up for the downloaded block */ zr->strm.next_in = buf; zr->strm.avail_in = len; if (zr->strm.total_in == 0 || offset != (off_t)zr->strm.total_in) { zsync_configure_zstream_for_zdata(zr->zs, &(zr->strm), offset, &(zr->outoffset)); /* On first iteration, we might be reading an incomplete block from zsync's point of view. Limit avail_out so we can stop after doing that and realign with the buffer. */ zr->strm.avail_out = blocksize - ((size_t)zr->outoffset % blocksize); zr->strm.next_out = zr->outbuf; } else { if (zr->outoffset == -1) { fprintf(stderr, "data didn't align with block boundary in compressed stream\n"); return 1; } zr->strm.next_in = buf; zr->strm.avail_in = len; } while (zr->strm.avail_in && !eoz) { int rc; /* Read in up to the next block (in the libzsync sense on the output stream) boundary */ rc = inflate(&(zr->strm), Z_SYNC_FLUSH); switch (rc) { case Z_STREAM_END: eoz = 1; case Z_BUF_ERROR: case Z_OK: if (zr->strm.avail_out == 0 || eoz) { /* If this was at the start of a block, try submitting it */ if (!((size_t)zr->outoffset % blocksize)) { int rc; if (zr->strm.avail_out) memset(zr->strm.next_out, 0, zr->strm.avail_out); rc = zsync_submit_data(zr->zs, zr->outbuf, zr->outoffset, 1); if (!zr->strm.avail_out) ret |= rc; zr->outoffset += blocksize; } else { /* We were reading a block fragment; update outoffset, and we are now block-aligned. */ zr->outoffset += (zr->strm.next_out - zr->outbuf); } zr->strm.avail_out = blocksize; zr->strm.next_out = zr->outbuf; } break; default: fprintf(stderr, "zlib error: %s (%d)\n", zr->strm.msg, rc); eoz = 1; ret = -1; break; } } return ret; }