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 */ | ||||
| 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; | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 Linus Torvalds
						Linus Torvalds