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:
Linus Torvalds 2005-06-02 07:57:25 -07:00
Родитель c4483576b8
Коммит 5180cacc20
2 изменённых файлов: 75 добавлений и 20 удалений

Просмотреть файл

@ -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);

Просмотреть файл

@ -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;