summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/filebuf.c43
-rw-r--r--src/unix/posix.h1
-rw-r--r--src/win32/posix.c9
-rw-r--r--src/win32/posix.h1
4 files changed, 42 insertions, 12 deletions
diff --git a/src/filebuf.c b/src/filebuf.c
index acfdcd141..86a643d38 100644
--- a/src/filebuf.c
+++ b/src/filebuf.c
@@ -360,29 +360,48 @@ int git_filebuf_reserve(git_filebuf *file, void **buffer, size_t len)
int git_filebuf_printf(git_filebuf *file, const char *format, ...)
{
va_list arglist;
- size_t space_left = file->buf_size - file->buf_pos;
+ size_t space_left;
int len, error;
+ char *tmp_buffer;
- va_start(arglist, format);
- len = vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
- va_end(arglist);
+ space_left = file->buf_size - file->buf_pos;
+
+ do {
+ va_start(arglist, format);
+ len = p_vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
+ va_end(arglist);
+
+ if (len < 0)
+ return git__throw(GIT_EOSERR, "Failed to format string");
+
+ if ((size_t)len <= space_left) {
+ file->buf_pos += len;
+ return GIT_SUCCESS;
+ }
- if (len < 0 || (size_t)len >= space_left) {
if ((error = flush_buffer(file)) < GIT_SUCCESS)
return git__rethrow(error, "Failed to output to buffer");
space_left = file->buf_size - file->buf_pos;
- va_start(arglist, format);
- len = vsnprintf((char *)file->buffer + file->buf_pos, space_left, format, arglist);
- va_end(arglist);
+ } while ((size_t)len <= space_left);
- if (len < 0 || (size_t)len > file->buf_size)
- return GIT_ENOMEM;
+ tmp_buffer = git__malloc(len + 1);
+ if (!tmp_buffer)
+ return GIT_ENOMEM;
+
+ va_start(arglist, format);
+ len = p_vsnprintf(tmp_buffer, len + 1, format, arglist);
+ va_end(arglist);
+
+ if (len < 0) {
+ free(tmp_buffer);
+ return git__throw(GIT_EOSERR, "Failed to format string");
}
- file->buf_pos += len;
- return GIT_SUCCESS;
+ error = git_filebuf_write(file, tmp_buffer, len);
+ free(tmp_buffer);
+ return error;
}
diff --git a/src/unix/posix.h b/src/unix/posix.h
index d52aa095c..16daf15bd 100644
--- a/src/unix/posix.h
+++ b/src/unix/posix.h
@@ -12,5 +12,6 @@
#define p_fsync(fd) fsync(fd)
#define p_realpath(p, po) realpath(p, po)
#define p_fnmatch(p, s, f) fnmatch(p, s, f)
+#define p_vsnprintf(b, c, f, a) vsnprintf(b, c, f, a)
#endif
diff --git a/src/win32/posix.c b/src/win32/posix.c
index dfa4e1a2c..c4d9eb387 100644
--- a/src/win32/posix.c
+++ b/src/win32/posix.c
@@ -209,3 +209,12 @@ char *p_realpath(const char *orig_path, char *buffer)
return buffer;
}
+int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr)
+{
+#ifdef _MSV_VER
+ int len = _vsnprintf(buffer, count, format, argptr);
+ return (len < 0) ? _vscprintf(format, argptr) : len;
+#else /* MinGW */
+ return vsnprintf(buffer, count, format, argptr);
+#endif
+}
diff --git a/src/win32/posix.h b/src/win32/posix.h
index 503c5d874..efac68e74 100644
--- a/src/win32/posix.h
+++ b/src/win32/posix.h
@@ -23,5 +23,6 @@ extern int p_lstat(const char *file_name, struct stat *buf);
extern int p_readlink(const char *link, char *target, size_t target_len);
extern int p_hide_directory__w32(const char *path);
extern char *p_realpath(const char *orig_path, char *buffer);
+extern int p_vsnprintf(char *buffer, size_t count, const char *format, va_list argptr);
#endif