Split up unpack_sha1_file() some more
Make a separate helper for parsing the header of an object file (really carefully) and for unpacking the rest. This means that anybody who uses the "unpack_sha1_header()" interface can easily look at the header and decide to unpack the rest too, without doing any extra work.maint
parent
c4483576b8
commit
5180cacc20
1
cache.h
1
cache.h
|
@ -152,6 +152,7 @@ extern char *sha1_file_name(const unsigned char *sha1);
|
||||||
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
/* Read and unpack a sha1 file into memory, write memory to a sha1 file */
|
||||||
extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
|
extern void * map_sha1_file(const unsigned char *sha1, unsigned long *size);
|
||||||
extern int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size);
|
extern int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void *buffer, unsigned long size);
|
||||||
|
extern int parse_sha1_header(char *hdr, char *type, unsigned long *sizep);
|
||||||
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
|
extern void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size);
|
||||||
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
|
extern void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size);
|
||||||
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
|
extern int write_sha1_file(void *buf, unsigned long len, const char *type, unsigned char *return_sha1);
|
||||||
|
|
94
sha1_file.c
94
sha1_file.c
|
@ -320,33 +320,87 @@ int unpack_sha1_header(z_stream *stream, void *map, unsigned long mapsize, void
|
||||||
return inflate(stream, 0);
|
return inflate(stream, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)
|
void *unpack_sha1_rest(z_stream *stream, void *buffer, unsigned long size)
|
||||||
{
|
{
|
||||||
int ret, bytes;
|
int bytes = strlen(buffer) + 1;
|
||||||
z_stream stream;
|
char *buf = xmalloc(1+size);
|
||||||
char buffer[8192];
|
|
||||||
unsigned char *buf;
|
|
||||||
|
|
||||||
ret = unpack_sha1_header(&stream, map, mapsize, buffer, sizeof(buffer));
|
memcpy(buf, buffer + bytes, stream->total_out - bytes);
|
||||||
if (ret < Z_OK || sscanf(buffer, "%10s %lu", type, size) != 2)
|
bytes = stream->total_out - bytes;
|
||||||
return NULL;
|
if (bytes < size) {
|
||||||
|
stream->next_out = buf + bytes;
|
||||||
bytes = strlen(buffer) + 1;
|
stream->avail_out = size - bytes;
|
||||||
buf = xmalloc(1+*size);
|
while (inflate(stream, Z_FINISH) == Z_OK)
|
||||||
|
|
||||||
memcpy(buf, buffer + bytes, stream.total_out - bytes);
|
|
||||||
bytes = stream.total_out - bytes;
|
|
||||||
if (bytes < *size && ret == Z_OK) {
|
|
||||||
stream.next_out = buf + bytes;
|
|
||||||
stream.avail_out = *size - bytes;
|
|
||||||
while (inflate(&stream, Z_FINISH) == Z_OK)
|
|
||||||
/* nothing */;
|
/* nothing */;
|
||||||
}
|
}
|
||||||
buf[*size] = 0;
|
buf[size] = 0;
|
||||||
inflateEnd(&stream);
|
inflateEnd(stream);
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We used to just use "sscanf()", but that's actually way
|
||||||
|
* too permissive for what we want to check. So do an anal
|
||||||
|
* object header parse by hand.
|
||||||
|
*/
|
||||||
|
int parse_sha1_header(char *hdr, char *type, unsigned long *sizep)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
unsigned long size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The type can be at most ten bytes (including the
|
||||||
|
* terminating '\0' that we add), and is followed by
|
||||||
|
* a space.
|
||||||
|
*/
|
||||||
|
i = 10;
|
||||||
|
for (;;) {
|
||||||
|
char c = *hdr++;
|
||||||
|
if (c == ' ')
|
||||||
|
break;
|
||||||
|
if (!--i)
|
||||||
|
return -1;
|
||||||
|
*type++ = c;
|
||||||
|
}
|
||||||
|
*type = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The length must follow immediately, and be in canonical
|
||||||
|
* decimal format (ie "010" is not valid).
|
||||||
|
*/
|
||||||
|
size = *hdr++ - '0';
|
||||||
|
if (size > 9)
|
||||||
|
return -1;
|
||||||
|
if (size) {
|
||||||
|
for (;;) {
|
||||||
|
unsigned long c = *hdr - '0';
|
||||||
|
if (c > 9)
|
||||||
|
break;
|
||||||
|
hdr++;
|
||||||
|
size = size * 10 + c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*sizep = size;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The length must be followed by a zero byte
|
||||||
|
*/
|
||||||
|
return *hdr ? -1 : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void * unpack_sha1_file(void *map, unsigned long mapsize, char *type, unsigned long *size)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
z_stream stream;
|
||||||
|
char hdr[8192];
|
||||||
|
|
||||||
|
ret = unpack_sha1_header(&stream, map, mapsize, hdr, sizeof(hdr));
|
||||||
|
if (ret < Z_OK || parse_sha1_header(hdr, type, size) < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return unpack_sha1_rest(&stream, hdr, *size);
|
||||||
|
}
|
||||||
|
|
||||||
void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
|
void * read_sha1_file(const unsigned char *sha1, char *type, unsigned long *size)
|
||||||
{
|
{
|
||||||
unsigned long mapsize;
|
unsigned long mapsize;
|
||||||
|
|
Loading…
Reference in New Issue