compat: auto-detect if zlib has uncompress2()
We have a copy of uncompress2() implementation in compat/ so that we
can build with an older version of zlib that lack the function, and
the build procedure selects if it is used via the NO_UNCOMPRESS2
$(MAKE) variable. This is yet another "annoying" knob the porters
need to tweak on platforms that are not common enough to have the
default set in the config.mak.uname file.
Attempt to instead ask the system header <zlib.h> to decide if we
need the compatibility implementation. This is a deviation from the
way we have been handling the "compatiblity" features so far, and if
it can be done cleanly enough, it could work as a model for features
that need compatibility definition we discover in the future. With
that goal in mind, avoid expedient but ugly hacks, like shoving the
code that is conditionally compiled into an unrelated .c file, which
may not work in future cases---instead, take an approach that uses a
file that is independently compiled and stands on its own.
Compile and link compat/zlib-uncompress2.c file unconditionally, but
conditionally hide the implementation behind #if/#endif when zlib
version is 1.2.9 or newer, and unconditionally archive the resulting
object file in the libgit.a to be picked up by the linker.
There are a few things to note in the shape of the code base after
this change:
- We no longer use NO_UNCOMPRESS2 knob; if the system header
<zlib.h> claims a version that is more cent than the library
actually is, this would break, but it is easy to add it back when
we find such a system.
- The object file compat/zlib-uncompress2.o is always compiled and
archived in libgit.a, just like a few other compat/ object files
already are.
- The inclusion of <zlib.h> is done in <git-compat-util.h>; we used
to do so from <cache.h> which includes <git-compat-util.h> as the
first thing it does, so from the *.c codes, there is no practical
change.
- Until objects in libgit.a that is already used gains a reference
to the function, the reftable code will be the only one that
wants it, so libgit.a on the linker command line needs to appear
once more at the end to satisify the mutual dependency.
- Beat found a trick used by OpenSSL to avoid making the
conditionally-compiled object truly empty (apparently because
they had to deal with compilers that do not want to see an
effectively empty input file). Our compat/zlib-uncompress2.c
file borrows the same trick for portabilty.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Beat Bolli <dev+git@drbeat.li>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 years ago
|
|
|
#include "git-compat-util.h"
|
|
|
|
|
|
|
|
#if ZLIB_VERNUM < 0x1290
|
|
|
|
/* taken from zlib's uncompr.c
|
|
|
|
|
|
|
|
commit cacf7f1d4e3d44d871b605da3b647f07d718623f
|
|
|
|
Author: Mark Adler <madler@alumni.caltech.edu>
|
|
|
|
Date: Sun Jan 15 09:18:46 2017 -0800
|
|
|
|
|
|
|
|
zlib 1.2.11
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 1995-2003, 2010, 2014, 2016 Jean-loup Gailly, Mark Adler
|
|
|
|
* For conditions of distribution and use, see copyright notice in zlib.h
|
|
|
|
*/
|
|
|
|
|
|
|
|
/* clang-format off */
|
|
|
|
|
|
|
|
/* ===========================================================================
|
|
|
|
Decompresses the source buffer into the destination buffer. *sourceLen is
|
|
|
|
the byte length of the source buffer. Upon entry, *destLen is the total size
|
|
|
|
of the destination buffer, which must be large enough to hold the entire
|
|
|
|
uncompressed data. (The size of the uncompressed data must have been saved
|
|
|
|
previously by the compressor and transmitted to the decompressor by some
|
|
|
|
mechanism outside the scope of this compression library.) Upon exit,
|
|
|
|
*destLen is the size of the decompressed data and *sourceLen is the number
|
|
|
|
of source bytes consumed. Upon return, source + *sourceLen points to the
|
|
|
|
first unused input byte.
|
|
|
|
|
|
|
|
uncompress returns Z_OK if success, Z_MEM_ERROR if there was not enough
|
|
|
|
memory, Z_BUF_ERROR if there was not enough room in the output buffer, or
|
|
|
|
Z_DATA_ERROR if the input data was corrupted, including if the input data is
|
|
|
|
an incomplete zlib stream.
|
|
|
|
*/
|
|
|
|
int ZEXPORT uncompress2 (
|
|
|
|
Bytef *dest,
|
|
|
|
uLongf *destLen,
|
|
|
|
const Bytef *source,
|
|
|
|
uLong *sourceLen) {
|
|
|
|
z_stream stream;
|
|
|
|
int err;
|
|
|
|
const uInt max = (uInt)-1;
|
|
|
|
uLong len, left;
|
|
|
|
Byte buf[1]; /* for detection of incomplete stream when *destLen == 0 */
|
|
|
|
|
|
|
|
len = *sourceLen;
|
|
|
|
if (*destLen) {
|
|
|
|
left = *destLen;
|
|
|
|
*destLen = 0;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
left = 1;
|
|
|
|
dest = buf;
|
|
|
|
}
|
|
|
|
|
|
|
|
stream.next_in = (z_const Bytef *)source;
|
|
|
|
stream.avail_in = 0;
|
|
|
|
stream.zalloc = (alloc_func)0;
|
|
|
|
stream.zfree = (free_func)0;
|
|
|
|
stream.opaque = (voidpf)0;
|
|
|
|
|
|
|
|
err = inflateInit(&stream);
|
|
|
|
if (err != Z_OK) return err;
|
|
|
|
|
|
|
|
stream.next_out = dest;
|
|
|
|
stream.avail_out = 0;
|
|
|
|
|
|
|
|
do {
|
|
|
|
if (stream.avail_out == 0) {
|
|
|
|
stream.avail_out = left > (uLong)max ? max : (uInt)left;
|
|
|
|
left -= stream.avail_out;
|
|
|
|
}
|
|
|
|
if (stream.avail_in == 0) {
|
|
|
|
stream.avail_in = len > (uLong)max ? max : (uInt)len;
|
|
|
|
len -= stream.avail_in;
|
|
|
|
}
|
|
|
|
err = inflate(&stream, Z_NO_FLUSH);
|
|
|
|
} while (err == Z_OK);
|
|
|
|
|
|
|
|
*sourceLen -= len + stream.avail_in;
|
|
|
|
if (dest != buf)
|
|
|
|
*destLen = stream.total_out;
|
|
|
|
else if (stream.total_out && err == Z_BUF_ERROR)
|
|
|
|
left = 1;
|
|
|
|
|
|
|
|
inflateEnd(&stream);
|
|
|
|
return err == Z_STREAM_END ? Z_OK :
|
|
|
|
err == Z_NEED_DICT ? Z_DATA_ERROR :
|
|
|
|
err == Z_BUF_ERROR && left + stream.avail_out ? Z_DATA_ERROR :
|
|
|
|
err;
|
|
|
|
}
|
compat: auto-detect if zlib has uncompress2()
We have a copy of uncompress2() implementation in compat/ so that we
can build with an older version of zlib that lack the function, and
the build procedure selects if it is used via the NO_UNCOMPRESS2
$(MAKE) variable. This is yet another "annoying" knob the porters
need to tweak on platforms that are not common enough to have the
default set in the config.mak.uname file.
Attempt to instead ask the system header <zlib.h> to decide if we
need the compatibility implementation. This is a deviation from the
way we have been handling the "compatiblity" features so far, and if
it can be done cleanly enough, it could work as a model for features
that need compatibility definition we discover in the future. With
that goal in mind, avoid expedient but ugly hacks, like shoving the
code that is conditionally compiled into an unrelated .c file, which
may not work in future cases---instead, take an approach that uses a
file that is independently compiled and stands on its own.
Compile and link compat/zlib-uncompress2.c file unconditionally, but
conditionally hide the implementation behind #if/#endif when zlib
version is 1.2.9 or newer, and unconditionally archive the resulting
object file in the libgit.a to be picked up by the linker.
There are a few things to note in the shape of the code base after
this change:
- We no longer use NO_UNCOMPRESS2 knob; if the system header
<zlib.h> claims a version that is more cent than the library
actually is, this would break, but it is easy to add it back when
we find such a system.
- The object file compat/zlib-uncompress2.o is always compiled and
archived in libgit.a, just like a few other compat/ object files
already are.
- The inclusion of <zlib.h> is done in <git-compat-util.h>; we used
to do so from <cache.h> which includes <git-compat-util.h> as the
first thing it does, so from the *.c codes, there is no practical
change.
- Until objects in libgit.a that is already used gains a reference
to the function, the reftable code will be the only one that
wants it, so libgit.a on the linker command line needs to appear
once more at the end to satisify the mutual dependency.
- Beat found a trick used by OpenSSL to avoid making the
conditionally-compiled object truly empty (apparently because
they had to deal with compilers that do not want to see an
effectively empty input file). Our compat/zlib-uncompress2.c
file borrows the same trick for portabilty.
Signed-off-by: Ævar Arnfjörð Bjarmason <avarab@gmail.com>
Helped-by: Beat Bolli <dev+git@drbeat.li>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
3 years ago
|
|
|
#else
|
|
|
|
static void *dummy_variable = &dummy_variable;
|
|
|
|
#endif
|