There are no callers left, and we don't want anybody to add new ones (they should use the not-unsafe version instead). So let's drop the function. Signed-off-by: Jeff King <peff@peff.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
		
			
				
	
	
		
			213 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			213 lines
		
	
	
		
			4.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
#include "git-compat-util.h"
 | 
						|
#include "chunk-format.h"
 | 
						|
#include "csum-file.h"
 | 
						|
#include "gettext.h"
 | 
						|
#include "hash.h"
 | 
						|
#include "trace2.h"
 | 
						|
 | 
						|
/*
 | 
						|
 * When writing a chunk-based file format, collect the chunks in
 | 
						|
 * an array of chunk_info structs. The size stores the _expected_
 | 
						|
 * amount of data that will be written by write_fn.
 | 
						|
 */
 | 
						|
struct chunk_info {
 | 
						|
	uint32_t id;
 | 
						|
	uint64_t size;
 | 
						|
	chunk_write_fn write_fn;
 | 
						|
 | 
						|
	const void *start;
 | 
						|
};
 | 
						|
 | 
						|
struct chunkfile {
 | 
						|
	struct hashfile *f;
 | 
						|
 | 
						|
	struct chunk_info *chunks;
 | 
						|
	size_t chunks_nr;
 | 
						|
	size_t chunks_alloc;
 | 
						|
};
 | 
						|
 | 
						|
struct chunkfile *init_chunkfile(struct hashfile *f)
 | 
						|
{
 | 
						|
	struct chunkfile *cf = xcalloc(1, sizeof(*cf));
 | 
						|
	cf->f = f;
 | 
						|
	return cf;
 | 
						|
}
 | 
						|
 | 
						|
void free_chunkfile(struct chunkfile *cf)
 | 
						|
{
 | 
						|
	if (!cf)
 | 
						|
		return;
 | 
						|
	free(cf->chunks);
 | 
						|
	free(cf);
 | 
						|
}
 | 
						|
 | 
						|
int get_num_chunks(struct chunkfile *cf)
 | 
						|
{
 | 
						|
	return cf->chunks_nr;
 | 
						|
}
 | 
						|
 | 
						|
void add_chunk(struct chunkfile *cf,
 | 
						|
	       uint32_t id,
 | 
						|
	       size_t size,
 | 
						|
	       chunk_write_fn fn)
 | 
						|
{
 | 
						|
	ALLOC_GROW(cf->chunks, cf->chunks_nr + 1, cf->chunks_alloc);
 | 
						|
 | 
						|
	cf->chunks[cf->chunks_nr].id = id;
 | 
						|
	cf->chunks[cf->chunks_nr].write_fn = fn;
 | 
						|
	cf->chunks[cf->chunks_nr].size = size;
 | 
						|
	cf->chunks_nr++;
 | 
						|
}
 | 
						|
 | 
						|
int write_chunkfile(struct chunkfile *cf, void *data)
 | 
						|
{
 | 
						|
	int i, result = 0;
 | 
						|
	uint64_t cur_offset = hashfile_total(cf->f);
 | 
						|
 | 
						|
	trace2_region_enter("chunkfile", "write", the_repository);
 | 
						|
 | 
						|
	/* Add the table of contents to the current offset */
 | 
						|
	cur_offset += (cf->chunks_nr + 1) * CHUNK_TOC_ENTRY_SIZE;
 | 
						|
 | 
						|
	for (i = 0; i < cf->chunks_nr; i++) {
 | 
						|
		hashwrite_be32(cf->f, cf->chunks[i].id);
 | 
						|
		hashwrite_be64(cf->f, cur_offset);
 | 
						|
 | 
						|
		cur_offset += cf->chunks[i].size;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Trailing entry marks the end of the chunks */
 | 
						|
	hashwrite_be32(cf->f, 0);
 | 
						|
	hashwrite_be64(cf->f, cur_offset);
 | 
						|
 | 
						|
	for (i = 0; i < cf->chunks_nr; i++) {
 | 
						|
		off_t start_offset = hashfile_total(cf->f);
 | 
						|
		result = cf->chunks[i].write_fn(cf->f, data);
 | 
						|
 | 
						|
		if (result)
 | 
						|
			goto cleanup;
 | 
						|
 | 
						|
		if (hashfile_total(cf->f) - start_offset != cf->chunks[i].size)
 | 
						|
			BUG("expected to write %"PRId64" bytes to chunk %"PRIx32", but wrote %"PRId64" instead",
 | 
						|
			    cf->chunks[i].size, cf->chunks[i].id,
 | 
						|
			    hashfile_total(cf->f) - start_offset);
 | 
						|
	}
 | 
						|
 | 
						|
cleanup:
 | 
						|
	trace2_region_leave("chunkfile", "write", the_repository);
 | 
						|
	return result;
 | 
						|
}
 | 
						|
 | 
						|
int read_table_of_contents(struct chunkfile *cf,
 | 
						|
			   const unsigned char *mfile,
 | 
						|
			   size_t mfile_size,
 | 
						|
			   uint64_t toc_offset,
 | 
						|
			   int toc_length,
 | 
						|
			   unsigned expected_alignment)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
	uint32_t chunk_id;
 | 
						|
	const unsigned char *table_of_contents = mfile + toc_offset;
 | 
						|
 | 
						|
	ALLOC_GROW(cf->chunks, toc_length, cf->chunks_alloc);
 | 
						|
 | 
						|
	while (toc_length--) {
 | 
						|
		uint64_t chunk_offset, next_chunk_offset;
 | 
						|
 | 
						|
		chunk_id = get_be32(table_of_contents);
 | 
						|
		chunk_offset = get_be64(table_of_contents + 4);
 | 
						|
 | 
						|
		if (!chunk_id) {
 | 
						|
			error(_("terminating chunk id appears earlier than expected"));
 | 
						|
			return 1;
 | 
						|
		}
 | 
						|
		if (chunk_offset % expected_alignment != 0) {
 | 
						|
			error(_("chunk id %"PRIx32" not %d-byte aligned"),
 | 
						|
			      chunk_id, expected_alignment);
 | 
						|
			return 1;
 | 
						|
		}
 | 
						|
 | 
						|
		table_of_contents += CHUNK_TOC_ENTRY_SIZE;
 | 
						|
		next_chunk_offset = get_be64(table_of_contents + 4);
 | 
						|
 | 
						|
		if (next_chunk_offset < chunk_offset ||
 | 
						|
		    next_chunk_offset > mfile_size - the_hash_algo->rawsz) {
 | 
						|
			error(_("improper chunk offset(s) %"PRIx64" and %"PRIx64""),
 | 
						|
			      chunk_offset, next_chunk_offset);
 | 
						|
			return -1;
 | 
						|
		}
 | 
						|
 | 
						|
		for (i = 0; i < cf->chunks_nr; i++) {
 | 
						|
			if (cf->chunks[i].id == chunk_id) {
 | 
						|
				error(_("duplicate chunk ID %"PRIx32" found"),
 | 
						|
					chunk_id);
 | 
						|
				return -1;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		cf->chunks[cf->chunks_nr].id = chunk_id;
 | 
						|
		cf->chunks[cf->chunks_nr].start = mfile + chunk_offset;
 | 
						|
		cf->chunks[cf->chunks_nr].size = next_chunk_offset - chunk_offset;
 | 
						|
		cf->chunks_nr++;
 | 
						|
	}
 | 
						|
 | 
						|
	chunk_id = get_be32(table_of_contents);
 | 
						|
	if (chunk_id) {
 | 
						|
		error(_("final chunk has non-zero id %"PRIx32""), chunk_id);
 | 
						|
		return -1;
 | 
						|
	}
 | 
						|
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
struct pair_chunk_data {
 | 
						|
	const unsigned char **p;
 | 
						|
	size_t *size;
 | 
						|
};
 | 
						|
 | 
						|
static int pair_chunk_fn(const unsigned char *chunk_start,
 | 
						|
			 size_t chunk_size,
 | 
						|
			 void *data)
 | 
						|
{
 | 
						|
	struct pair_chunk_data *pcd = data;
 | 
						|
	*pcd->p = chunk_start;
 | 
						|
	*pcd->size = chunk_size;
 | 
						|
	return 0;
 | 
						|
}
 | 
						|
 | 
						|
int pair_chunk(struct chunkfile *cf,
 | 
						|
	       uint32_t chunk_id,
 | 
						|
	       const unsigned char **p,
 | 
						|
	       size_t *size)
 | 
						|
{
 | 
						|
	struct pair_chunk_data pcd = { .p = p, .size = size };
 | 
						|
	return read_chunk(cf, chunk_id, pair_chunk_fn, &pcd);
 | 
						|
}
 | 
						|
 | 
						|
int read_chunk(struct chunkfile *cf,
 | 
						|
	       uint32_t chunk_id,
 | 
						|
	       chunk_read_fn fn,
 | 
						|
	       void *data)
 | 
						|
{
 | 
						|
	int i;
 | 
						|
 | 
						|
	for (i = 0; i < cf->chunks_nr; i++) {
 | 
						|
		if (cf->chunks[i].id == chunk_id)
 | 
						|
			return fn(cf->chunks[i].start, cf->chunks[i].size, data);
 | 
						|
	}
 | 
						|
 | 
						|
	return CHUNK_NOT_FOUND;
 | 
						|
}
 | 
						|
 | 
						|
uint8_t oid_version(const struct git_hash_algo *algop)
 | 
						|
{
 | 
						|
	switch (hash_algo_by_ptr(algop)) {
 | 
						|
	case GIT_HASH_SHA1:
 | 
						|
		return 1;
 | 
						|
	case GIT_HASH_SHA256:
 | 
						|
		return 2;
 | 
						|
	default:
 | 
						|
		die(_("invalid hash version"));
 | 
						|
	}
 | 
						|
}
 |