Esempio n. 1
0
ZIP_EXTERN int
zip_source_open(zip_source_t *src) {
    if (src->source_closed) {
	return -1;
    }
    if (src->write_state == ZIP_SOURCE_WRITE_REMOVED) {
	zip_error_set(&src->error, ZIP_ER_DELETED, 0);
	return -1;
    }

    if (ZIP_SOURCE_IS_OPEN_READING(src)) {
	if ((zip_source_supports(src) & ZIP_SOURCE_MAKE_COMMAND_BITMASK(ZIP_SOURCE_SEEK)) == 0) {
	    zip_error_set(&src->error, ZIP_ER_INUSE, 0);
	    return -1;
	}
    }
    else {
	if (ZIP_SOURCE_IS_LAYERED(src)) {
	    if (zip_source_open(src->src) < 0) {
		_zip_error_set_from_source(&src->error, src->src);
		return -1;
	    }
	}

	if (_zip_source_call(src, NULL, 0, ZIP_SOURCE_OPEN) < 0) {
	    if (ZIP_SOURCE_IS_LAYERED(src)) {
		zip_source_close(src->src);
	    }
	    return -1;
	}
    }

    src->eof = false;
    src->had_read_error = false;
    _zip_error_clear(&src->error);
    src->open_count++;

    return 0;
}
Esempio n. 2
0
ZIP_EXTERN zip_t *
zip_open_from_source(zip_source_t *src, int _flags, zip_error_t *error)
{
    static zip_int64_t needed_support_read = -1;
    static zip_int64_t needed_support_write = -1;

    unsigned int flags;
    zip_int64_t supported;
    exists_t exists;

    if (_flags < 0 || src == NULL) {
	zip_error_set(error, ZIP_ER_INVAL, 0);
        return NULL;
    }
    flags = (unsigned int)_flags;

    supported = zip_source_supports(src);
    if (needed_support_read == -1) {
        needed_support_read = zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_SEEK, ZIP_SOURCE_TELL, ZIP_SOURCE_STAT, -1);
        needed_support_write = 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);
    }
    if ((supported & needed_support_read) != needed_support_read) {
        zip_error_set(error, ZIP_ER_OPNOTSUPP, 0);
        return NULL;
    }
    if ((supported & needed_support_write) != needed_support_write) {
        flags |= ZIP_RDONLY;
    }

    if ((flags & (ZIP_RDONLY|ZIP_TRUNCATE)) == (ZIP_RDONLY|ZIP_TRUNCATE)) {
	zip_error_set(error, ZIP_ER_RDONLY, 0);
	return NULL;
    }

    exists = _zip_file_exists(src, error);
    switch (exists) {
    case EXISTS_ERROR:
	return NULL;

    case EXISTS_NOT:
	if ((flags & ZIP_CREATE) == 0) {
	    zip_error_set(error, ZIP_ER_NOENT, 0);
	    return NULL;
	}
	return _zip_allocate_new(src, flags, error);

    default: {
	zip_t *za;
	if (flags & ZIP_EXCL) {
	    zip_error_set(error, ZIP_ER_EXISTS, 0);
	    return NULL;
	}
	if (zip_source_open(src) < 0) {
	    _zip_error_set_from_source(error, src);
	    return NULL;
	}

	if (flags & ZIP_TRUNCATE) {
	    za = _zip_allocate_new(src, flags, error);
	}
	else {
	    /* ZIP_CREATE gets ignored if file exists and not ZIP_EXCL, just like open() */
	    za = _zip_open(src, flags, error);
	}

	if (za == NULL) {
	    zip_source_close(src);
	    return NULL;
	}
	return za;
    }
    }
}
Esempio n. 3
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_int64_t new_position;
            zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);

	    if (args == NULL) {
		return -1;
	    }
            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;
    }
}