diff --git a/sha1_file.c b/sha1_file.c
index 9fe2bd69a1edbaf1103de79d5e9d857939470d4f..9c260384201857eb32d07c87e1178fd3947968ee 100644 (file)
--- a/sha1_file.c
+++ b/sha1_file.c
@@ -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;
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;
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;
}
inflateEnd(stream);
return buf;
}
}
}
}
}
-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)
{
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;
}
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];
unsigned char *sha1)
{
char hdr[32];
int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *returnsha1)
{
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];
unsigned char *compressed;
z_stream stream;
unsigned char sha1[20];
@@ -1966,7 +1979,7 @@ int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned cha
return error("sha1 file %s: %s\n", filename, strerror(errno));
}
return error("sha1 file %s: %s\n", filename, strerror(errno));
}
- snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
+ snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory());
fd = mkstemp(tmpfile);
if (fd < 0) {
fd = mkstemp(tmpfile);
if (fd < 0) {
@@ -1994,15 +2007,21 @@ 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;
/* 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)
die("unable to write sha1 file");
fchmod(fd, 0444);
size = stream.total_out;
if (write_buffer(fd, compressed, size) < 0)
die("unable to write sha1 file");
fchmod(fd, 0444);
- close(fd);
+ if (close(fd))
+ die("unable to write sha1 file");
free(compressed);
return move_temp_to_file(tmpfile, filename);
free(compressed);
return move_temp_to_file(tmpfile, filename);
int ret;
SHA_CTX c;
int ret;
SHA_CTX c;
- snprintf(tmpfile, sizeof(tmpfile), "%s/obj_XXXXXX", get_object_directory());
+ snprintf(tmpfile, sizeof(tmpfile), "%s/tmp_obj_XXXXXX", get_object_directory());
local = mkstemp(tmpfile);
if (local < 0) {
local = mkstemp(tmpfile);
if (local < 0) {
} while (1);
inflateEnd(&stream);
} while (1);
inflateEnd(&stream);
- close(local);
+ fchmod(local, 0444);
+ if (close(local) != 0)
+ die("unable to write sha1 file");
SHA1_Final(real_sha1, &c);
if (ret != Z_STREAM_END) {
unlink(tmpfile);
SHA1_Final(real_sha1, &c);
if (ret != Z_STREAM_END) {
unlink(tmpfile);