зеркало из https://github.com/microsoft/git.git
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.
This commit is contained in:
Родитель
c4483576b8
Коммит
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 */
|
||||
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 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 * 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);
|
||||
|
|
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);
|
||||
}
|
||||
|
||||
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;
|
||||
z_stream stream;
|
||||
char buffer[8192];
|
||||
unsigned char *buf;
|
||||
int bytes = strlen(buffer) + 1;
|
||||
char *buf = xmalloc(1+size);
|
||||
|
||||
ret = unpack_sha1_header(&stream, map, mapsize, buffer, sizeof(buffer));
|
||||
if (ret < Z_OK || sscanf(buffer, "%10s %lu", type, size) != 2)
|
||||
return NULL;
|
||||
|
||||
bytes = strlen(buffer) + 1;
|
||||
buf = xmalloc(1+*size);
|
||||
|
||||
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)
|
||||
memcpy(buf, buffer + bytes, stream->total_out - bytes);
|
||||
bytes = stream->total_out - bytes;
|
||||
if (bytes < size) {
|
||||
stream->next_out = buf + bytes;
|
||||
stream->avail_out = size - bytes;
|
||||
while (inflate(stream, Z_FINISH) == Z_OK)
|
||||
/* nothing */;
|
||||
}
|
||||
buf[*size] = 0;
|
||||
inflateEnd(&stream);
|
||||
buf[size] = 0;
|
||||
inflateEnd(stream);
|
||||
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)
|
||||
{
|
||||
unsigned long mapsize;
|
||||
|
|
Загрузка…
Ссылка в новой задаче