From 5fd41ffacdef5454acbe51f5e23a97eb5158226d Mon Sep 17 00:00:00 2001 From: Johannes Sixt Date: Mon, 22 Oct 2007 14:01:27 +0200 Subject: [PATCH] Implement a work-around for a mis-behaved vsnprintf on Windows. On Windows, vsnprintf returns -1 if the buffer is too small instead of the number of characters needed. This wrapper computes the needed buffer size by trying various sizes with exponential growth. A large growth factor is used so as only few trials are required if a really large result needs to be stored. Signed-off-by: Johannes Sixt --- compat/mingw.c | 26 ++++++++++++++++++++++++++ git-compat-util.h | 4 ++++ 2 files changed, 30 insertions(+) diff --git a/compat/mingw.c b/compat/mingw.c index 2554f19765..43eda9e174 100644 --- a/compat/mingw.c +++ b/compat/mingw.c @@ -459,3 +459,29 @@ int mingw_rename(const char *pold, const char *pnew) errno = EACCES; return -1; } + +#undef vsnprintf +/* this is out of line because it uses alloca() behind the scenes, + * which must not be called in a loop (alloca() reclaims the allocations + * only at function exit) + */ +static int try_vsnprintf(size_t size, const char *fmt, va_list args) +{ + char buf[size]; /* gcc-ism */ + return vsnprintf(buf, size, fmt, args); +} + +int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args) +{ + int len = vsnprintf(buf, size, fmt, args); + if (len >= 0) + return len; + /* ouch, buffer too small; need to compute the size */ + if (size < 250) + size = 250; + do { + size *= 4; + len = try_vsnprintf(size, fmt, args); + } while (len < 0); + return len; +} diff --git a/git-compat-util.h b/git-compat-util.h index f52ced3763..e4f643d70b 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -503,6 +503,10 @@ int git_fstat(int fd, struct stat *buf); #define lstat(x,y) git_lstat(x,y) #define stat(x,y) git_lstat(x,y) #define fstat(x,y) git_fstat(x,y) + +int mingw_vsnprintf(char *buf, size_t size, const char *fmt, va_list args); +#define vsnprintf mingw_vsnprintf + #endif /* __MINGW32__ */ #endif