Esempio n. 1
0
int git_zstream_deflatebuf(git_buf *out, const void *in, size_t in_len)
{
	git_zstream zs = GIT_ZSTREAM_INIT;
	int error = 0;

	if ((error = git_zstream_init(&zs)) < 0)
		return error;

	if ((error = git_zstream_set_input(&zs, in, in_len)) < 0)
		goto done;

	while (!git_zstream_done(&zs)) {
		size_t step = git_zstream_suggest_output_len(&zs), written;

		if ((error = git_buf_grow(out, out->size + step)) < 0)
			goto done;

		written = out->asize - out->size;

		if ((error = git_zstream_get_output(
				out->ptr + out->size, &written, &zs)) < 0)
			goto done;

		out->size += written;
	}

	/* NULL terminate for consistency if possible */
	if (out->size < out->asize)
		out->ptr[out->size] = '\0';

done:
	git_zstream_free(&zs);
	return error;
}
Esempio n. 2
0
static void loose_backend__readstream_free(git_odb_stream *_stream)
{
	loose_readstream *stream = (loose_readstream *)_stream;

	git_futils_mmap_free(&stream->map);
	git_zstream_free(&stream->zstream);
	git__free(stream);
}
Esempio n. 3
0
static int read_header_loose_standard(
	git_rawobj *out, const unsigned char *data, size_t len)
{
	git_zstream zs = GIT_ZSTREAM_INIT;
	obj_hdr hdr;
	unsigned char inflated[MAX_HEADER_LEN];
	size_t header_len, inflated_len = sizeof(inflated);
	int error;

	if ((error = git_zstream_init(&zs, GIT_ZSTREAM_INFLATE)) < 0 ||
		(error = git_zstream_set_input(&zs, data, len)) < 0 ||
		(error = git_zstream_get_output_chunk(inflated, &inflated_len, &zs)) < 0 ||
		(error = parse_header(&hdr, &header_len, inflated, inflated_len)) < 0)
		goto done;

	out->len = hdr.size;
	out->type = hdr.type;

done:
	git_zstream_free(&zs);
	return error;
}
Esempio n. 4
0
static int loose_backend__readstream(
	git_odb_stream **stream_out,
	size_t *len_out,
	git_otype *type_out,
	git_odb_backend *_backend,
	const git_oid *oid)
{
	loose_backend *backend;
	loose_readstream *stream = NULL;
	git_hash_ctx *hash_ctx = NULL;
	git_buf object_path = GIT_BUF_INIT;
	obj_hdr hdr;
	int error = 0;

	assert(stream_out && len_out && type_out && _backend && oid);

	backend = (loose_backend *)_backend;
	*stream_out = NULL;
	*len_out = 0;
	*type_out = GIT_OBJ_BAD;

	if (locate_object(&object_path, backend, oid) < 0) {
		error = git_odb__error_notfound("no matching loose object",
			oid, GIT_OID_HEXSZ);
		goto done;
	}

	stream = git__calloc(1, sizeof(loose_readstream));
	GITERR_CHECK_ALLOC(stream);

	hash_ctx = git__malloc(sizeof(git_hash_ctx));
	GITERR_CHECK_ALLOC(hash_ctx);

	if ((error = git_hash_ctx_init(hash_ctx)) < 0 ||
		(error = git_futils_mmap_ro_file(&stream->map, object_path.ptr)) < 0 ||
		(error = git_zstream_init(&stream->zstream, GIT_ZSTREAM_INFLATE)) < 0)
		goto done;

	/* check for a packlike loose object */
	if (!is_zlib_compressed_data(stream->map.data, stream->map.len))
		error = loose_backend__readstream_packlike(&hdr, stream);
	else
		error = loose_backend__readstream_standard(&hdr, stream);

	if (error < 0)
		goto done;

	stream->stream.backend = _backend;
	stream->stream.hash_ctx = hash_ctx;
	stream->stream.read = &loose_backend__readstream_read;
	stream->stream.free = &loose_backend__readstream_free;

	*stream_out = (git_odb_stream *)stream;
	*len_out = hdr.size;
	*type_out = hdr.type;

done:
	if (error < 0) {
		git_futils_mmap_free(&stream->map);
		git_zstream_free(&stream->zstream);
		git_hash_ctx_cleanup(hash_ctx);
		git__free(hash_ctx);
		git__free(stream);
	}

	git_buf_dispose(&object_path);
	return error;
}
Esempio n. 5
0
static int read_loose_standard(git_rawobj *out, git_buf *obj)
{
	git_zstream zstream = GIT_ZSTREAM_INIT;
	unsigned char head[MAX_HEADER_LEN], *body = NULL;
	size_t decompressed, head_len, body_len, alloc_size;
	obj_hdr hdr;
	int error;

	if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0 ||
		(error = git_zstream_set_input(&zstream, git_buf_cstr(obj), git_buf_len(obj))) < 0)
		goto done;

	decompressed = sizeof(head);

	/*
	 * inflate the initial part of the compressed buffer in order to
	 * parse the header; read the largest header possible, then push the
	 * remainder into the body buffer.
	 */
	if ((error = git_zstream_get_output(head, &decompressed, &zstream)) < 0 ||
		(error = parse_header(&hdr, &head_len, head, decompressed)) < 0)
		goto done;

	if (!git_object_typeisloose(hdr.type)) {
		giterr_set(GITERR_ODB, "failed to inflate disk object");
		error = -1;
		goto done;
	}

	/*
	 * allocate a buffer and inflate the object data into it
	 * (including the initial sequence in the head buffer).
	 */
	if (GIT_ADD_SIZET_OVERFLOW(&alloc_size, hdr.size, 1) ||
		(body = git__malloc(alloc_size)) == NULL) {
		error = -1;
		goto done;
	}

	assert(decompressed >= head_len);
	body_len = decompressed - head_len;

	if (body_len)
		memcpy(body, head + head_len, body_len);

	decompressed = hdr.size - body_len;
	if ((error = git_zstream_get_output(body + body_len, &decompressed, &zstream)) < 0)
		goto done;

	if (!git_zstream_done(&zstream)) {
		giterr_set(GITERR_ZLIB, "failed to finish zlib inflation: stream aborted prematurely");
		error = -1;
		goto done;
	}

	body[hdr.size] = '\0';

	out->data = body;
	out->len = hdr.size;
	out->type = hdr.type;

done:
	if (error < 0)
		git__free(body);

	git_zstream_free(&zstream);
	return error;
}