Merge branch 'maint'
[git] / compat / snprintf.c
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 expects the
6  * number of characters to write, and does not necessarily write the
7  * trailing NUL.
8  */
9 #ifndef SNPRINTF_SIZE_CORR
10 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ < 4
11 #define SNPRINTF_SIZE_CORR 1
12 #else
13 #define SNPRINTF_SIZE_CORR 0
14 #endif
15 #endif
16
17 #undef vsnprintf
18 int git_vsnprintf(char *str, size_t maxsize, const char *format, va_list ap)
19 {
20         char *s;
21         int ret = -1;
22
23         if (maxsize > 0) {
24                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
25                 if (ret == maxsize-1)
26                         ret = -1;
27                 /* Windows does not NUL-terminate if result fills buffer */
28                 str[maxsize-1] = 0;
29         }
30         if (ret != -1)
31                 return ret;
32
33         s = NULL;
34         if (maxsize < 128)
35                 maxsize = 128;
36
37         while (ret == -1) {
38                 maxsize *= 4;
39                 str = realloc(s, maxsize);
40                 if (! str)
41                         break;
42                 s = str;
43                 ret = vsnprintf(str, maxsize-SNPRINTF_SIZE_CORR, format, ap);
44                 if (ret == maxsize-1)
45                         ret = -1;
46         }
47         free(s);
48         return ret;
49 }
50
51 int git_snprintf(char *str, size_t maxsize, const char *format, ...)
52 {
53         va_list ap;
54         int ret;
55
56         va_start(ap, format);
57         ret = git_vsnprintf(str, maxsize, format, ap);
58         va_end(ap);
59
60         return ret;
61 }
62