Example #1
0
static zip_int64_t
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct crc_context *ctx;
    zip_int64_t n;

    ctx = (struct crc_context *)_ctx;

    switch (cmd) {
        case ZIP_SOURCE_OPEN:
            ctx->position = 0;
            return 0;
            
        case ZIP_SOURCE_READ:
            if ((n = zip_source_read(src, data, len)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }
            
            if (n == 0) {
                if (ctx->crc_position == ctx->position) {
                    ctx->crc_complete = 1;
                    ctx->size = ctx->position;

                    if (ctx->validate) {
                        struct zip_stat st;
                    
                        if (zip_source_stat(src, &st) < 0) {
                            _zip_error_set_from_source(&ctx->error, src);
                            return -1;
                        }
                    
                        if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
                            zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
                            return -1;
                        }
                        if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
                            zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
                            return -1;
                        }
                    }
                }
            }
            else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
		zip_uint64_t i, nn;

		for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
		    nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);

		    ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
                    ctx->crc_position += nn;
		}
            }
            ctx->position += (zip_uint64_t)n;
            return n;

        case ZIP_SOURCE_CLOSE:
            return 0;

        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;

	    st = (zip_stat_t *)data;

	    if (ctx->crc_complete) {
		/* TODO: Set comp_size, comp_method, encryption_method?
		        After all, this only works for uncompressed data. */
		st->size = ctx->size;
		st->crc = ctx->crc;
		st->comp_size = ctx->size;
		st->comp_method = ZIP_CM_STORE;
		st->encryption_method = ZIP_EM_NONE;
		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
	    }
            return 0;
        }
            
        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);

        case ZIP_SOURCE_FREE:
            free(ctx);
            return 0;
            
        case ZIP_SOURCE_SUPPORTS:
        {
            zip_int64_t mask = zip_source_supports(src);

            if (mask < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
        }

        case ZIP_SOURCE_SEEK:
        {
            zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
            zip_int64_t new_position;

            if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }

            ctx->position = (zip_uint64_t)new_position;

            return 0;
        }

        case ZIP_SOURCE_TELL:
            return (zip_int64_t)ctx->position;
            
        default:
            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}
Example #2
0
static zip_int64_t
crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source_cmd_t cmd)
{
    struct crc_context *ctx;
    zip_int64_t n;

    ctx = (struct crc_context *)_ctx;

    switch (cmd) {
        case ZIP_SOURCE_OPEN:
            ctx->eof = 0;
            ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
            ctx->size = 0;
            
            return 0;
            
        case ZIP_SOURCE_READ:
            if (ctx->eof || len == 0)
                return 0;
            
            if ((n=zip_source_read(src, data, len)) < 0) {
                _zip_error_set_from_source(&ctx->error, src);
                return -1;
            }
            
            if (n == 0) {
                ctx->eof = 1;
                if (ctx->validate) {
                    struct zip_stat st;
                    
                    if (zip_source_stat(src, &st) < 0) {
                        _zip_error_set_from_source(&ctx->error, src);
                        return -1;
                    }
                    
                    if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
                        zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
                        return -1;
                    }
                    if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
                        zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
                        return -1;
                    }
                }
            }
            else {
		zip_uint64_t i, nn;

		for (i=0; i < (zip_uint64_t)n; i += nn) {
		    nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);

		    ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
		}
                ctx->size += (zip_uint64_t)n;
            }
            return n;

        case ZIP_SOURCE_CLOSE:
            return 0;

        case ZIP_SOURCE_STAT:
        {
            zip_stat_t *st;

	    st = (zip_stat_t *)data;

	    if (ctx->eof) {
		/* TODO: Set comp_size, comp_method, encryption_method?
		        After all, this only works for uncompressed data. */
		st->size = ctx->size;
		st->crc = ctx->crc;
		st->comp_size = ctx->size;
		st->comp_method = ZIP_CM_STORE;
		st->encryption_method = ZIP_EM_NONE;
		st->valid |= ZIP_STAT_SIZE|ZIP_STAT_CRC|ZIP_STAT_COMP_SIZE|ZIP_STAT_COMP_METHOD|ZIP_STAT_ENCRYPTION_METHOD;;
	    }
            return 0;
        }
            
        case ZIP_SOURCE_ERROR:
            return zip_error_to_data(&ctx->error, data, len);

        case ZIP_SOURCE_FREE:
            free(ctx);
            return 0;
            
        case ZIP_SOURCE_SUPPORTS:
            return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
            
        default:
            zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
            return -1;
    }
}