Skip to content

Commit d8f6fee

Browse files
committed
pack: refactor unpacking of raw objects to use git_zstream
While we do have a zstream abstraction that encapsulates all the calls to zlib as well as its error handling, we do not use it in our pack file code. Refactor it to make the code a lot easier to understand.
1 parent ba64f50 commit d8f6fee

File tree

3 files changed

+44
-41
lines changed

3 files changed

+44
-41
lines changed

src/pack.c

Lines changed: 38 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@
77

88
#include "pack.h"
99

10-
#include "odb.h"
1110
#include "delta.h"
12-
#include "sha1_lookup.h"
13-
#include "mwindow.h"
1411
#include "futils.h"
12+
#include "mwindow.h"
13+
#include "odb.h"
1514
#include "oid.h"
15+
#include "sha1_lookup.h"
16+
#include "zstream.h"
1617

1718
#include <zlib.h>
1819

@@ -845,64 +846,60 @@ void git_packfile_stream_dispose(git_packfile_stream *obj)
845846
static int packfile_unpack_compressed(
846847
git_rawobj *obj,
847848
struct git_pack_file *p,
848-
git_mwindow **w_curs,
849-
off64_t *curpos,
849+
git_mwindow **mwindow,
850+
off64_t *position,
850851
size_t size,
851852
git_object_t type)
852853
{
853-
size_t buf_size;
854-
int st;
855-
z_stream stream;
856-
unsigned char *buffer, *in;
857-
858-
GIT_ERROR_CHECK_ALLOC_ADD(&buf_size, size, 1);
859-
buffer = git__calloc(1, buf_size);
860-
GIT_ERROR_CHECK_ALLOC(buffer);
854+
git_zstream zstream = GIT_ZSTREAM_INIT;
855+
size_t buffer_len, total = 0;
856+
char *data = NULL;
857+
int error;
861858

862-
memset(&stream, 0, sizeof(stream));
863-
stream.next_out = buffer;
864-
stream.avail_out = (uInt)buf_size;
865-
stream.zalloc = use_git_alloc;
866-
stream.zfree = use_git_free;
859+
GIT_ERROR_CHECK_ALLOC_ADD(&buffer_len, size, 1);
860+
data = git__calloc(1, buffer_len);
861+
GIT_ERROR_CHECK_ALLOC(data);
867862

868-
st = inflateInit(&stream);
869-
if (st != Z_OK) {
870-
git__free(buffer);
863+
if ((error = git_zstream_init(&zstream, GIT_ZSTREAM_INFLATE)) < 0) {
871864
git_error_set(GIT_ERROR_ZLIB, "failed to init zlib stream on unpack");
872-
873-
return -1;
865+
goto out;
874866
}
875867

876868
do {
877-
in = pack_window_open(p, w_curs, *curpos, &stream.avail_in);
878-
stream.next_in = in;
879-
st = inflate(&stream, Z_FINISH);
880-
git_mwindow_close(w_curs);
869+
size_t bytes = buffer_len - total;
870+
unsigned int window_len;
871+
unsigned char *in;
881872

882-
if (!stream.avail_out)
883-
break; /* the payload is larger than it should be */
873+
in = pack_window_open(p, mwindow, *position, &window_len);
884874

885-
if (st == Z_BUF_ERROR && in == NULL) {
886-
inflateEnd(&stream);
887-
git__free(buffer);
888-
return GIT_EBUFS;
875+
if ((error = git_zstream_set_input(&zstream, in, window_len)) < 0 ||
876+
(error = git_zstream_get_output_chunk(data + total, &bytes, &zstream)) < 0) {
877+
git_mwindow_close(mwindow);
878+
goto out;
889879
}
890880

891-
*curpos += stream.next_in - in;
892-
} while (st == Z_OK || st == Z_BUF_ERROR);
881+
git_mwindow_close(mwindow);
893882

894-
inflateEnd(&stream);
883+
*position += window_len - zstream.in_len;
884+
total += bytes;
885+
} while (total < size);
895886

896-
if ((st != Z_STREAM_END) || stream.total_out != size) {
897-
git__free(buffer);
887+
if (total != size || !git_zstream_eos(&zstream)) {
898888
git_error_set(GIT_ERROR_ZLIB, "error inflating zlib stream");
899-
return -1;
889+
error = -1;
890+
goto out;
900891
}
901892

902893
obj->type = type;
903894
obj->len = size;
904-
obj->data = buffer;
905-
return 0;
895+
obj->data = data;
896+
897+
out:
898+
git_zstream_free(&zstream);
899+
if (error)
900+
git__free(data);
901+
902+
return error;
906903
}
907904

908905
/*

src/zstream.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,11 @@ bool git_zstream_done(git_zstream *zstream)
7777
return (!zstream->in_len && zstream->zerr == Z_STREAM_END);
7878
}
7979

80+
bool git_zstream_eos(git_zstream *zstream)
81+
{
82+
return zstream->zerr == Z_STREAM_END;
83+
}
84+
8085
size_t git_zstream_suggest_output_len(git_zstream *zstream)
8186
{
8287
if (zstream->in_len > ZSTREAM_BUFFER_SIZE)

src/zstream.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ int git_zstream_get_output_chunk(
4444
int git_zstream_get_output(void *out, size_t *out_len, git_zstream *zstream);
4545

4646
bool git_zstream_done(git_zstream *zstream);
47+
bool git_zstream_eos(git_zstream *zstream);
4748

4849
void git_zstream_reset(git_zstream *zstream);
4950

0 commit comments

Comments
 (0)