cvsserver: Introduce new state variable 'method'
[gitweb.git] / sha1_file.c
index 9fe2bd69a1edbaf1103de79d5e9d857939470d4f..940bab561254842fd50c59cf9284a8c878cb3fd8 100644 (file)
@@ -1030,14 +1030,27 @@ static void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size
                n = size;
        memcpy(buf, (char *) buffer + bytes, n);
        bytes = n;
-       if (bytes < size) {
+       if (bytes <= size) {
+               /*
+                * The above condition must be (bytes <= size), not
+                * (bytes < size).  In other words, even though we
+                * expect no more output and set avail_out to zer0,
+                * the input zlib stream may have bytes that express
+                * "this concludes the stream", and we *do* want to
+                * eat that input.
+                *
+                * Otherwise we would not be able to test that we
+                * consumed all the input to reach the expected size;
+                * we also want to check that zlib tells us that all
+                * went well with status == Z_STREAM_END at the end.
+                */
                stream->next_out = buf + bytes;
                stream->avail_out = size - bytes;
                while (status == Z_OK)
                        status = inflate(stream, Z_FINISH);
        }
        buf[size] = 0;
-       if ((status == Z_OK || status == Z_STREAM_END) && !stream->avail_in) {
+       if (status == Z_STREAM_END && !stream->avail_in) {
                inflateEnd(stream);
                return buf;
        }
@@ -1795,7 +1808,7 @@ void *read_object_with_reference(const unsigned char *sha1,
        }
 }
 
-static void write_sha1_file_prepare(void *buf, unsigned long len,
+static void write_sha1_file_prepare(const void *buf, unsigned long len,
                                     const char *type, unsigned char *sha1,
                                     char *hdr, int *hdrlen)
 {
@@ -1923,7 +1936,7 @@ static void setup_object_header(z_stream *stream, const char *type, unsigned lon
        stream->avail_out -= hdrlen;
 }
 
-int hash_sha1_file(void *buf, unsigned long len, const char *type,
+int hash_sha1_file(const void *buf, unsigned long len, const char *type,
                    unsigned char *sha1)
 {
        char hdr[32];
@@ -1934,7 +1947,7 @@ int hash_sha1_file(void *buf, unsigned long len, const char *type,
 
 int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
 {
-       int size;
+       int size, ret;
        unsigned char *compressed;
        z_stream stream;
        unsigned char sha1[20];
@@ -1994,9 +2007,14 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
        /* Then the data itself.. */
        stream.next_in = buf;
        stream.avail_in = len;
-       while (deflate(&stream, Z_FINISH) == Z_OK)
-               /* nothing */;
-       deflateEnd(&stream);
+       ret = deflate(&stream, Z_FINISH);
+       if (ret != Z_STREAM_END)
+               die("unable to deflate new object %s (%d)", sha1_to_hex(sha1), ret);
+
+       ret = deflateEnd(&stream);
+       if (ret != Z_OK)
+               die("deflateEnd on object %s failed (%d)", sha1_to_hex(sha1), ret);
+
        size = stream.total_out;
 
        if (write_buffer(fd, compressed, size) < 0)