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 <tanoku@gmail.com>
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131
diff --git a/src/repository.c b/src/repository.c
index e921c34..14c8f45 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 <stdarg.h>
#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 476ca54..8a37687 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