From e802d8cca8b7fddb8ae157b84fb7c1e84671546d Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Sun, 19 Sep 2010 03:53:57 +0300 Subject: [PATCH] Implement internal methods to write on sources The new 'git__source_printf' does an overflow-safe printf on a source bfufer. The new 'git__source_write' does an overflow-safe byte write on a source buffer. Signed-off-by: Vicent Marti --- src/repository.c | 89 +++++++++++++++++++++++++++++++++++++----------- src/repository.h | 4 ++- 2 files changed, 73 insertions(+), 20 deletions(-) diff --git a/src/repository.c b/src/repository.c index e921c3454..14c8f456a 100644 --- a/src/repository.c +++ b/src/repository.c @@ -22,6 +22,7 @@ * the Free Software Foundation, 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ +#include #include "common.h" #include "repository.h" @@ -91,9 +92,77 @@ void git_repository_free(git_repository *repo) free(repo); } +static int source_resize(git_odb_source *src) +{ + size_t write_offset, new_size; + void *new_data; + + write_offset = src->write_ptr - src->raw.data; + + new_size = src->raw.len * 2; + if ((new_data = git__malloc(new_size)) == NULL) + return GIT_ENOMEM; + + memcpy(new_data, src->raw.data, src->written_bytes); + free(src->raw.data); + + src->raw.data = new_data; + src->raw.len = new_size; + src->write_ptr = new_data + write_offset; + + return GIT_SUCCESS; +} + +int git__source_printf(git_odb_source *source, const char *format, ...) +{ + va_list arglist; + int len, did_resize = 0; + + if (!source->open || source->write_ptr == NULL) + return GIT_ERROR; + + va_start(arglist, format); + + len = vsnprintf(source->write_ptr, source->raw.len - source->written_bytes, format, arglist); + + while (source->written_bytes + len >= source->raw.len) { + if (source_resize(source) < 0) + return GIT_ENOMEM; + + did_resize = 1; + } + + if (did_resize) + vsnprintf(source->write_ptr, source->raw.len - source->written_bytes, format, arglist); + + source->write_ptr += len; + source->written_bytes += len; + + return GIT_SUCCESS; +} + +int git__source_write(git_odb_source *source, const void *bytes, size_t len) +{ + assert(source); + + if (!source->open || source->write_ptr == NULL) + return GIT_ERROR; + + while (source->written_bytes + len >= source->raw.len) { + if (source_resize(source) < 0) + return GIT_ENOMEM; + } + + memcpy(source->write_ptr, bytes, len); + source->write_ptr += len; + source->written_bytes += len; + + return GIT_SUCCESS; +} + void git_object__source_prepare_write(git_object *object) { - size_t base_size = 512; + const size_t base_size = 4096; /* 4Kb base size */ if (object->source.write_ptr != NULL || object->source.open) git_object__source_close(object); @@ -109,24 +178,6 @@ void git_object__source_prepare_write(git_object *object) object->source.out_of_sync = 1; } -int git_object__source_write(git_object *object, const void *bytes, size_t len) -{ - assert(object); - - if (!object->source.open || object->source.write_ptr == NULL) - return GIT_ERROR; - - /* TODO: resize buffer on overflow */ - if (object->source.written_bytes + len >= object->source.raw.len) - return GIT_ENOMEM; - - memcpy(object->source.write_ptr, bytes, len); - object->source.write_ptr += len; - object->source.written_bytes += len; - - return GIT_SUCCESS; -} - int git_object__source_writeback(git_object *object) { int error; diff --git a/src/repository.h b/src/repository.h index 476ca546b..8a37687be 100644 --- a/src/repository.h +++ b/src/repository.h @@ -30,7 +30,9 @@ struct git_repository { int git_object__source_open(git_object *object); void git_object__source_close(git_object *object); void git_object__source_prepare_write(git_object *object); -int git_object__source_write(git_object *object, const void *bytes, size_t len); int git_object__source_writeback(git_object *object); +int git__source_printf(git_odb_source *source, const char *format, ...); +int git__source_write(git_odb_source *source, const void *bytes, size_t len); + #endif