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 <johannes.sixt@telecom.at>
This commit is contained in:
Johannes Sixt
2007-10-22 14:01:27 +02:00
parent 2671981e99
commit 5fd41ffacd
2 changed files with 30 additions and 0 deletions

View File

@@ -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;
}

View File

@@ -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