1 #include "../git-compat-util.h"
2 
3 /*
4  * The size parameter specifies the available space, i.e. includes
5  * the trailing NUL byte; but Windows's vsnprintf uses the entire
6  * buffer and avoids the trailing NUL, should the buffer be exactly
7  * big enough for the result. Defining SNPRINTF_SIZE_CORR to 1 will
8  * therefore remove 1 byte from the reported buffer size, so we
9  * always have room for a trailing NUL byte.
10  */
11 #ifndef SNPRINTF_SIZE_CORR
12 #if defined(WIN32) && (!defined(__GNUC__) || __GNUC__ < 4) && (!defined(_MSC_VER) || _MSC_VER < 1900)
13 #define SNPRINTF_SIZE_CORR 1
14 #else
15 #define SNPRINTF_SIZE_CORR 0
16 #endif
17 #endif
18 
19 #undef vsnprintf
git_vsnprintf(char * str,size_t maxsize,const char * format,va_list ap)20 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
21 {
22 	va_list cp;
23 	char *s;
24 	int ret = -1;
25 
26 	if (maxsize > 0) {
27 		va_copy(cp, ap);
28 		ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
29 		va_end(cp);
30 		if (ret == maxsize-1)
31 			ret = -1;
32 		/* Windows does not NUL-terminate if result fills buffer */
33 		str[maxsize-1] = 0;
34 	}
35 	if (ret != -1)
36 		return ret;
37 
38 	s = NULL;
39 	if (maxsize < 128)
40 		maxsize = 128;
41 
42 	while (ret == -1) {
43 		maxsize *= 4;
44 		str = realloc(s, maxsize);
45 		if (! str)
46 			break;
47 		s = str;
48 		va_copy(cp, ap);
49 		ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, cp);
50 		va_end(cp);
51 		if (ret == maxsize-1)
52 			ret = -1;
53 	}
54 	free(s);
55 	return ret;
56 }
57 
git_snprintf(char * str,size_t maxsize,const char * format,...)58 int git_snprintf(char *str, size_t maxsize, const char *format, ...)
59 {
60 	va_list ap;
61 	int ret;
62 
63 	va_start(ap, format);
64 	ret = git_vsnprintf(str, maxsize, format, ap);
65 	va_end(ap);
66 
67 	return ret;
68 }
69 
70