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; }
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); }
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; }
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; }
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; }