Esempio n. 1
0
/* 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;
}
Esempio n. 2
0
/* 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;
}